Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import SimpleSchema from "simpl-schema";
import Logger from "@reactioncommerce/logger";
import Random from "@reactioncommerce/random";
import ReactionError from "@reactioncommerce/reaction-error";
import { xformCartCheckout } from "@reactioncommerce/reaction-graphql-xforms/cart";
import hashLoginToken from "/imports/node-app/core/util/hashLoginToken";
import appEvents from "/imports/node-app/core/util/appEvents";
import getFulfillmentGroupItemsWithTaxAdded from "/imports/plugins/core/taxes/server/no-meteor/mutations/getFulfillmentGroupItemsWithTaxAdded";
import { Order as OrderSchema, Payment as PaymentSchema } from "/imports/collections/schemas";
import getDiscountsTotalForCart from "/imports/plugins/core/discounts/server/no-meteor/util/getDiscountsTotalForCart";
import getCartById from "/imports/plugins/core/shipping/server/no-meteor/util/getCartById.js";


const orderItemsSchema = new SimpleSchema({
"addedAt": {
Expand Down Expand Up @@ -236,7 +239,7 @@ export default async function createOrder(context, input) {
inputSchema.validate(cleanedInput);

const { afterValidate, createPaymentForFulfillmentGroup, order: orderInput } = cleanedInput;
const { cartId, currencyCode, email, fulfillmentGroups, shopId } = orderInput;
const { cartId, cartToken, currencyCode, email, fulfillmentGroups, shopId } = orderInput;
const { accountId, account, collections } = context;
const { Orders } = collections;

Expand All @@ -256,9 +259,11 @@ export default async function createOrder(context, input) {
workflow: { status: "new", workflow: ["coreOrderWorkflow/notStarted"] }
};

const cart = await getCartById(context, cartId, { cartToken, throwIfNotFound: true });
const cartWithSummary = await xformCartCheckout(collections, cart);
// Verify that the price for the chosen shipment method on each group matches between what the client
// provided and what the current quote is.
const rates = await context.queries.getFulfillmentMethodsWithQuotes(finalGroup, context);
const rates = await context.queries.getFulfillmentMethodsWithQuotes(finalGroup, cartWithSummary, context);
const selectedFulfillmentMethod = rates.find((rate) => groupInput.selectedFulfillmentMethodId === rate.method._id);
if (!selectedFulfillmentMethod) {
throw new ReactionError("invalid", "The selected fulfillment method is no longer available." +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test("add a flat rate fulfillment restriction", async () => {
restriction: {
type: "deny",
attributes: [
{ property: "vendor", value: "erik", propertyType: "string", operator: "eq" },
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] }
Expand All @@ -26,7 +26,7 @@ test("add a flat rate fulfillment restriction", async () => {
restriction: {
type: "deny",
attributes: [
{ property: "vendor", value: "erik", propertyType: "string", operator: "eq" },
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mockContext.userHasPermission.mockReturnValueOnce(true);
const value = {
type: "deny",
attributes: [
{ property: "vendor", value: "erik", propertyType: "string", operator: "eq" },
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] }
Expand All @@ -30,7 +30,7 @@ test("delete a flat rate fulfillment restriction", async () => {
restriction: {
type: "deny",
attributes: [
{ property: "vendor", value: "erik", propertyType: "string", operator: "eq" },
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { getConnectionTypeResolvers } from "@reactioncommerce/reaction-graphql-utils";
import FlatRateFulfillmentRestriction from "./FlatRateFulfillmentRestriction";
import Mutation from "./Mutation";
import Query from "./Query";

export default {
...getConnectionTypeResolvers("FlatRateFulfillmentRestriction"),
FlatRateFulfillmentRestriction,
Mutation,
Query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default async function getShippingRestrictionAttributes(context, cartWith
const allProductsTags = await tagsByIds(collections, catalogProductsAndVariants);

for (const orderLineItem of orderItems) {
const productAndVariants = catalogProductsAndVariants.find((catProduct) => catProduct.product.productId === orderLineItem.productId);
const productAndVariants = catalogProductsAndVariants.find((catProduct) => catProduct.product.productId === orderLineItem.productId || orderLineItem.productConfiguration.productId);

if (!productAndVariants) {
throw new ReactionError("not-found", "Catalog product not found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import _ from "lodash";
*/
export async function findCatalogProductsAndVariants(collections, orderLineItems) {
const { Catalog } = collections;
const productIds = orderLineItems.map((orderLineItem) => orderLineItem.productId);
const productIds = orderLineItems.map((orderLineItem) => orderLineItem.productId || orderLineItem.productConfiguration.productId);

const catalogProductItems = await Catalog.find({
"product.productId": { $in: productIds },
Expand All @@ -21,7 +21,7 @@ export async function findCatalogProductsAndVariants(collections, orderLineItems

const catalogProductsAndVariants = catalogProductItems.map((catalogProduct) => {
const { product } = catalogProduct;
const orderedVariant = orderLineItems.find((item) => item.productId === product.productId);
const orderedVariant = orderLineItems.find((item) => product.productId === item.productId || item.productConfiguration.productId);

const { parentVariant, variant } = findVariantInCatalogProduct(product, orderedVariant.variantId);

Expand Down
24 changes: 24 additions & 0 deletions imports/plugins/included/surcharges/register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Reaction from "/imports/plugins/core/core/server/Reaction";
import getFulfillmentSurchargesWithQuotes from "./server/no-meteor/getFulfillmentSurchargesWithQuotes";
import resolvers from "./server/no-meteor/resolvers";
import mutations from "./server/no-meteor/mutations";
import queries from "./server/no-meteor/queries";
import schemas from "./server/no-meteor/schemas";
import startup from "./server/no-meteor/startup";

Reaction.registerPackage({
label: "Surcharges",
name: "reaction-surcharges",
icon: "fa fa-icon-money",
autoEnable: true,
graphQL: {
resolvers,
schemas
},
mutations,
queries,
functionsByType: {
getFulfillmentSurchargesWithQuotes: [getFulfillmentSurchargesWithQuotes],
startup: [startup]
}
});
9 changes: 9 additions & 0 deletions imports/plugins/included/surcharges/server/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[{
"i18n": "en",
"ns": "reaction-surcharges",
"translation": {
"reaction-surcharges": {
"admin": {}
}
}
}]
10 changes: 10 additions & 0 deletions imports/plugins/included/surcharges/server/i18n/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { loadTranslations } from "/imports/plugins/core/core/server/startup/i18n";

import en from "./en.json";

//
// we want all the files in individual
// imports for easier handling by
// automated translation software
//
loadTranslations([en]);
1 change: 1 addition & 0 deletions imports/plugins/included/surcharges/server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./i18n";
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @name getSurchargesCollection
* @summary Get shipping surcharges collection from Mongo
* @param {Object} context - an object containing the per-request state
* @returns {Object|null} shipping surcharges collection for the provided fulfillment group
*/
export function getSurchargesCollection(context) {
return context.app.db.collection("Surcharges");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import SimpleSchema from "simpl-schema";
import Random from "@reactioncommerce/random";
import ReactionError from "@reactioncommerce/reaction-error";
import surchargeSchema from "../util/surchargeSchema";

const inputSchema = new SimpleSchema({
surcharge: surchargeSchema,
shopId: String
});

/**
* @method createSurchargeMutation
* @summary Creates a surcharge
* @param {Object} context - an object containing the per-request state
* @param {Object} input - Input (see SimpleSchema)
* @return {Promise<Object>} An object with a `surcharge` property containing the created surcharge
*/
export default async function createSurchargeMutation(context, input) {
const cleanedInput = inputSchema.clean(input); // add default values and such
inputSchema.validate(cleanedInput);

const { surcharge, shopId } = cleanedInput;
const { collections, userHasPermission } = context;
const { Surcharges } = collections;

if (!userHasPermission(["admin", "owner", "shipping"], shopId)) {
throw new ReactionError("access-denied", "Access Denied");
}

const { insertedCount } = await Surcharges.insertOne({
_id: Random.id(),
shopId,
...surcharge
});
if (insertedCount === 0) throw new ReactionError("server-error", "Unable to create surcharge");

return { surcharge };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import mockContext, { mockCollection } from "/imports/test-utils/helpers/mockContext";
import createSurchargeMutation from "./createSurcharge";


// Create mock context with Surcharges collection
mockContext.collections.Surcharges = mockCollection("Surcharges");
mockContext.userHasPermission.mockReturnValueOnce(true);

test("add a surcharge", async () => {
mockContext.collections.Surcharges.insertOne.mockReturnValueOnce(Promise.resolve({}));

const result = await createSurchargeMutation(mockContext, {
_id: "surcharge123",
shopId: "shop123",
surcharge: {
type: "surcharge",
attributes: [
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] },
surcharges: [
{
amount: "19.99",
message: "You are shipping hazardous items, there is a 19.99 surcharge",
reason: "An item meets a surcharge restriction"
}
]
}
});

expect(result).toEqual({
surcharge: {
type: "surcharge",
attributes: [
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] },
surcharges: [
{
amount: "19.99",
message: "You are shipping hazardous items, there is a 19.99 surcharge",
reason: "An item meets a surcharge restriction"
}
]
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import SimpleSchema from "simpl-schema";
import ReactionError from "@reactioncommerce/reaction-error";

const inputSchema = new SimpleSchema({
surchargeId: String,
shopId: String
});

/**
* @method deleteSurcharge
* @summary deletes a surcharge
* @param {Object} context - an object containing the per-request state
* @param {Object} input - Input (see SimpleSchema)
* @return {Promise<Object>} An object with a `surcharge` property containing the deleted surcharge
*/
export default async function deleteSurcharge(context, input) {
inputSchema.validate(input);

const { surchargeId, shopId } = input;
const { collections, userHasPermission } = context;
const { Surcharges } = collections;

if (!userHasPermission(["admin", "owner", "shipping"], shopId)) {
throw new ReactionError("access-denied", "Access Denied");
}

const { ok, value } = await Surcharges.findOneAndDelete({
_id: surchargeId,
shopId
});
if (ok !== 1) throw new ReactionError("not-found", "Not found");

return { surcharge: value };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import mockContext, { mockCollection } from "/imports/test-utils/helpers/mockContext";
import deleteSurchargeMutation from "./deleteSurcharge";


// Create mock context with Surcharges collection
mockContext.collections.Surcharges = mockCollection("Surcharges");
mockContext.userHasPermission.mockReturnValueOnce(true);

const value = {
type: "surcharge",
attributes: [
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] },
surcharges: [{
amount: 19.99,
reason: "Hazardous items",
message: "A surcharge will apply to this shipment because of a hazardous item."
}]
};

test("delete a surcharge", async () => {
mockContext.collections.Surcharges.findOneAndDelete.mockReturnValueOnce(Promise.resolve({
ok: 1,
value
}));

const result = await deleteSurchargeMutation(mockContext, {
surchargeId: "surcharge123",
shopId: "shop123"
});

expect(result).toEqual({
surcharge: {
type: "surcharge",
attributes: [
{ property: "vendor", value: "reaction", propertyType: "string", operator: "eq" },
{ property: "productType", value: "knife", propertyType: "string", operator: "eq" }
],
destination: { region: ["CO", "NY"] },
surcharges: [{
amount: 19.99,
reason: "Hazardous items",
message: "A surcharge will apply to this shipment because of a hazardous item."
}]
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import createSurcharge from "./createSurcharge";
import deleteSurcharge from "./deleteSurcharge";
import updateSurcharge from "./updateSurcharge";

export default {
createSurcharge,
deleteSurcharge,
updateSurcharge
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import SimpleSchema from "simpl-schema";
import ReactionError from "@reactioncommerce/reaction-error";
import surchargeSchema from "../util/surchargeSchema";

const inputSchema = new SimpleSchema({
surcharge: surchargeSchema,
shopId: String
});


/**
* @method updateSurchargeMutation
* @summary updates a surcharge
* @param {Object} context - an object containing the per-request state
* @param {Object} input - Input (see SimpleSchema)
* @return {Promise<Object>} An object with a `surcharge` property containing the updated surcharge
*/
export default async function updateSurchargeMutation(context, input) {
const cleanedInput = inputSchema.clean(input); // add default values and such
inputSchema.validate(cleanedInput);

const { surcharge, surchargeId, shopId } = cleanedInput;
const { collections, userHasPermission } = context;
const { Surcharges } = collections;

if (!userHasPermission(["admin", "owner", "shipping"], shopId)) {
throw new ReactionError("access-denied", "Access Denied");
}

const { matchedCount } = await Surcharges.updateOne({
_id: surchargeId,
shopId
}, {
$set: {
_id: surchargeId,
...surcharge
}
});
if (matchedCount === 0) throw new ReactionError("not-found", "Not found");

return { surcharge };
}
Loading