diff --git a/jest.config.cjs b/jest.config.cjs index 9f68328d4e4..e57f3fba8c0 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -25,6 +25,7 @@ const externalNodeModules = [ "@reactioncommerce/api-plugin-settings", "@reactioncommerce/api-plugin-simple-schema", "@reactioncommerce/api-plugin-shops", + "@reactioncommerce/api-plugin-surcharges", "@reactioncommerce/api-plugin-tags", "@reactioncommerce/api-utils", "@reactioncommerce/db-version-check", diff --git a/package-lock.json b/package-lock.json index 0d6cbd7fa54..cb114c7a838 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1801,6 +1801,43 @@ "@reactioncommerce/api-utils": "^1.9.0" } }, + "@reactioncommerce/api-plugin-surcharges": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@reactioncommerce/api-plugin-surcharges/-/api-plugin-surcharges-1.0.0.tgz", + "integrity": "sha512-ue9Er3z/7J7klAG8AQGpyxeQs1Ts9UpCUblCGK4HM47O5Dn2JhTBNqIYccYDWKHzl25Va3o/dRT4Usjto3OBOA==", + "requires": { + "@reactioncommerce/api-utils": "^1.12.0", + "@reactioncommerce/random": "^1.0.2", + "@reactioncommerce/reaction-error": "^1.0.1", + "lodash": "^4.17.15", + "simpl-schema": "^1.5.7" + }, + "dependencies": { + "@reactioncommerce/api-utils": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@reactioncommerce/api-utils/-/api-utils-1.12.0.tgz", + "integrity": "sha512-5zePbau5ERFeD47xPclSmloinOPZzainxfAVghCetPVBdCxabH0EgAQ/uaHcZ4KDXrQRU80NxZ9yxTeiZrZRpQ==", + "requires": { + "@reactioncommerce/logger": "^1.1.3", + "@reactioncommerce/random": "^1.0.2", + "@reactioncommerce/reaction-error": "^1.0.1", + "accounting-js": "^1.1.1", + "callsite": "^1.0.0", + "graphql": "^14.6.0", + "graphql-fields": "^2.0.3", + "graphql-relay": "^0.6.0", + "lodash": "^4.17.15", + "ramda": "^0.27.0", + "transliteration": "^2.1.8" + } + }, + "ramda": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", + "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==" + } + } + }, "@reactioncommerce/api-plugin-tags": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@reactioncommerce/api-plugin-tags/-/api-plugin-tags-1.0.0.tgz", diff --git a/package.json b/package.json index abfa5fdc2f4..1653a3dc2a3 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@reactioncommerce/api-plugin-accounts": "~1.2.0", "@reactioncommerce/api-plugin-address-validation": "~1.3.0", "@reactioncommerce/api-plugin-address-validation-test": "~1.0.0", - "@reactioncommerce/api-plugin-carts": "^1.0.0", + "@reactioncommerce/api-plugin-carts": "~1.0.0", "@reactioncommerce/api-plugin-catalogs": "~1.0.0", "@reactioncommerce/api-plugin-discounts": "~1.0.0", "@reactioncommerce/api-plugin-email": "~1.0.0", @@ -41,6 +41,7 @@ "@reactioncommerce/api-plugin-settings": "~1.0.0", "@reactioncommerce/api-plugin-shops": "~1.0.0", "@reactioncommerce/api-plugin-simple-schema": "~1.0.0", + "@reactioncommerce/api-plugin-surcharges": "~1.0.0", "@reactioncommerce/api-plugin-tags": "~1.0.0", "@reactioncommerce/api-utils": "~1.10.0", "@reactioncommerce/db-version-check": "~1.0.0", diff --git a/plugins.json b/plugins.json index 4b21a7f9841..928831a930d 100644 --- a/plugins.json +++ b/plugins.json @@ -30,7 +30,7 @@ "simpleSchema": "@reactioncommerce/api-plugin-simple-schema", "sitemapGenerator": "@reactioncommerce/plugin-sitemap-generator", "stripePayments": "@reactioncommerce/api-plugin-payments-stripe", - "surcharges": "./src/plugins/surcharges/index.js", + "surcharges": "@reactioncommerce/api-plugin-surcharges", "systemInfo": "@reactioncommerce/plugin-system-information", "tags": "@reactioncommerce/api-plugin-tags", "taxes": "./src/core-services/taxes/index.js", diff --git a/src/plugins/surcharges/getSurcharges.js b/src/plugins/surcharges/getSurcharges.js deleted file mode 100644 index 74cf71c22a4..00000000000 --- a/src/plugins/surcharges/getSurcharges.js +++ /dev/null @@ -1,71 +0,0 @@ -import Random from "@reactioncommerce/random"; -import extendCommonOrder from "../../core-services/shipping/util/extendCommonOrder.js"; // TODO: remove cross-plugin import (https://github.com/reactioncommerce/reaction/issues/5633) -import { surchargeCheck } from "./util/surchargeCheck.js"; - - -/** - * @summary Returns a list of surcharges to apply based on the cart. - * @param {Object} context - Context - * @param {Object} input - Additional input - * @param {Object} input.commonOrder - CommonOrder - * @returns {Array} - an array that surcharges to apply to cart / order - * @private - */ -export default async function getSurcharges(context, { commonOrder }) { - const { collections: { Surcharges } } = context; - - // Get surcharges from Mongo - // Use forEach to use Mongos built in memory handling to not - // overload memory while fetching the entire collection - const surcharges = []; - await Surcharges.find({ shopId: commonOrder.shopId }).forEach((surcharge) => { - surcharges.push(surcharge); - }); - - if (surcharges.length === 0) return []; - - // Keep this after the early exit since this hits the DB a bunch and isn't needed - // when there are no surcharges defined. - const extendedCommonOrder = await extendCommonOrder(context, commonOrder); - - const allAppliedSurcharges = await surcharges.reduce(async (appliedSurcharges, surcharge) => { - const awaitedAppliedSurcharges = await appliedSurcharges; - - const { methodIds } = surcharge; - const { fulfillmentMethodId } = extendedCommonOrder; - - // Check to see if surcharge has methodIds attached to it. - // If it doesn't, this surcharge can apply to any fulfillmentMethod - if (Array.isArray(methodIds) && methodIds.length > 0) { - // If surcharge has methodIds attached to it, and fulfillmentMethodId is not yet set, - // don't apply any surcharges at this time - if (!fulfillmentMethodId) return awaitedAppliedSurcharges; - - // If surcharge has methodIds attached to it, and fulfillmentMethodId is set, - // check to see if surcharge applies to this methodId. - // If not, don't apply surcharge. - if (!methodIds.includes(fulfillmentMethodId)) return awaitedAppliedSurcharges; - } - - const applySurcharge = await surchargeCheck(surcharge, extendedCommonOrder); - - // If surcharge passes all checks, it is valid and should be added to valid surcharges array - if (applySurcharge) { - awaitedAppliedSurcharges.push(surcharge); - } - - return awaitedAppliedSurcharges; - }, Promise.resolve([])); - - // We don't need all data to be passed to Cart / Order - // Parse provided surcharge data to pass only relevant data to match Cart / Order schema - const appliedSurchargesFormattedForFulfillment = allAppliedSurcharges.map((surcharge) => ({ - _id: Random.id(), - surchargeId: surcharge._id, - amount: surcharge.amount, - messagesByLanguage: surcharge.messagesByLanguage, - cartId: commonOrder.cartId - })); - - return appliedSurchargesFormattedForFulfillment; -} diff --git a/src/plugins/surcharges/index.js b/src/plugins/surcharges/index.js deleted file mode 100644 index 5ef409b976a..00000000000 --- a/src/plugins/surcharges/index.js +++ /dev/null @@ -1,47 +0,0 @@ -import getSurcharges from "./getSurcharges.js"; -import mutations from "./mutations/index.js"; -import policies from "./policies.json"; -import queries from "./queries/index.js"; -import resolvers from "./resolvers/index.js"; -import schemas from "./schemas/index.js"; -import setSurchargesOnCart from "./util/setSurchargesOnCart.js"; - -/** - * @summary Import and call this function to add this plugin to your API. - * @param {ReactionAPI} app The ReactionAPI instance - * @returns {undefined} - */ -export default async function register(app) { - await app.registerPlugin({ - label: "Surcharges", - name: "reaction-surcharges", - version: app.context.appVersion, - collections: { - Surcharges: { - name: "Surcharges", - indexes: [ - [{ shopId: 1 }] - ] - } - }, - graphQL: { - resolvers, - schemas - }, - mutations, - policies, - queries, - functionsByType: { - getSurcharges: [getSurcharges] - }, - cart: { - transforms: [ - { - name: "setSurchargesOnCart", - fn: setSurchargesOnCart, - priority: 20 - } - ] - } - }); -} diff --git a/src/plugins/surcharges/mutations/createSurcharge.js b/src/plugins/surcharges/mutations/createSurcharge.js deleted file mode 100644 index af1279640f2..00000000000 --- a/src/plugins/surcharges/mutations/createSurcharge.js +++ /dev/null @@ -1,37 +0,0 @@ -import SimpleSchema from "simpl-schema"; -import Random from "@reactioncommerce/random"; -import ReactionError from "@reactioncommerce/reaction-error"; -import surchargeSchema from "../util/surchargeSchema.js"; - -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) - * @returns {Promise} 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 } = context; - const { Surcharges } = collections; - - await context.validatePermissions("reaction:legacy:surcharges", "create", { shopId }); - - surcharge._id = Random.id(); - surcharge.shopId = shopId; - surcharge.createdAt = new Date(); - - - const { insertedCount } = await Surcharges.insertOne(surcharge); - if (insertedCount === 0) throw new ReactionError("server-error", "Unable to create surcharge"); - - return { surcharge }; -} diff --git a/src/plugins/surcharges/mutations/createSurcharge.test.js b/src/plugins/surcharges/mutations/createSurcharge.test.js deleted file mode 100644 index 668fd2ba4d5..00000000000 --- a/src/plugins/surcharges/mutations/createSurcharge.test.js +++ /dev/null @@ -1,48 +0,0 @@ -import mockCollection from "@reactioncommerce/api-utils/tests/mockCollection.js"; -import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; -import createSurchargeMutation from "./createSurcharge.js"; - - -// Create mock context with Surcharges collection -mockContext.collections.Surcharges = mockCollection("Surcharges"); -mockContext.validatePermissions.mockReturnValueOnce(Promise.resolve(null)); - -const surchargeAttributes = [ - { property: "vendor", value: "reaction", propertyType: "string", operator: "eq" }, - { property: "productType", value: "knife", propertyType: "string", operator: "eq" } -]; - -const surchargeMessagesByLanguage = [ - { - content: "You are shipping hazardous items, there is a 19.99 surcharge", - language: "en" - }, { - content: "Spanish - You are shipping hazardous items, there is a 19.99 surcharge", - language: "es" - } -]; - -const surchargeDestination = { region: ["CO", "NY"] }; - -test("add a surcharge", async () => { - mockContext.collections.Surcharges.insertOne.mockReturnValueOnce(Promise.resolve({})); - - const result = await createSurchargeMutation(mockContext, { - shopId: "shop123", - surcharge: { - amount: 19.99, - messagesByLanguage: surchargeMessagesByLanguage, - type: "surcharge", - attributes: surchargeAttributes, - destination: surchargeDestination - } - }); - - expect(result.surcharge.shopId).toEqual("shop123"); - expect(result.surcharge.amount).toEqual(19.99); - expect(result.surcharge.messagesByLanguage).toEqual(surchargeMessagesByLanguage); - expect(result.surcharge.attributes).toEqual(surchargeAttributes); - expect(result.surcharge.destination).toEqual(surchargeDestination); - expect(typeof result.surcharge._id).toEqual("string"); - expect(typeof result.surcharge.createdAt).toEqual("object"); -}); diff --git a/src/plugins/surcharges/mutations/deleteSurcharge.js b/src/plugins/surcharges/mutations/deleteSurcharge.js deleted file mode 100644 index e1f0bbbef81..00000000000 --- a/src/plugins/surcharges/mutations/deleteSurcharge.js +++ /dev/null @@ -1,32 +0,0 @@ -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) - * @returns {Promise} 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 } = context; - const { Surcharges } = collections; - - await context.validatePermissions(`reaction:legacy:surcharges:${surchargeId}`, "delete", { shopId }); - - const { ok, value } = await Surcharges.findOneAndDelete({ - _id: surchargeId, - shopId - }); - if (ok !== 1) throw new ReactionError("not-found", "Not found"); - - return { surcharge: value }; -} diff --git a/src/plugins/surcharges/mutations/deleteSurcharge.test.js b/src/plugins/surcharges/mutations/deleteSurcharge.test.js deleted file mode 100644 index 14d8bc47ac5..00000000000 --- a/src/plugins/surcharges/mutations/deleteSurcharge.test.js +++ /dev/null @@ -1,52 +0,0 @@ -import mockCollection from "@reactioncommerce/api-utils/tests/mockCollection.js"; -import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; -import deleteSurchargeMutation from "./deleteSurcharge.js"; - - -// Create mock context with Surcharges collection -mockContext.collections.Surcharges = mockCollection("Surcharges"); -mockContext.validatePermissions.mockReturnValueOnce(Promise.resolve(null)); - -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"] }, - amount: { - amount: 19.99, - currencyCode: "USD" - }, - 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"] }, - amount: { - amount: 19.99, - currencyCode: "USD" - }, - reason: "Hazardous items", - message: "A surcharge will apply to this shipment because of a hazardous item." - } - }); -}); diff --git a/src/plugins/surcharges/mutations/index.js b/src/plugins/surcharges/mutations/index.js deleted file mode 100644 index fc4143b0628..00000000000 --- a/src/plugins/surcharges/mutations/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import createSurcharge from "./createSurcharge.js"; -import deleteSurcharge from "./deleteSurcharge.js"; -import updateSurcharge from "./updateSurcharge.js"; - -export default { - createSurcharge, - deleteSurcharge, - updateSurcharge -}; diff --git a/src/plugins/surcharges/mutations/updateSurcharge.js b/src/plugins/surcharges/mutations/updateSurcharge.js deleted file mode 100644 index 4d7d7443d52..00000000000 --- a/src/plugins/surcharges/mutations/updateSurcharge.js +++ /dev/null @@ -1,43 +0,0 @@ -import SimpleSchema from "simpl-schema"; -import ReactionError from "@reactioncommerce/reaction-error"; -import surchargeSchema from "../util/surchargeSchema.js"; - -const inputSchema = new SimpleSchema({ - shopId: String, - surcharge: surchargeSchema, - surchargeId: String -}); - - -/** - * @method updateSurchargeMutation - * @summary updates a surcharge - * @param {Object} context - an object containing the per-request state - * @param {Object} input - Input (see SimpleSchema) - * @returns {Promise} 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 } = context; - const { Surcharges } = collections; - - await context.validatePermissions(`reaction:legacy:surcharges:${surchargeId}`, "update", { shopId }); - - const { matchedCount } = await Surcharges.updateOne({ - _id: surchargeId, - shopId - }, { - $set: { - updatedAt: new Date(), - ...surcharge - } - }); - surcharge._id = surchargeId; - surcharge.shopId = shopId; - if (matchedCount === 0) throw new ReactionError("not-found", "Not found"); - - return { surcharge }; -} diff --git a/src/plugins/surcharges/mutations/updateSurcharge.test.js b/src/plugins/surcharges/mutations/updateSurcharge.test.js deleted file mode 100644 index 3809afd4192..00000000000 --- a/src/plugins/surcharges/mutations/updateSurcharge.test.js +++ /dev/null @@ -1,85 +0,0 @@ -import mockCollection from "@reactioncommerce/api-utils/tests/mockCollection.js"; -import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; -import updateSurchargeMutation from "./updateSurcharge.js"; - - -// Create mock context with Surcharges collection -mockContext.collections.Surcharges = mockCollection("Surcharges"); -mockContext.validatePermissions.mockReturnValueOnce(Promise.resolve(null)); - -const surcharge = { - type: "surcharge", - attributes: [ - { property: "vendor", value: "reaction", propertyType: "string", operator: "eq" }, - { property: "productType", value: "knife", propertyType: "string", operator: "eq" } - ], - destination: { region: ["CO", "NY"] }, - amount: 5.99, - messagesByLanguage: [ - { - content: "Original Message English", - language: "en" - }, { - content: "Original Message Spanish", - language: "es" - } - ] -}; - -const updatedSurcharge = { - type: "surcharge", - attributes: [ - { property: "vendor", value: "john", propertyType: "string", operator: "eq" }, - { property: "productType", value: "gun", propertyType: "string", operator: "eq" } - ], - destination: { region: ["NJ", "WY"] }, - amount: { - amount: 17.99, - currencyCode: "USD" - }, - messagesByLanguage: [ - { - content: "Updated Message English", - language: "en" - }, { - content: "Updated Message Spanish", - language: "es" - } - ] -}; - -test("update a surcharge", async () => { - mockContext.collections.Surcharges.updateOne.mockReturnValueOnce(Promise.resolve({ - ok: 1, - updatedSurcharge - })); - - const result = await updateSurchargeMutation(mockContext, { - surcharge, - surchargeId: "surcharge123", - shopId: "shop123" - }); - - expect(result).toEqual({ - surcharge: { - _id: "surcharge123", - shopId: "shop123", - type: "surcharge", - attributes: [ - { property: "vendor", value: "reaction", propertyType: "string", operator: "eq" }, - { property: "productType", value: "knife", propertyType: "string", operator: "eq" } - ], - destination: { region: ["CO", "NY"] }, - amount: 5.99, - messagesByLanguage: [ - { - content: "Original Message English", - language: "en" - }, { - content: "Original Message Spanish", - language: "es" - } - ] - } - }); -}); diff --git a/src/plugins/surcharges/policies.json b/src/plugins/surcharges/policies.json deleted file mode 100644 index fdeac744883..00000000000 --- a/src/plugins/surcharges/policies.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "description": "Surcharge managers acting on all surcharges.", - "subjects": [ "reaction:groups:surcharge-managers" ], - "resources": [ "reaction:legacy:surcharges" ], - "actions": [ - "create", - "read" - ], - "effect": "allow" - }, - { - "description": "Surcharge managers acting on a single surcharge.", - "subjects": [ "reaction:groups:surcharge-managers" ], - "resources": [ "reaction:legacy:surcharges:*" ], - "actions": [ - "delete", - "read", - "update" - ], - "effect": "allow" - } -] diff --git a/src/plugins/surcharges/queries/index.js b/src/plugins/surcharges/queries/index.js deleted file mode 100644 index 458a0e91023..00000000000 --- a/src/plugins/surcharges/queries/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import surchargeById from "./surchargeById.js"; -import surcharges from "./surcharges.js"; - -export default { - surchargeById, - surcharges -}; diff --git a/src/plugins/surcharges/queries/surchargeById.js b/src/plugins/surcharges/queries/surchargeById.js deleted file mode 100644 index 820a0fbd835..00000000000 --- a/src/plugins/surcharges/queries/surchargeById.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @name surchargeById - * @method - * @memberof Fulfillment/NoMeteorQueries - * @summary Query the Surcharges collection for a surcharge with the provided shopId and surchargeId - * @param {Object} context - an object containing the per-request state - * @param {Object} params - request parameters - * @param {String} params.language - Language to retrieve surcharge message in - * @param {String} params.shopId - Shop ID for the shop that owns the surcharge - * @param {String} params.surchargeId - Surcharge ID of the surcharge we are requesting - * @returns {Promise|undefined} - A surcharge document, if one is found - */ -export default async function surchargeById(context, { surchargeId, shopId } = {}) { - const { collections } = context; - const { Surcharges } = collections; - - const surcharge = await Surcharges.findOne({ - _id: surchargeId, - shopId - }); - - return surcharge; -} diff --git a/src/plugins/surcharges/queries/surcharges.js b/src/plugins/surcharges/queries/surcharges.js deleted file mode 100644 index 8f249ce7e7c..00000000000 --- a/src/plugins/surcharges/queries/surcharges.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @name surcharges - * @method - * @memberof Fulfillment/NoMeteorQueries - * @summary Query the Surcharges collection for surcharges with the provided shopId - * @param {Object} context - an object containing the per-request state - * @param {Object} params - request parameters - * @param {String} params.shopId - Shop ID for the shop that owns the surcharges - * @returns {Promise|undefined} - Surcharge documents, if found - */ -export default async function surcharges(context, { shopId } = {}) { - const { collections } = context; - const { Surcharges } = collections; - - return Surcharges.find({ - shopId - }); -} diff --git a/src/plugins/surcharges/resolvers/AppliedSurcharge/index.js b/src/plugins/surcharges/resolvers/AppliedSurcharge/index.js deleted file mode 100644 index 3975b746434..00000000000 --- a/src/plugins/surcharges/resolvers/AppliedSurcharge/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import { encodeSurchargeOpaqueId } from "../../xforms/id.js"; -import xformSurchargeAmount from "../../xforms/xformSurchargeAmount.js"; -import getSurchargeMessageForLanguage from "../../util/getSurchargeMessageForLanguage.js"; - -export default { - _id: (node) => encodeSurchargeOpaqueId(node._id), - amount: (node, _, context) => node.amount && xformSurchargeAmount(context, node.shopId, node.amount), - message: (node, { language }) => node.messagesByLanguage && - node.messagesByLanguage.length && - getSurchargeMessageForLanguage(language, node.messagesByLanguage) -}; diff --git a/src/plugins/surcharges/resolvers/Mutation/createSurcharge.js b/src/plugins/surcharges/resolvers/Mutation/createSurcharge.js deleted file mode 100644 index 79a622a2329..00000000000 --- a/src/plugins/surcharges/resolvers/Mutation/createSurcharge.js +++ /dev/null @@ -1,38 +0,0 @@ -import { decodeFulfillmentMethodOpaqueId, decodeShopOpaqueId } from "../../xforms/id.js"; -import createSurchargeMutation from "../../mutations/createSurcharge.js"; - -/** - * @name Mutation/createSurcharge - * @method - * @memberof Fulfillment/GraphQL - * @summary resolver for the createSurcharge GraphQL mutation - * @param {Object} parentResult - unused - * @param {Object} args.input - an object of all mutation arguments that were sent by the client - * @param {Object} args.input.surcharge - The surcharge object - * @param {String} args.input.shopId - The shop to create this surcharge for - * @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call - * @param {Object} context - an object containing the per-request state - * @returns {Promise} CreateSurchargePayload - */ -export default async function createSurcharge(parentResult, { input }, context) { - const { clientMutationId = null, surcharge, shopId: opaqueShopId } = input; - - const shopId = decodeShopOpaqueId(opaqueShopId); - - let decodedMethodIds = []; - if (surcharge.methodIds && Array.isArray(surcharge.methodIds)) { - decodedMethodIds = surcharge.methodIds.map((methodId) => decodeFulfillmentMethodOpaqueId(methodId)); - } - - surcharge.methodIds = decodedMethodIds; - - const { surcharge: insertedSurcharge } = await createSurchargeMutation(context, { - surcharge, - shopId - }); - - return { - clientMutationId, - surcharge: insertedSurcharge - }; -} diff --git a/src/plugins/surcharges/resolvers/Mutation/deleteSurcharge.js b/src/plugins/surcharges/resolvers/Mutation/deleteSurcharge.js deleted file mode 100644 index 4242b298da9..00000000000 --- a/src/plugins/surcharges/resolvers/Mutation/deleteSurcharge.js +++ /dev/null @@ -1,32 +0,0 @@ -import { decodeShopOpaqueId, decodeSurchargeOpaqueId } from "../../xforms/id.js"; -import deleteSurchargeMutation from "../../mutations/deleteSurcharge.js"; - -/** - * @name Mutation/deleteSurcharge - * @method - * @memberof Fulfillment/GraphQL - * @summary resolver for the deleteSurcharge GraphQL mutation - * @param {Object} parentResult - unused - * @param {Object} args.input - an object of all mutation arguments that were sent by the client - * @param {String} args.input.surchargeId - The ID of the surcharge you want to delete - * @param {String} args.input.shopId - The shop to delete this surcharge for - * @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call - * @param {Object} context - an object containing the per-request state - * @returns {Promise} DeleteSurchargePayload - */ -export default async function deleteSurcharge(parentResult, { input }, context) { - const { clientMutationId = null, surchargeId: opaqueSurchargeId, shopId: opaqueShopId } = input; - - const shopId = decodeShopOpaqueId(opaqueShopId); - const surchargeId = decodeSurchargeOpaqueId(opaqueSurchargeId); - - const { surcharge } = await deleteSurchargeMutation(context, { - surchargeId, - shopId - }); - - return { - clientMutationId, - surcharge - }; -} diff --git a/src/plugins/surcharges/resolvers/Mutation/index.js b/src/plugins/surcharges/resolvers/Mutation/index.js deleted file mode 100644 index fc4143b0628..00000000000 --- a/src/plugins/surcharges/resolvers/Mutation/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import createSurcharge from "./createSurcharge.js"; -import deleteSurcharge from "./deleteSurcharge.js"; -import updateSurcharge from "./updateSurcharge.js"; - -export default { - createSurcharge, - deleteSurcharge, - updateSurcharge -}; diff --git a/src/plugins/surcharges/resolvers/Mutation/updateSurcharge.js b/src/plugins/surcharges/resolvers/Mutation/updateSurcharge.js deleted file mode 100644 index 157ebe15e18..00000000000 --- a/src/plugins/surcharges/resolvers/Mutation/updateSurcharge.js +++ /dev/null @@ -1,41 +0,0 @@ -import { decodeFulfillmentMethodOpaqueId, decodeShopOpaqueId, decodeSurchargeOpaqueId } from "../../xforms/id.js"; -import updateSurchargeMutation from "../../mutations/updateSurcharge.js"; - -/** - * @name Mutation/updateSurcharge - * @method - * @memberof Fulfillment/GraphQL - * @summary resolver for the updateSurcharge GraphQL mutation - * @param {Object} parentResult - unused - * @param {Object} args.input - an object of all mutation arguments that were sent by the client - * @param {String} args.input.surchargeId - The ID of the surcharge you want to update - * @param {Object} args.input.surcharge - The full updated surcharge object, without ID - * @param {String} args.input.shopId - The shop to update this surcharge for - * @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call - * @param {Object} context - an object containing the per-request state - * @returns {Promise} updateSurchargePayload - */ -export default async function updateSurcharge(parentResult, { input }, context) { - const { clientMutationId = null, surcharge, surchargeId: opaqueSurchargeId, shopId: opaqueShopId } = input; - - const shopId = decodeShopOpaqueId(opaqueShopId); - const surchargeId = decodeSurchargeOpaqueId(opaqueSurchargeId); - - let decodedMethodIds = []; - if (surcharge.methodIds && Array.isArray(surcharge.methodIds)) { - decodedMethodIds = surcharge.methodIds.map((methodId) => decodeFulfillmentMethodOpaqueId(methodId)); - } - - surcharge.methodIds = decodedMethodIds; - - const { surcharge: updatedSurcharge } = await updateSurchargeMutation(context, { - surcharge, - surchargeId, - shopId - }); - - return { - clientMutationId, - surcharge: updatedSurcharge - }; -} diff --git a/src/plugins/surcharges/resolvers/Query/index.js b/src/plugins/surcharges/resolvers/Query/index.js deleted file mode 100644 index 458a0e91023..00000000000 --- a/src/plugins/surcharges/resolvers/Query/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import surchargeById from "./surchargeById.js"; -import surcharges from "./surcharges.js"; - -export default { - surchargeById, - surcharges -}; diff --git a/src/plugins/surcharges/resolvers/Query/surchargeById.js b/src/plugins/surcharges/resolvers/Query/surchargeById.js deleted file mode 100644 index 7b627cf3415..00000000000 --- a/src/plugins/surcharges/resolvers/Query/surchargeById.js +++ /dev/null @@ -1,23 +0,0 @@ -import { decodeShopOpaqueId, decodeSurchargeOpaqueId } from "../../xforms/id.js"; - -/** - * @name Query/surchargeById - * @method - * @memberof Fulfillment/GraphQL - * @summary resolver for the surchargeById GraphQL mutation - * @param {Object} parentResult - unused - * @param {Object} args - an object of all arguments that were sent by the client - * @param {String} args.language - Language to retrieve surcharge message in - * @param {String} args.surchargeId - Surcharge ID of the surcharge we are requesting - * @param {String} args.shopId - The shop that owns this surcharge - * @param {Object} context - an object containing the per-request state - * @returns {Promise|undefined} A Surcharge object - */ -export default async function surchargeById(parentResult, args, context) { - const { surchargeId, shopId } = args; - - return context.queries.surchargeById(context, { - surchargeId: decodeSurchargeOpaqueId(surchargeId), - shopId: decodeShopOpaqueId(shopId) - }); -} diff --git a/src/plugins/surcharges/resolvers/Query/surcharges.js b/src/plugins/surcharges/resolvers/Query/surcharges.js deleted file mode 100644 index 597f796a0a9..00000000000 --- a/src/plugins/surcharges/resolvers/Query/surcharges.js +++ /dev/null @@ -1,29 +0,0 @@ -import getPaginatedResponse from "@reactioncommerce/api-utils/graphql/getPaginatedResponse.js"; -import wasFieldRequested from "@reactioncommerce/api-utils/graphql/wasFieldRequested.js"; -import { decodeShopOpaqueId } from "../../xforms/id.js"; - -/** - * @name Query/surcharges - * @method - * @memberof Fulfillment/GraphQL - * @summary resolver for the surcharges GraphQL mutation - * @param {Object} parentResult - unused - * @param {Object} args - an object of all arguments that were sent by the client - * @param {String} args.shopId - The shop that owns these surcharges - * @param {Object} context - an object containing the per-request state - * @param {Object} info Info about the GraphQL request - * @returns {Promise|undefined} A Surcharge object - */ -export default async function surcharges(parentResult, args, context, info) { - const { shopId, ...connectionArgs } = args; - - const cursor = await context.queries.surcharges(context, { - shopId: decodeShopOpaqueId(shopId) - }); - - return getPaginatedResponse(cursor, connectionArgs, { - includeHasNextPage: wasFieldRequested("pageInfo.hasNextPage", info), - includeHasPreviousPage: wasFieldRequested("pageInfo.hasPreviousPage", info), - includeTotalCount: wasFieldRequested("totalCount", info) - }); -} diff --git a/src/plugins/surcharges/resolvers/Surcharge/index.js b/src/plugins/surcharges/resolvers/Surcharge/index.js deleted file mode 100644 index 0f8208182bd..00000000000 --- a/src/plugins/surcharges/resolvers/Surcharge/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import { encodeFulfillmentMethodOpaqueId, encodeShopOpaqueId, encodeSurchargeOpaqueId } from "../../xforms/id.js"; -import xformSurchargeAmount from "../../xforms/xformSurchargeAmount.js"; -import getSurchargeMessageForLanguage from "../../util/getSurchargeMessageForLanguage.js"; - -export default { - _id: (node) => encodeSurchargeOpaqueId(node._id), - shopId: (node) => encodeShopOpaqueId(node.shopId), - amount: (node, _, context) => node.amount && xformSurchargeAmount(context, node.shopId, node.amount), - message: (node, { language }) => node.messagesByLanguage && - node.messagesByLanguage.length && - getSurchargeMessageForLanguage(language, node.messagesByLanguage), - methodIds: (node) => node.methodIds.map(encodeFulfillmentMethodOpaqueId) -}; diff --git a/src/plugins/surcharges/resolvers/index.js b/src/plugins/surcharges/resolvers/index.js deleted file mode 100644 index 89f805da1ac..00000000000 --- a/src/plugins/surcharges/resolvers/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import getConnectionTypeResolvers from "@reactioncommerce/api-utils/graphql/getConnectionTypeResolvers.js"; -import AppliedSurcharge from "./AppliedSurcharge/index.js"; -import Surcharge from "./Surcharge/index.js"; -import Mutation from "./Mutation/index.js"; -import Query from "./Query/index.js"; - -export default { - ...getConnectionTypeResolvers("Surcharge"), - AppliedSurcharge, - Surcharge, - Mutation, - Query -}; diff --git a/src/plugins/surcharges/schemas/index.js b/src/plugins/surcharges/schemas/index.js deleted file mode 100644 index 30096f92e54..00000000000 --- a/src/plugins/surcharges/schemas/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import importAsString from "@reactioncommerce/api-utils/importAsString.js"; - -const schema = importAsString("./schema.graphql"); - -export default [schema]; diff --git a/src/plugins/surcharges/schemas/schema.graphql b/src/plugins/surcharges/schemas/schema.graphql deleted file mode 100644 index 80d99dd8362..00000000000 --- a/src/plugins/surcharges/schemas/schema.graphql +++ /dev/null @@ -1,380 +0,0 @@ -#### -# Custom data types for Surcharges data -#### - - -### -# Types -### -"Defines a surcharge that has been applied to a Cart or Order" -type AppliedSurcharge implements Node { - "The surcharge ID" - _id: ID! - - "The amount of the surcharge" - amount: Money! - - "The fulfillmentGroupId (for reference)" - fulfillmentGroupId: ID - - "The message to explain the surchage to customers, translated (if available) based on shop language" - message( - """ - The language in which you want the message. If no translation is available for this language, - it will be in the default language of the related shop. - """ - language: String! - ): String - - "The surchargeId from the surchages collection (for reference)" - surchargeDefinitionId: ID! -} - -"Defines a surcharge for surchargeById and surcharges query." -type Surcharge implements Node { - "The surcharge ID." - _id: ID! - - "Amount." - amount: Money! - - "Attribute restrictions." - attributes: [SurchargeAttributeRestrictions] - - "Destination restrictions." - destination: SurchargeDestinationRestrictions - - "Message translated into provided / default language." - message( - """ - The language in which you want the message. If no translation is available for this language, - it will be in the default language of the related shop. - """ - language: String! - ): String! - - "Messages provided with content and all languages" - messagesByLanguage: [SurchargeMessagesByLanguage] - - "Method IDs to apply this surcharge to." - methodIds: [ID] - - "The shop ID" - shopId: ID! - - """ - The type of this surcharge. Allowed types `surcharge`. - """ - type: SurchargeTypeEnum! -} - -"Attribute Restrictions attached to a Surcharge" -type SurchargeAttributeRestrictions { - "The operator to use for value comparison" - operator: String - - "The property to check" - property: String - - "The type of this property" - propertyType: String - - "The value to check for" - value: String -} - -""" -Wraps a list of `Surcharge`s, providing pagination cursors and information. - -For information about what Relay-compatible connections are and how to use them, see the following articles: -- [Relay Connection Documentation](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#connections) -- [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm) -- [Using Relay-style Connections With Apollo Client](https://www.apollographql.com/docs/react/recipes/pagination.html) -""" -type SurchargeConnection { - "The list of nodes that match the query, wrapped in an edge to provide a cursor string for each" - edges: [SurchargeEdge] - - """ - You can request the `nodes` directly to avoid the extra wrapping that `NodeEdge` has, - if you know you will not need to paginate the results. - """ - nodes: [Surcharge] - - "Information to help a client request the next or previous page" - pageInfo: PageInfo! - - "Total count for all pages" - totalCount: Int! -} - -""" -Destination restrictions attached to a surcharge. If multiple of `country`, -`region`, and `postal` are set, there is an AND relationship. -""" -type SurchargeDestinationRestrictions { - "Restrict for any of these destination countries" - country: [String] - - "Restrict for any of these destination postal codes" - postal: [String] - - "Restrict for any of these destination regions" - region: [String] -} - -"A connection edge in which each node is a `Surcharge` object" -type SurchargeEdge { - "The cursor that represents this node in the paginated results" - cursor: ConnectionCursor! - - "The surcharge" - node: Surcharge -} - -"Object that includes translated content and language of translation" -type SurchargeMessagesByLanguage { - "The message for this language" - content: String! - - "The language code" - language: String! -} - -### -# Extensions of existing types -### -extend type Cart { - "Surcharges applied to this cart" - surcharges: [AppliedSurcharge]! -} - -extend type Order { - "Surcharges applied to this order" - surcharges: [AppliedSurcharge]! -} - -extend type CartSummary { - """ - The combined total of all surcharges. This may be null, and there is a difference - between null and 0. Null means `not able to calculate`, such as when no fulfillment method has - been selected for some fulfillment groups. - """ - surchargeTotal: Money -} - -extend type OrderSummary { - "The total of all suurcharges applied" - surchargeTotal: Money -} - -### -# Enums -### -"Allowed values for surcharge `sortBy` parameter" -enum SurchargeSortByField { - "The date the surcharge definition was created" - createdAt -} - -"Allowed values for surcharge type" -enum SurchargeTypeEnum { - "Surcharge" - surcharge -} - - -### -# Inputs -### -"Input for the `CreateSurcharge` mutation" -input CreateSurchargeInput { - "An optional string identifying the mutation call, which will be returned in the response payload" - clientMutationId: String - - "The shop to create this surcharge for" - shopId: ID! - - "This defines the surcharge that you want to create" - surcharge: SurchargeInput! -} - -"Input for the `deleteSurcharge` mutation" -input DeleteSurchargeInput { - "An optional string identifying the mutation call, which will be returned in the response payload" - clientMutationId: String - - "The shop that owns the method" - shopId: ID! - - "The ID of the flat rate fulfillment method you want to delete" - surchargeId: ID! -} - -"Input to add a surcharge message with language" -input MessagesByLanguageInput { - "The message for this language" - content: String! - - "The language code" - language: String! -} - -"Input to add a surcharge attribute restriction" -input SurchargeAttributeRestrictionsInput { - "The operator to use for value comparison" - operator: String - - "The property to check" - property: String - - "The type of this property" - propertyType: String - - "The value to check for" - value: String -} - -"Input to add a surcharge destination restriction" -input SurchargeDestinationRestrictionsInput { - "Restrict for any of these destination countries" - country: [String] - - "Restrict for any of these destination postal codes" - postal: [String] - - "Restrict for any of these destination regions" - region: [String] -} - -"Defines a surcharge." -input SurchargeInput { - "Amount." - amount: Float! - - "Attribute restrictions." - attributes: [SurchargeAttributeRestrictionsInput] - - "Destination restrictions." - destination: SurchargeDestinationRestrictionsInput - - "Messages by language." - messagesByLanguage: [MessagesByLanguageInput]! - - "Method IDs to apply this surcharge to." - methodIds: [ID] - - """ - The type of this surcharge. Allowed types are `surcharge`. - """ - type: SurchargeTypeEnum! -} - -"Input for the `updateSurcharge` mutation" -input UpdateSurchargeInput { - "An optional string identifying the mutation call, which will be returned in the response payload" - clientMutationId: String - - "The shop that owns the method" - shopId: ID! - - "The updated surcharge. Pass the whole updated surcharge object without the ID." - surcharge: SurchargeInput! - - "The ID of the flat rate fulfillment surcharge you want to update" - surchargeId: ID! -} - - -#### -# Queries -#### -extend type Query { - "Get the full list of surcharges." - surcharges( - "ID of shop to get surcharges for" - shopId: ID!, - - "Return only results that come after this cursor. Use this with `first` to specify the number of results to return." - after: ConnectionCursor, - - "Return only results that come before this cursor. Use this with `last` to specify the number of results to return." - before: ConnectionCursor, - - "Return at most this many results. This parameter may be used with either `after` or `offset` parameters." - first: ConnectionLimitInt, - - "Return at most this many results. This parameter may be used with the `before` parameter." - last: ConnectionLimitInt, - - "Return results sorted in this order" - sortOrder: SortOrder = desc, - - "By default, surcharges are sorted by when they were created, newest first. Set this to sort by one of the other allowed fields" - sortBy: SurchargeSortByField = createdAt - ): SurchargeConnection! - - "Get a single surcharge definition by its ID" - surchargeById( - "ID of shop that owns the surcharge definition" - shopId: ID!, - - "The surcharge ID" - surchargeId: ID! - ): Surcharge -} - - -#### -# Mutations -#### -extend type Mutation { - "Create a surcharge" - createSurcharge( - "Mutation input" - input: CreateSurchargeInput! - ): CreateSurchargePayload! - - "Delete a flat rate fulfillment restriction" - deleteSurcharge( - "Mutation input" - input: DeleteSurchargeInput! - ): DeleteSurchargePayload! - - "Update a flat rate fulfillment surcharge" - updateSurcharge( - "Mutation input" - input: UpdateSurchargeInput! - ): UpdateSurchargePayload! -} - - -#### -# Payloads -#### -"Response from the `CreateSurcharge` mutation" -type CreateSurchargePayload { - "The same string you sent with the mutation params, for matching mutation calls with their responses" - clientMutationId: String - - "The created surcharge" - surcharge: Surcharge! -} - -"Response from the `deleteSurcharge` mutation" -type DeleteSurchargePayload { - "The same string you sent with the mutation params, for matching mutation calls with their responses" - clientMutationId: String - - "The removed fulfillment method" - surcharge: Surcharge! -} - -"Response from the `updateFlatRateFulfillmentMethod` mutation" -type UpdateSurchargePayload { - "The same string you sent with the mutation params, for matching mutation calls with their responses" - clientMutationId: String - - "The updated fulfillment surcharge" - surcharge: Surcharge! -} diff --git a/src/plugins/surcharges/util/getSurchargeMessageForLanguage.js b/src/plugins/surcharges/util/getSurchargeMessageForLanguage.js deleted file mode 100644 index 65581141970..00000000000 --- a/src/plugins/surcharges/util/getSurchargeMessageForLanguage.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name getSurchargeMessageForLanguage - * @summary Returns translated surcharge message - * @param {String} language Language to filter items by - * @param {Array} messagesByLanguage Surcharge messages by language array - * @returns {String} Translated surcharge message, or first surcharge message if translation in - * provided language is not available. - */ -export default function getSurchargeMessageForLanguage(language, messagesByLanguage) { - const translatedMessage = messagesByLanguage.find((message) => message.language === language); - return (translatedMessage && translatedMessage.content) || null; -} diff --git a/src/plugins/surcharges/util/setSurchargesOnCart.js b/src/plugins/surcharges/util/setSurchargesOnCart.js deleted file mode 100644 index 9106202cdad..00000000000 --- a/src/plugins/surcharges/util/setSurchargesOnCart.js +++ /dev/null @@ -1,36 +0,0 @@ -import getSurcharges from "../getSurcharges.js"; - -/** - * @summary Cart transformation function that sets surcharges on cart - * @param {Object} context Startup context - * @param {Object} cart The cart, which can be mutated. - * @param {Object} options Options - * @param {Function} options.getCommonOrders Call this to get CommonOrder objects for all the cart groups - * @returns {undefined} - */ -export default async function setSurchargesOnCart(context, cart, { getCommonOrders }) { - // This is a workaround for now because surcharge calculations sometimes need an account ID. - // We eventually need to add accountId to CommonOrder instead. - let contextWithAccount = { ...context }; - if (cart.accountId && !context.account) { - const { Accounts } = context.collections; - const account = await Accounts.findOne({ _id: cart.accountId }); - contextWithAccount = { - ...context, - account, - accountId: cart.accountId - }; - } - - // Merge surcharges from each shipping group - const cartSurcharges = []; - const commonOrders = await getCommonOrders(); - for (const commonOrder of commonOrders) { - const appliedSurcharges = await getSurcharges(contextWithAccount, { commonOrder }); // eslint-disable-line - - // Push shippingGroup surcharges to cart surcharge array - cartSurcharges.push(...appliedSurcharges); - } - - cart.surcharges = cartSurcharges; -} diff --git a/src/plugins/surcharges/util/surchargeCheck.js b/src/plugins/surcharges/util/surchargeCheck.js deleted file mode 100644 index 7bc22d6e06e..00000000000 --- a/src/plugins/surcharges/util/surchargeCheck.js +++ /dev/null @@ -1,79 +0,0 @@ -import operators from "@reactioncommerce/api-utils/operators.js"; -import propertyTypes from "@reactioncommerce/api-utils/propertyTypes.js"; - -/** - * @summary Filter surcharges based on surcharge restriction data - * @param {Object} surcharge - surcharge to check attributes and destination against - * @param {Object} extendCommonOrder - details about the purchase a user wants to make. - * @returns {Bool} true / false as to whether method is still valid after this check - */ -export async function surchargeCheck(surcharge, extendCommonOrder) { - const { items, shippingAddress } = extendCommonOrder; - const { attributes, destination } = surcharge; - - const validSurcharge = items.some((item) => { // eslint-disable-line - if (Array.isArray(attributes) && attributes.length) { - // Item must meet all attributes to be restricted - return attributes.every((attribute) => { - let attributeFound = operators[attribute.operator](item[attribute.property], propertyTypes[attribute.propertyType](attribute.value)); - - // If attribute is an array on the item, use `includes` instead of checking for === - // This works for tags, tagIds, and any future attribute that might be an array - if (Array.isArray(item[attribute.property])) { - attributeFound = item[attribute.property].includes(attribute.value); - } - - if (attributeFound && shippingAddress) { - // If there is no destination restriction, destination restriction is global - // Return true to restrict this method - if (!destination || Object.getOwnPropertyNames(destination).length === 0) return attributeFound; - - const { country, postal, region } = destination; - - if (postal && postal.includes(shippingAddress.postal)) { - return true; - } - - // Check for an allow list of regions - if (region && region.includes(shippingAddress.region)) { - return true; - } - - // Check for an allow list of countries - if (country && country.includes(shippingAddress.country)) { - return true; - } - } - - // If shipping location does not match restricted location && attribute, method is not restricted - return false; - }); - } - - // If there are no attributes on the surcharge, and destination doesn't exist, don't apply surcharge - if (!destination) return false; - - const { country, postal, region } = destination; - - // If destination exists, make sure we have a shipping address, and check against it - if (shippingAddress) { - if (postal && postal.includes(shippingAddress.postal)) { - return true; - } - - // Check for an allow list of regions - if (region && region.includes(shippingAddress.region)) { - return true; - } - - // Check for an allow list of countries - if (country && country.includes(shippingAddress.country)) { - return true; - } - } - - return false; - }); - - return validSurcharge; -} diff --git a/src/plugins/surcharges/util/surchargeCheck.test.js b/src/plugins/surcharges/util/surchargeCheck.test.js deleted file mode 100644 index 5c7e581b411..00000000000 --- a/src/plugins/surcharges/util/surchargeCheck.test.js +++ /dev/null @@ -1,223 +0,0 @@ -import mockCollection from "@reactioncommerce/api-utils/tests/mockCollection.js"; -import mockContext from "@reactioncommerce/api-utils/tests/mockContext.js"; -import { surchargeCheck } from "./surchargeCheck.js"; - -// Create mock context with Surcharges collection -mockContext.collections.Surcharges = mockCollection("Surcharges"); - -const mockSurchargeWithAttributesAndLocation = [ - { - _id: "9FNSPHfzYd9LpitJb", - shopId: "J8Bhq3uTtdgwZx3rz", - methodIds: [], - type: "surcharge", - attributes: [ - { - property: "vendor", - value: "Restricted Vendor", - propertyType: "string", - operator: "eq" - } - ], - destination: { - region: [ - "CA", - "NY" - ] - }, - amount: { - amount: 9.99, - currencyCode: "USD" - }, - message: "This surcharge applies because the product name is \"Basic Reaction Product\" and the destination is California or New York" - } -]; - -const mockSurchargeWithAttributes = [ - { - _id: "9FNSPHfzYd9LpitJb", - shopId: "J8Bhq3uTtdgwZx3rz", - methodIds: [], - type: "surcharge", - attributes: [ - { - property: "vendor", - value: "Restricted Vendor", - propertyType: "string", - operator: "eq" - } - ], - destination: {}, - amount: { - amount: 9.99, - currencyCode: "USD" - }, - message: "This surcharge applies because the product name is \"Basic Reaction Product\" and the destination is California or New York" - }, - { - _id: "9FNSPHfzYd9LpitJb", - shopId: "J8Bhq3uTtdgwZx3rz", - methodIds: [], - type: "surcharge", - attributes: [ - { - property: "vendor", - value: "Dog Industries", - propertyType: "string", - operator: "eq" - } - ], - destination: {}, - amount: { - amount: 9.99, - currencyCode: "USD" - }, - message: "This surcharge applies because the product name is \"Basic Reaction Product\" and the destination is California or New York" - } -]; - -const mockSurchargeWithLocation = [ - { - _id: "9FNSPHfzYd9LpitJb", - shopId: "J8Bhq3uTtdgwZx3rz", - methodIds: [], - type: "surcharge", - attributes: [], - destination: { - region: [ - "CA", - "NY" - ] - }, - amount: { - amount: 9.99, - currencyCode: "USD" - }, - message: "This surcharge applies because the product name is \"Basic Reaction Product\" and the destination is California or New York" - } -]; - - -// Mock cart items -const mockHydratedOrderItems = { - _id: "tMkp5QwZog5ihYTfG", - createdAt: "2018-11-01T16:42:03.448Z", - description: "Represent the city that never sleeps with this classic T.", - isDeleted: false, - isTaxable: true, - isVisible: true, - pageTitle: "212. 646. 917.", - price: 12.99, - primaryImage: [Object], - productId: "cR6LKN5yGSiei7cia", - shopId: "J8Bhq3uTtdgwZx3rz", - slug: "new-york-city-1998-t-shirt", - supportedFulfillmentTypes: [Array], - tagIds: [Array], - title: "Small", - type: "product-simple", - updatedAt: "2018-11-01T16:42:03.448Z", - vendor: "Restricted Vendor", - height: 10, - index: 0, - length: 10, - optionTitle: "Small", - originCountry: "US", - taxCode: "0000", - variantId: "tMkp5QwZog5ihYTfG", - weight: 50, - width: 10, - tags: [Array] -}; - -const mockExtendedCommonOrderCalifornia = { - shippingAddress: - { - address1: "123 California Street", - city: "Los Angeles", - country: "US", - postal: "90405", - region: "CA" - }, - discountTotal: 0, - items: - [mockHydratedOrderItems], - itemTotal: 898.95, - total: 898.95 -}; - -const mockExtendedCommonOrderColorado = { - shippingAddress: - { - address1: "123 Colorado Street", - city: "Denver", - country: "US", - postal: "80231", - region: "CO" - }, - discountTotal: 0, - items: - [mockHydratedOrderItems], - itemTotal: 898.95, - total: 898.95 -}; - -test("Attributes & Location true - Order with vendor \"Restricted Vendor\" and shipping location \"California\" should apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithAttributesAndLocation)); - - const surchargeToTest = mockSurchargeWithAttributesAndLocation[0]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderCalifornia); - - expect(applySurcharge).toEqual(true); -}); - -test("Attributes & Location false - Order with vendor \"Restricted Vendor\" and shipping location \"Colorado\" should not apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithAttributesAndLocation)); - - const surchargeToTest = mockSurchargeWithAttributesAndLocation[0]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderColorado); - - expect(applySurcharge).toEqual(false); -}); - -test("Attributes true - Order with vendor \"Restricted Vendor\" should apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithAttributes)); - - const surchargeToTest = mockSurchargeWithAttributes[0]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderCalifornia); - - expect(applySurcharge).toEqual(true); -}); - -test("Attributes false - Order with vendor \"Dog Industries\" should not apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithAttributes)); - - const surchargeToTest = mockSurchargeWithAttributes[1]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderColorado); - - expect(applySurcharge).toEqual(false); -}); - -test("Location true - Order with shipping location \"California\" should apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithLocation)); - - const surchargeToTest = mockSurchargeWithLocation[0]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderCalifornia); - - expect(applySurcharge).toEqual(true); -}); - -test("Location false - Order with shipping location \"Colorado\" should not apply surcharge", async () => { - mockContext.collections.Surcharges.toArray.mockReturnValue(Promise.resolve(mockSurchargeWithLocation)); - - const surchargeToTest = mockSurchargeWithLocation[0]; - - const applySurcharge = await surchargeCheck(surchargeToTest, mockExtendedCommonOrderColorado); - - expect(applySurcharge).toEqual(false); -}); diff --git a/src/plugins/surcharges/util/surchargeSchema.js b/src/plugins/surcharges/util/surchargeSchema.js deleted file mode 100644 index b1c80410ad9..00000000000 --- a/src/plugins/surcharges/util/surchargeSchema.js +++ /dev/null @@ -1,101 +0,0 @@ -import SimpleSchema from "simpl-schema"; - -/** - * @name Attributes - * @memberof Schemas - * @type {SimpleSchema} - * @property {String} property required - * @property {String} value required - * @property {String} propertyType required - * @property {String} operator required - */ -export const Attributes = new SimpleSchema({ - property: String, - value: String, - propertyType: String, - operator: String -}); - -/** - * @name Destination - * @memberof Schemas - * @type {SimpleSchema} - * @property {String} country optional - * @property {String} region optional - * @property {String} postal optional - */ -export const Destination = new SimpleSchema({ - "country": { - type: Array, - optional: true - }, - "country.$": String, - "region": { - type: Array, - optional: true - }, - "region.$": String, - "postal": { - type: Array, - optional: true - }, - "postal.$": String -}); - -/** - * @name Message - * @memberof Schemas - * @type {SimpleSchema} - * @property {String} content - * @property {String} language - */ -const Message = new SimpleSchema({ - content: String, - language: String -}); - -export const Surcharge = new SimpleSchema({ - "amount": { - type: Number - }, - /* - * Order item attributes methods this surcharge applies to - */ - "attributes": { - type: Array, - optional: true - }, - "attributes.$": Attributes, - /* - * Destinations this surcharge applies to - */ - "destination": { - type: Destination, - optional: true - }, - /* - * Message is used as a client message to let customers know why this surcharge might apply - * It can be saved in various languages - */ - "messagesByLanguage": { - type: Array - }, - "messagesByLanguage.$": { - type: Message - }, - /* - * Fulfillment methods this surcharge applies to - * If blank, it applies to all methods - */ - "methodIds": { - type: Array, - optional: true - }, - "methodIds.$": String, - "type": { - type: String, - defaultValue: "surcharge" - } -}); - -export default Surcharge; diff --git a/src/plugins/surcharges/xforms/id.js b/src/plugins/surcharges/xforms/id.js deleted file mode 100644 index f6a04f2fdd4..00000000000 --- a/src/plugins/surcharges/xforms/id.js +++ /dev/null @@ -1,16 +0,0 @@ -import decodeOpaqueIdForNamespace from "@reactioncommerce/api-utils/decodeOpaqueIdForNamespace.js"; -import encodeOpaqueId from "@reactioncommerce/api-utils/encodeOpaqueId.js"; - -const namespaces = { - FulfillmentMethod: "reaction/fulfillmentMethod", - Surcharge: "reaction/surcharge", - Shop: "reaction/shop" -}; - -export const encodeFulfillmentMethodOpaqueId = encodeOpaqueId(namespaces.FulfillmentMethod); -export const encodeSurchargeOpaqueId = encodeOpaqueId(namespaces.Surcharge); -export const encodeShopOpaqueId = encodeOpaqueId(namespaces.Shop); - -export const decodeFulfillmentMethodOpaqueId = decodeOpaqueIdForNamespace(namespaces.FulfillmentMethod); -export const decodeSurchargeOpaqueId = decodeOpaqueIdForNamespace(namespaces.Surcharge); -export const decodeShopOpaqueId = decodeOpaqueIdForNamespace(namespaces.Shop); diff --git a/src/plugins/surcharges/xforms/xformSurchargeAmount.js b/src/plugins/surcharges/xforms/xformSurchargeAmount.js deleted file mode 100644 index 03d222dd011..00000000000 --- a/src/plugins/surcharges/xforms/xformSurchargeAmount.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @name xformSurchargeAmount - * @summary Transforms amount from Float to Money type - * @param {Object} context An object with request-specific state - * @param {String} shopId ID of shop - * @param {String} importedAmount amount to convert to Money type - * @returns {Object} Transformed amount - */ -export default async function xformSurchargeAmount(context, shopId, importedAmount) { - const shop = await context.collections.Shops.findOne({ _id: shopId }); - const { currency: currencyCode } = shop; - - return { - amount: importedAmount, - currencyCode - }; -} diff --git a/tests/util/factory.js b/tests/util/factory.js index 32f493edc62..bd7b0364ad5 100644 --- a/tests/util/factory.js +++ b/tests/util/factory.js @@ -72,6 +72,10 @@ import { Sitemap } from "@reactioncommerce/plugin-sitemap-generator/src/simpleSchemas.js"; +import { + Surcharge +} from "@reactioncommerce/api-plugin-surcharges/src/util/surchargeSchema.js"; + import { Tag } from "@reactioncommerce/api-plugin-tags/src/simpleSchemas.js"; @@ -80,10 +84,6 @@ import { extendInventorySchemas } from "../../src/core-services/inventory/simpleSchemas.js"; -import { - Surcharge -} from "../../src/plugins/surcharges/util/surchargeSchema.js"; - import { TaxRates } from "../../src/plugins/taxes-rates/simpleSchemas.js";