diff --git a/jest.config.cjs b/jest.config.cjs index 874cf518f25..12cbc1cdb9c 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -21,6 +21,7 @@ const externalNodeModules = [ "@reactioncommerce/api-plugin-orders", "@reactioncommerce/api-plugin-payments", "@reactioncommerce/api-plugin-payments-stripe", + "@reactioncommerce/api-plugin-pricing-simple", "@reactioncommerce/api-plugin-products", "@reactioncommerce/api-plugin-settings", "@reactioncommerce/api-plugin-simple-schema", diff --git a/package-lock.json b/package-lock.json index 98080ee6018..25ab8fadcc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1747,6 +1747,18 @@ } } }, + "@reactioncommerce/api-plugin-pricing-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@reactioncommerce/api-plugin-pricing-simple/-/api-plugin-pricing-simple-1.0.0.tgz", + "integrity": "sha512-KRYDmkwIIr41+HLeCJ0HJVM5g2oWRcZ3T/idkNpzImE9R2eKdsKNp2oIetZjs5XBDAed5myVrtyGHXmtWcshqQ==", + "requires": { + "@reactioncommerce/api-utils": "^1.9.0", + "@reactioncommerce/logger": "^1.1.3", + "@reactioncommerce/reaction-error": "^1.0.1", + "accounting-js": "^1.1.1", + "simpl-schema": "^1.5.7" + } + }, "@reactioncommerce/api-plugin-products": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@reactioncommerce/api-plugin-products/-/api-plugin-products-1.0.0.tgz", diff --git a/package.json b/package.json index ff1af8b2683..c61c2a5acf2 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@reactioncommerce/api-plugin-orders": "~1.0.0", "@reactioncommerce/api-plugin-payments": "~1.0.0", "@reactioncommerce/api-plugin-payments-stripe": "~1.0.0", + "@reactioncommerce/api-plugin-pricing-simple": "~1.0.0", "@reactioncommerce/api-plugin-products": "~1.0.0", "@reactioncommerce/api-plugin-settings": "~1.0.0", "@reactioncommerce/api-plugin-shipments": "~1.0.0", diff --git a/plugins.json b/plugins.json index 7c44c1fe68b..97bb27afcfe 100644 --- a/plugins.json +++ b/plugins.json @@ -19,7 +19,7 @@ "notifications": "@reactioncommerce/api-plugin-notifications", "orders": "@reactioncommerce/api-plugin-orders", "payments": "@reactioncommerce/api-plugin-payments", - "pricing": "./src/plugins/simple-pricing/index.js", + "pricing": "@reactioncommerce/api-plugin-pricing-simple", "product": "@reactioncommerce/api-plugin-products", "sMTPEmail": "@reactioncommerce/api-plugin-email-smtp", "settings": "@reactioncommerce/api-plugin-settings", diff --git a/src/mockTypes.graphql b/src/mockTypes.graphql index da0aaf3857a..18d913392f2 100644 --- a/src/mockTypes.graphql +++ b/src/mockTypes.graphql @@ -419,6 +419,8 @@ extend type FakeData { productVariantInput: ProductVariantInput ): Product, "Fake field to satisfy linting" + productVariant: ProductVariant, + "Fake field to satisfy linting" metafield: Metafield "Fake field to satisfy linting" imageInfo: ImageInfo, diff --git a/src/plugins/simple-pricing/README.md b/src/plugins/simple-pricing/README.md deleted file mode 100644 index 92c0556b17b..00000000000 --- a/src/plugins/simple-pricing/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Simple Pricing - -Pricing data falls under it's own domain within the Reaction Commerce system, however it currently needs to be intertwined and available from other system domains (i.e., Catalog, Cart, Checkout, Orders). To give us more flexibility in pricing data management we've begun to move pricing get/set functions into this `simple-pricing` plugin and calling these functions from the `context.queries` object from within their respective functions. Now we can fully replace the pricing management system without modification to core by creating a custom plugin that replaces the `simple-pricing` queries. - -## Queries - -Any pricing plugin is expected to define and register the following query functions. - -### getVariantPrice - -This query function is used to get a product variant's real current price. diff --git a/src/plugins/simple-pricing/i18n/en.json b/src/plugins/simple-pricing/i18n/en.json deleted file mode 100644 index 59b315d6669..00000000000 --- a/src/plugins/simple-pricing/i18n/en.json +++ /dev/null @@ -1,11 +0,0 @@ -[{ - "i18n": "en", - "ns": "reaction-simple-pricing", - "translation": { - "reaction-simple-pricing": { - "productVariant": { - "noPriceTracking": "Prices are tracked only for sellable variants. Select an option to manage prices for it." - } - } - } -}] diff --git a/src/plugins/simple-pricing/i18n/index.js b/src/plugins/simple-pricing/i18n/index.js deleted file mode 100644 index e6a23601392..00000000000 --- a/src/plugins/simple-pricing/i18n/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import en from "./en.json"; - -// -// we want all the files in individual -// imports for easier handling by -// automated translation software -// -export default { - translations: [...en] -}; diff --git a/src/plugins/simple-pricing/index.js b/src/plugins/simple-pricing/index.js deleted file mode 100644 index e4f0a8233aa..00000000000 --- a/src/plugins/simple-pricing/index.js +++ /dev/null @@ -1,49 +0,0 @@ -import i18n from "./i18n/index.js"; -import policies from "./policies.json"; -import preStartup from "./preStartup.js"; -import mutations from "./mutations/index.js"; -import queries from "./queries/index.js"; -import resolvers from "./resolvers/index.js"; -import schemas from "./schemas/index.js"; -import startup from "./startup.js"; -import getMinPriceSortByFieldPath from "./util/getMinPriceSortByFieldPath.js"; -import mutateNewProductBeforeCreate from "./util/mutateNewProductBeforeCreate.js"; -import mutateNewVariantBeforeCreate from "./util/mutateNewVariantBeforeCreate.js"; -import publishProductToCatalog from "./util/publishProductToCatalog.js"; -import { PriceRange } from "./simpleSchemas.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: "Pricing", - name: "reaction-pricing", - version: app.context.appVersion, - i18n, - functionsByType: { - getMinPriceSortByFieldPath: [getMinPriceSortByFieldPath], - mutateNewProductBeforeCreate: [mutateNewProductBeforeCreate], - mutateNewVariantBeforeCreate: [mutateNewVariantBeforeCreate], - preStartup: [preStartup], - publishProductToCatalog: [publishProductToCatalog], - startup: [startup] - }, - graphQL: { - resolvers, - schemas - }, - mutations, - policies, - queries, - catalog: { - publishedProductFields: ["price"], - publishedProductVariantFields: ["compareAtPrice", "price"] - }, - simpleSchemas: { - PriceRange - } - }); -} diff --git a/src/plugins/simple-pricing/mutations/index.js b/src/plugins/simple-pricing/mutations/index.js deleted file mode 100644 index 01c1771a1ca..00000000000 --- a/src/plugins/simple-pricing/mutations/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import updateProductVariantPrices from "./updateProductVariantPrices.js"; - -export default { - updateProductVariantPrices -}; diff --git a/src/plugins/simple-pricing/mutations/updateProductVariantPrices.js b/src/plugins/simple-pricing/mutations/updateProductVariantPrices.js deleted file mode 100644 index c34ec54926c..00000000000 --- a/src/plugins/simple-pricing/mutations/updateProductVariantPrices.js +++ /dev/null @@ -1,65 +0,0 @@ -import SimpleSchema from "simpl-schema"; -import ReactionError from "@reactioncommerce/reaction-error"; - -const pricesInput = new SimpleSchema({ - compareAtPrice: { - type: Number, - optional: true - }, - price: { - type: Number, - optional: true - } -}); - -const inputSchema = new SimpleSchema({ - prices: { - type: pricesInput - }, - shopId: String, - variantId: String -}); - -/** - * @method updateProductVariantPrices - * @summary Updates the price fields on a product variant - * @param {Object} context - an object containing the per-request state - * @param {Object} input - Input arguments for the bulk operation - * @param {Object} input.prices - prices to update - * @param {Object} [input.prices.compareAtPrice] - variant compareAtPrice - * @param {Object} [input.prices.price] - variant price - * @param {String} input.variantId - variantId of product to update - * @param {String} input.shopId - shopId of shop product belongs to - * @return {Promise} updateProductVariant payload - */ -export default async function updateProductVariantPrices(context, input) { - inputSchema.validate(input); - const { appEvents, collections } = context; - const { Products } = collections; - const { prices, variantId, shopId } = input; - - // Check that user has permission to create product - await context.validatePermissions(`reaction:legacy:products:${variantId}`, "update:prices", { - shopId - }); - - const fields = Object.keys(prices); - if (fields.length === 0) throw new ReactionError("invalid-param", "At least one field to update must be provided"); - - const { value: updatedProductVariant } = await Products.findOneAndUpdate( - { _id: variantId, shopId, type: "variant" }, - { $set: { ...prices } }, - { returnOriginal: false } - ); - - if (!updatedProductVariant) throw new ReactionError("error-occurred", "Unable to update variant prices"); - - await appEvents.emit("afterVariantUpdate", { - fields, - productId: updatedProductVariant.ancestors[0], - productVariant: updatedProductVariant, - productVariantId: variantId - }); - - return updatedProductVariant; -} diff --git a/src/plugins/simple-pricing/policies.json b/src/plugins/simple-pricing/policies.json deleted file mode 100644 index a58f3f056ab..00000000000 --- a/src/plugins/simple-pricing/policies.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "description": "Product managers acting on specific entities.", - "subjects": [ "reaction:groups:product-managers" ], - "resources": [ "reaction:legacy:products:*" ], - "actions": [ - "update:prices" - ], - "effect": "allow" - } -] diff --git a/src/plugins/simple-pricing/preStartup.js b/src/plugins/simple-pricing/preStartup.js deleted file mode 100644 index 7b273f2fa48..00000000000 --- a/src/plugins/simple-pricing/preStartup.js +++ /dev/null @@ -1,11 +0,0 @@ -import { extendSimplePricingSchemas } from "./simpleSchemas.js"; - -/** - * @method preStartup - * @summary Simple pricing preStartup function. - * @param {Object} context - App context. - * @returns {undefined} - void, no return. - */ -export default function simplePricingPreStartup(context) { - extendSimplePricingSchemas(context.simpleSchemas); -} diff --git a/src/plugins/simple-pricing/queries/getVariantPrice.js b/src/plugins/simple-pricing/queries/getVariantPrice.js deleted file mode 100644 index 0486693fc86..00000000000 --- a/src/plugins/simple-pricing/queries/getVariantPrice.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @method getVariantPrice - * @summary This method returns the applicable price and currency code for a selected product. - * @param {Object} context - App context - * @param {Object} catalogVariant - A selected product variant. - * @param {String} currencyCode - The currency code in which to get price - * @returns {Object} - A cart item price value. - */ -export default function getVariantPrice(context, catalogVariant, currencyCode) { - if (!currencyCode) throw new Error("getVariantPrice received no currency code"); - if (!catalogVariant) throw new Error("getVariantPrice received no catalogVariant"); - if (!catalogVariant.pricing) throw new Error(`Catalog variant ${catalogVariant._id} has no pricing information saved`); - - return catalogVariant.pricing[currencyCode] || {}; -} diff --git a/src/plugins/simple-pricing/queries/index.js b/src/plugins/simple-pricing/queries/index.js deleted file mode 100644 index 0d4786781a4..00000000000 --- a/src/plugins/simple-pricing/queries/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import getVariantPrice from "./getVariantPrice.js"; - -export default { - getVariantPrice -}; diff --git a/src/plugins/simple-pricing/resolvers/CatalogProduct.js b/src/plugins/simple-pricing/resolvers/CatalogProduct.js deleted file mode 100644 index 03a48ce1a2a..00000000000 --- a/src/plugins/simple-pricing/resolvers/CatalogProduct.js +++ /dev/null @@ -1,5 +0,0 @@ -import xformPricingArray from "../util/xformPricingArray.js"; - -export default { - pricing: (node) => xformPricingArray(node.pricing) -}; diff --git a/src/plugins/simple-pricing/resolvers/CatalogProductVariant.js b/src/plugins/simple-pricing/resolvers/CatalogProductVariant.js deleted file mode 100644 index 03a48ce1a2a..00000000000 --- a/src/plugins/simple-pricing/resolvers/CatalogProductVariant.js +++ /dev/null @@ -1,5 +0,0 @@ -import xformPricingArray from "../util/xformPricingArray.js"; - -export default { - pricing: (node) => xformPricingArray(node.pricing) -}; diff --git a/src/plugins/simple-pricing/resolvers/Mutation/index.js b/src/plugins/simple-pricing/resolvers/Mutation/index.js deleted file mode 100644 index 01c1771a1ca..00000000000 --- a/src/plugins/simple-pricing/resolvers/Mutation/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import updateProductVariantPrices from "./updateProductVariantPrices.js"; - -export default { - updateProductVariantPrices -}; diff --git a/src/plugins/simple-pricing/resolvers/Mutation/updateProductVariantPrices.js b/src/plugins/simple-pricing/resolvers/Mutation/updateProductVariantPrices.js deleted file mode 100644 index eafbd90bb76..00000000000 --- a/src/plugins/simple-pricing/resolvers/Mutation/updateProductVariantPrices.js +++ /dev/null @@ -1,37 +0,0 @@ -import { decodeProductOpaqueId, decodeShopOpaqueId } from "../../xforms/id.js"; - -/** - * - * @method updateProductVariantPrices - * @summary Updates the price fields on a product variant - * @param {Object} _ - unused - * @param {Object} args - The input arguments - * @param {Object} args.input - mutation input object - * @param {String} args.input.clientMutationId - The mutation id - * @param {Object} args.input.prices - prices to update - * @param {Object} [args.input.prices.compareAtPrice] - variant compareAtPrice - * @param {Object} [args.input.prices.price] - variant price - * @param {String} args.input.shopId - shopId of shop product belongs to - * @param {String} args.input.variantId - Id of variant to update - * @param {Object} context - an object containing the per-request state - * @return {Promise} updateProductVariantPrices payload - */ -export default async function updateProductVariantPrices(_, { input }, context) { - const { - clientMutationId = null, - prices, - shopId, - variantId - } = input; - - const updatedVariant = await context.mutations.updateProductVariantPrices(context, { - variantId: decodeProductOpaqueId(variantId), - shopId: decodeShopOpaqueId(shopId), - prices - }); - - return { - clientMutationId, - variant: updatedVariant - }; -} diff --git a/src/plugins/simple-pricing/resolvers/Product.js b/src/plugins/simple-pricing/resolvers/Product.js deleted file mode 100644 index 40d1cc6bd20..00000000000 --- a/src/plugins/simple-pricing/resolvers/Product.js +++ /dev/null @@ -1,7 +0,0 @@ -import xformProductPricing from "../xforms/xformProductPricing.js"; -import xformProductPrice from "../xforms/xformProductPrice.js"; - -export default { - price: (node) => xformProductPrice(node), - pricing: (node, _, context) => xformProductPricing(node, context) -}; diff --git a/src/plugins/simple-pricing/resolvers/ProductPricingInfo.js b/src/plugins/simple-pricing/resolvers/ProductPricingInfo.js deleted file mode 100644 index be6865deaf1..00000000000 --- a/src/plugins/simple-pricing/resolvers/ProductPricingInfo.js +++ /dev/null @@ -1,24 +0,0 @@ -import getCurrencyDefinitionByCode from "@reactioncommerce/api-utils/getCurrencyDefinitionByCode.js"; -import getDisplayPrice from "../util/getDisplayPrice.js"; - -export default { - currency: (node) => getCurrencyDefinitionByCode(node.currencyCode), - compareAtPrice: ({ compareAtPrice: amount, currencyCode }) => { - if (typeof amount === "number" && amount > 0) { - return { amount, currencyCode }; - } - return null; - }, - displayPrice: (node) => { - if (node.displayPrice) { - // Operating in core catalog plugin mode. - // Use displayPrice directly from mongo. - // It was computed at publish time. - return node.displayPrice; - } - // Operating in catalog publisher mode. - // displayPrice was not computed ahead of time. - // Compute it on the fly now. - return getDisplayPrice(node.minPrice, node.maxPrice, getCurrencyDefinitionByCode(node.currencyCode)); - } -}; diff --git a/src/plugins/simple-pricing/resolvers/ProductPricingInfo.test.js b/src/plugins/simple-pricing/resolvers/ProductPricingInfo.test.js deleted file mode 100644 index 0a3863148ee..00000000000 --- a/src/plugins/simple-pricing/resolvers/ProductPricingInfo.test.js +++ /dev/null @@ -1,10 +0,0 @@ -import ProductPricingInfo from "./ProductPricingInfo.js"; - -test("displayPrice: catalog plugin mongo mode", () => { - expect(ProductPricingInfo.displayPrice({ displayPrice: "$Unit test 1" })).toEqual("$Unit test 1"); -}); - -test("displayPrice: catalog publisher resolver mode", () => { - const displayPrice = ProductPricingInfo.displayPrice({ minPrice: 1.01, maxPrice: 2.02, currencyCode: "USD" }); - expect(displayPrice).toEqual("$1.01 - $2.02"); -}); diff --git a/src/plugins/simple-pricing/resolvers/ProductVariant.js b/src/plugins/simple-pricing/resolvers/ProductVariant.js deleted file mode 100644 index 578c4140bae..00000000000 --- a/src/plugins/simple-pricing/resolvers/ProductVariant.js +++ /dev/null @@ -1,9 +0,0 @@ -import xformProductVariantPricing from "../xforms/xformProductVariantPricing.js"; -import xformProductVariantPrice from "../xforms/xformProductVariantPrice.js"; -import xformProductVariantCompareAtPrice from "../xforms/xformProductVariantCompareAtPrice.js"; - -export default { - compareAtPrice: (node) => xformProductVariantCompareAtPrice(node), - price: (node) => xformProductVariantPrice(node), - pricing: (node, _, context) => xformProductVariantPricing(node, context) -}; diff --git a/src/plugins/simple-pricing/resolvers/index.js b/src/plugins/simple-pricing/resolvers/index.js deleted file mode 100644 index ba3465ac739..00000000000 --- a/src/plugins/simple-pricing/resolvers/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import CatalogProduct from "./CatalogProduct.js"; -import CatalogProductVariant from "./CatalogProductVariant.js"; -import Mutation from "./Mutation/index.js"; -import ProductVariant from "./ProductVariant.js"; -import Product from "./Product.js"; -import ProductPricingInfo from "./ProductPricingInfo.js"; - -export default { - CatalogProduct, - CatalogProductVariant, - Mutation, - Product, - ProductVariant, - ProductPricingInfo -}; diff --git a/src/plugins/simple-pricing/schemas/index.js b/src/plugins/simple-pricing/schemas/index.js deleted file mode 100644 index 30096f92e54..00000000000 --- a/src/plugins/simple-pricing/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/simple-pricing/schemas/schema.graphql b/src/plugins/simple-pricing/schemas/schema.graphql deleted file mode 100644 index 35b971fc568..00000000000 --- a/src/plugins/simple-pricing/schemas/schema.graphql +++ /dev/null @@ -1,158 +0,0 @@ -"The product price or price range for a specific currency" -type ProductPricingInfo { - """ - A comparison price value, usually MSRP. If `price` is null, this will also be null. That is, - only purchasable variants will have a `compareAtPrice`. - """ - compareAtPrice: Money - - "The code for the currency these pricing details applies to" - currency: Currency! - - "Pricing converted to specified currency" - currencyExchangePricing( - "Code for the currency in which you want to see pricing info" - currencyCode: String! - ): CurrencyExchangeProductPricingInfo - - """ - UI should display this price. If a product has multiple potential prices depending on selected - variants and options, then this is a price range string such as "$3.95 - $6.99". It includes the currency - symbols. - """ - displayPrice: String! - - "The price of the most expensive possible variant+option combination" - maxPrice: Float! - - "The price of the least expensive possible variant+option combination" - minPrice: Float! - - """ - For variants with no options and for options, this will always be set to a price. For variants - with options and products, this will be `null`. There must be a price for a variant to be - added to a cart or purchased. Otherwise you would instead add one of its child options to a cart. - """ - price: Float -} - -"The product price or price range for a specific currency" -type CurrencyExchangeProductPricingInfo { - """ - A comparison price value, usually MSRP. If `price` is null, this will also be null. That is, - only purchasable variants will have a `compareAtPrice`. - """ - compareAtPrice: Money - - "The code for the currency these pricing details applies to" - currency: Currency! - - """ - UI should display this price. If a product has multiple potential prices depending on selected - variants and options, then this is a price range string such as "$3.95 - $6.99". It includes the currency - symbols. - """ - displayPrice: String! - - "The price of the most expensive possible variant+option combination" - maxPrice: Float! - - "The price of the least expensive possible variant+option combination" - minPrice: Float! - - """ - For variants with no options and for options, this will always be set to a price. For variants - with options and products, this will be `null`. There must be a price for a variant to be - added to a cart or purchased. Otherwise you would instead add one of its child options to a cart. - """ - price: Float -} - -"Product price range" -type ProductPriceRange { - "Maximum price in range" - max: Float - - "Minimum price in range" - min: Float - - "Price range display" - range: String -} - -extend type CatalogProduct { - "Price and related information, per currency" - pricing: [ProductPricingInfo]! -} - -extend type CatalogProductVariant { - "Price and related information, per currency" - pricing: [ProductPricingInfo]! -} - -extend type Product { - "Price range" - price: ProductPriceRange @deprecated(reason: "Use `pricing`") - - "Pricing information" - pricing: ProductPricingInfo! -} - -extend type ProductVariant { - "Compare at price of the variant" - compareAtPrice: Float @deprecated(reason: "Use `pricing`") - - "Price of the variant" - price: Float @deprecated(reason: "Use `pricing`") - - "Pricing information" - pricing: ProductPricingInfo! -} - -extend input ProductVariantInput { - "Variant compareAtPrice. DEPRECATED. Use the `updateProductVariantPrices` mutation to set product variant prices." - # @deprecated isn't allowed on input fields yet. See See https://github.com/graphql/graphql-spec/pull/525 - compareAtPrice: Float - - "Variant price. DEPRECATED. Use the `updateProductVariantPrices` mutation to set product variant prices." - # @deprecated isn't allowed on input fields yet. See See https://github.com/graphql/graphql-spec/pull/525 - price: Float -} - -"Input for the `updateProductVariantField` mutation" -input UpdateProductVariantPricesInput { - "Prices to update" - prices: ProductVariantPricesInput! - - "ID of shop that owns the variant to update" - shopId: ID! - - "ID of variant to update" - variantId: ID! -} - -"Mutation input for a product variant or option" -input ProductVariantPricesInput { - "Variant compareAtPrice" - compareAtPrice: Float - - "Variant price" - price: Float -} - -extend type Mutation { - "Update an existing product variants prices" - updateProductVariantPrices( - "Mutation input" - input: UpdateProductVariantPricesInput! - ): UpdateProductVariantPricesPayload! -} - -"Response payload of `updateProductVariantPricesField` mutation" -type UpdateProductVariantPricesPayload { - "The same string you sent with the mutation params, for matching mutation calls with their responses" - clientMutationId: String - - "Updated variant" - variant: ProductVariant! -} diff --git a/src/plugins/simple-pricing/simpleSchemas.js b/src/plugins/simple-pricing/simpleSchemas.js deleted file mode 100644 index 5fc2fd0d916..00000000000 --- a/src/plugins/simple-pricing/simpleSchemas.js +++ /dev/null @@ -1,83 +0,0 @@ -import SimpleSchema from "simpl-schema"; - -/** - * @name PriceRange - * @type {SimpleSchema} - * @memberof Schemas - * @property {String} range, default value: `"0.00"` - * @property {Number} min optional, default value: `0` - * @property {Number} max optional, default value: `0` - */ -export const PriceRange = new SimpleSchema({ - range: { - type: String, - defaultValue: "0.00" - }, - min: { - type: Number, - defaultValue: 0, - optional: true - }, - max: { - type: Number, - defaultValue: 0, - optional: true - } -}); - -const variantSchemaExtension = { - pricing: { - type: Object, - blackbox: true - } -}; - -/** - * @summary Extend SimpleSchemas from other plugins - * @param {Object} schemas SimpleSchema map from context - * @return {undefined} - */ -export function extendSimplePricingSchemas(schemas) { - const { - CatalogProduct, - CatalogProductOption, - CatalogProductVariant, - Product, - ProductVariant - } = schemas; - - Product.extend({ - price: { - label: "Price", - type: PriceRange - } - }); - - ProductVariant.extend({ - compareAtPrice: { - label: "Compare At Price", - type: Number, - optional: true, - min: 0, - defaultValue: 0.00 - }, - price: { - label: "Price", - type: Number, - defaultValue: 0.00, - min: 0, - optional: true - } - }); - - CatalogProduct.extend({ - pricing: { - type: Object, - blackbox: true - } - }); - - // Extend the catalog variant database schemas - CatalogProductVariant.extend(variantSchemaExtension); - CatalogProductOption.extend(variantSchemaExtension); -} diff --git a/src/plugins/simple-pricing/startup.js b/src/plugins/simple-pricing/startup.js deleted file mode 100644 index 7db48298d9b..00000000000 --- a/src/plugins/simple-pricing/startup.js +++ /dev/null @@ -1,73 +0,0 @@ -import collectionIndex from "@reactioncommerce/api-utils/collectionIndex.js"; -import getProductPriceRange from "./util/getProductPriceRange.js"; -import getVariantPriceRange from "./util/getVariantPriceRange.js"; - -const fieldsThatChangeAncestorPricing = ["isDeleted", "isVisible", "price"]; - -/** - * @method startup - * @summary Simple pricing startup function. - * @param {Object} context - App context. - * @returns {undefined} - void, no return. - */ -export default async function simplePricingStartup(context) { - const { appEvents, collections } = context; - const { Catalog, Products, Shops } = collections; - - // Add an index to support built-in minPrice sorting for the primary shop's - // default currency code only. - const shop = await Shops.findOne({ shopType: "primary" }); - if (shop && shop.currency) { - collectionIndex(Catalog, { - [`product.pricing.${shop.currency}.minPrice`]: 1, - _id: 1 - }); - } - - /** - * Updates the `price` field for a Products collection product based on its - * updated variants. - * @param {Object} variant The updated variant object - * @returns {undefined} - */ - async function updateProductPrice(variant) { - const productDocs = await Products.find({ - $or: [ - { _id: { $in: variant.ancestors } }, - { ancestors: { $in: variant.ancestors } } - ] - }).toArray(); - - // productDocs has all sibling and ancestor docs from Products. - // We now want to update `price` field only for those that are - // not siblings. - /* eslint-disable no-await-in-loop */ - for (const productDoc of productDocs) { - if (productDoc.ancestors.length < variant.ancestors.length) { - let price; - if (productDoc.ancestors.length === 0) { - price = getProductPriceRange(productDoc._id, productDocs); - } else { - price = getVariantPriceRange(productDoc._id, productDocs); - } - - await Products.updateOne({ _id: productDoc._id }, { - $set: { price } - }); - } - } - /* eslint-enable no-await-in-loop */ - } - - // Listen for variant soft deletion from the Products collection, and recalculate - // the price range for the parent variant and product - appEvents.on("afterVariantSoftDelete", async ({ variant }) => updateProductPrice(variant)); - - // Listen for variant price changes in the Products collection, and recalculate - // the price range for the parent variant and product - appEvents.on("afterVariantUpdate", async ({ productVariant, fields }) => { - if (!fields.some((field) => fieldsThatChangeAncestorPricing.includes(field))) return; - - await updateProductPrice(productVariant); - }); -} diff --git a/src/plugins/simple-pricing/util/getDisplayPrice.js b/src/plugins/simple-pricing/util/getDisplayPrice.js deleted file mode 100644 index 6481186fd05..00000000000 --- a/src/plugins/simple-pricing/util/getDisplayPrice.js +++ /dev/null @@ -1,37 +0,0 @@ -import accounting from "accounting-js"; - -/** - * @name getDisplayPrice - * @method - * @summary Returns a price for front-end display in the given currency - * @param {Number} minPrice Minimum price - * @param {Number} maxPrice Maximum price - * @param {Object} currencyInfo Currency object from Reaction shop schema - * @returns {String} Display price with currency symbol(s) - */ -export default function getDisplayPrice(minPrice, maxPrice, currencyInfo = { symbol: "" }) { - let displayPrice; - - if (minPrice === maxPrice) { - // Display 1 price (min = max) - displayPrice = accounting.formatMoney(minPrice, currencyInfo); - } else { - // Display range - let minFormatted; - - // Account for currencies where only one currency symbol should be displayed. Ex: 680,18 - 1 359,68 руб. - if (currencyInfo.where === "right") { - const modifiedCurrencyInfo = Object.assign({}, currencyInfo, { - symbol: "" - }); - minFormatted = accounting.formatMoney(minPrice, modifiedCurrencyInfo).trim(); - } else { - minFormatted = accounting.formatMoney(minPrice, currencyInfo); - } - - const maxFormatted = accounting.formatMoney(maxPrice, currencyInfo); - displayPrice = `${minFormatted} - ${maxFormatted}`; - } - - return displayPrice; -} diff --git a/src/plugins/simple-pricing/util/getDisplayPrice.test.js b/src/plugins/simple-pricing/util/getDisplayPrice.test.js deleted file mode 100644 index b521699ff5b..00000000000 --- a/src/plugins/simple-pricing/util/getDisplayPrice.test.js +++ /dev/null @@ -1,33 +0,0 @@ -import getDisplayPrice from "./getDisplayPrice.js"; - -const mockUSDCurrencyInfo = { - enabled: true, - format: "%s%v", - symbol: "$", - rate: 1 -}; -const minUSDPrice = 10; -const maxUSDPrice = 19.99; -const expectedUSDDisplayPrice = "$10.00 - $19.99"; - -const mockRUBCurrencyInfo = { - enabled: true, - format: "%v %s", - symbol: "руб.", - decimal: ",", - thousand: " ", - scale: 0, - where: "right", - rate: 68.017871 -}; -const minRUBPrice = 680.18; -const maxRUBPrice = 1359.68; -const expectedRUBDisplayPrice = "680,18 - 1 359,68 руб."; - -test("getDisplayPrice correctly formats USD price range", () => { - expect(getDisplayPrice(minUSDPrice, maxUSDPrice, mockUSDCurrencyInfo)).toBe(expectedUSDDisplayPrice); -}); - -test("getDisplayPrice correctly formats RUB price range", () => { - expect(getDisplayPrice(minRUBPrice, maxRUBPrice, mockRUBCurrencyInfo)).toBe(expectedRUBDisplayPrice); -}); diff --git a/src/plugins/simple-pricing/util/getMinPriceSortByFieldPath.js b/src/plugins/simple-pricing/util/getMinPriceSortByFieldPath.js deleted file mode 100644 index b4f03f1ff95..00000000000 --- a/src/plugins/simple-pricing/util/getMinPriceSortByFieldPath.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param {Object} context - an object containing the per-request state - * @param {Object} connectionArgs - an object of all arguments that were sent by the client - * @param {String} connectionArgs.sortPriceByCurrencyCode - currency code - * @returns {Number} minimum price - */ -export default function getMinPriceSortByFieldPathForSimplePricing(context, { connectionArgs }) { - const { sortByPriceCurrencyCode } = connectionArgs || {}; - - if (typeof sortByPriceCurrencyCode !== "string") { - throw new Error("sortByPriceCurrencyCode is required when sorting by minPrice"); - } - - return `product.pricing.${sortByPriceCurrencyCode}.minPrice`; -} diff --git a/src/plugins/simple-pricing/util/getPriceRange.js b/src/plugins/simple-pricing/util/getPriceRange.js deleted file mode 100644 index fd1c9dfeb71..00000000000 --- a/src/plugins/simple-pricing/util/getPriceRange.js +++ /dev/null @@ -1,38 +0,0 @@ -import getDisplayPrice from "./getDisplayPrice.js"; - -/** - * - * @method getPriceRange - * @summary Get Price object from array of Product prices - * @param {Array} prices - Array of Product price properties - * @param {Object} [currencyInfo] - A currency object in Reaction schema - * @returns {Promise} PriceRange object - */ -export default function getPriceRange(prices, currencyInfo) { - if (prices.length === 1) { - const price = prices[0]; - return { - range: getDisplayPrice(price, price, currencyInfo), - min: price, - max: price - }; - } - - let priceMin = Number.POSITIVE_INFINITY; - let priceMax = Number.NEGATIVE_INFINITY; - - prices.forEach((price) => { - if (price < priceMin) { - priceMin = price; - } - if (price > priceMax) { - priceMax = price; - } - }); - - return { - range: getDisplayPrice(priceMin, priceMax, currencyInfo), - min: priceMin, - max: priceMax - }; -} diff --git a/src/plugins/simple-pricing/util/getPriceRange.test.js b/src/plugins/simple-pricing/util/getPriceRange.test.js deleted file mode 100644 index 2cec2e6cf87..00000000000 --- a/src/plugins/simple-pricing/util/getPriceRange.test.js +++ /dev/null @@ -1,61 +0,0 @@ -import getPriceRange from "./getPriceRange.js"; - -const mockZeroPrice = [0]; -const mockSinglePrice = [5.99]; -const mockSamePrices = [2.99, 2.99]; -const mockDifferentPrices = [2.99, 15.99]; -const mockMoreDifferentPrices = [...mockDifferentPrices, 8.99, 20.99]; - -// expect price object with zero values -test("expect price object with zero values when provided price values of 0", () => { - const spec = getPriceRange(mockZeroPrice); - const success = { - range: "0.00", - max: 0, - min: 0 - }; - expect(spec).toEqual(success); -}); - -// expect price object to have same value when only one price -test("expect price object to have same value when only one price", () => { - const spec = getPriceRange(mockSinglePrice); - const success = { - range: "5.99", - max: 5.99, - min: 5.99 - }; - expect(spec).toEqual(success); -}); - -// expect price object to have same value when provided prices are the same -test("expect price object to have same value when provided prices are the same", () => { - const spec = getPriceRange(mockSamePrices); - const success = { - range: "2.99", - max: 2.99, - min: 2.99 - }; - expect(spec).toEqual(success); -}); - -// expect price object with uniq range, min and max when provided pries are all different -test("expect price object with uniq range, min and max when provided pries are all different", () => { - const spec = getPriceRange(mockDifferentPrices); - const success = { - range: "2.99 - 15.99", - max: 15.99, - min: 2.99 - }; - expect(spec).toEqual(success); -}); - -test("expect price object with uniq range, min and max when provided pries are all different", () => { - const spec = getPriceRange(mockMoreDifferentPrices); - const success = { - range: "2.99 - 20.99", - max: 20.99, - min: 2.99 - }; - expect(spec).toEqual(success); -}); diff --git a/src/plugins/simple-pricing/util/getProductPriceRange.js b/src/plugins/simple-pricing/util/getProductPriceRange.js deleted file mode 100644 index 279537fdf71..00000000000 --- a/src/plugins/simple-pricing/util/getProductPriceRange.js +++ /dev/null @@ -1,25 +0,0 @@ -import getPriceRange from "./getPriceRange.js"; -import getVariantPriceRange from "./getVariantPriceRange.js"; - -/** - * - * @method getProductPriceRange - * @summary Get the PriceRange object for a Product by ID - * @param {String} productId - A product ID - * @param {Object[]} variants - A list of documents from a Products.find call - * @returns {Object} Product PriceRange object - */ -export default function getProductPriceRange(productId, variants) { - const visibleVariants = variants.filter((option) => option.ancestors.length === 1 && - option.isVisible && !option.isDeleted); - - // If there are no visible variants, set price range to 0 - if (visibleVariants.length === 0) return getPriceRange([0]); - - const variantPrices = []; - visibleVariants.forEach((variant) => { - const { min, max } = getVariantPriceRange(variant._id, variants); - variantPrices.push(min, max); - }); - return getPriceRange(variantPrices); -} diff --git a/src/plugins/simple-pricing/util/getProductPriceRange.test.js b/src/plugins/simple-pricing/util/getProductPriceRange.test.js deleted file mode 100644 index c06c8f2acb5..00000000000 --- a/src/plugins/simple-pricing/util/getProductPriceRange.test.js +++ /dev/null @@ -1,112 +0,0 @@ -import { rewire as rewire$getVariantPriceRange, restore as restore$getVariantPriceRange } from "./getVariantPriceRange.js"; -import getProductPriceRange from "./getProductPriceRange.js"; - -const mockGetVariantPriceRange = jest.fn().mockName("getVariantPriceRange"); - -const internalShopId = "123"; -const internalCatalogProductId = "999"; -const internalVariantIds = ["875", "874"]; - -const createdAt = new Date("2018-04-16T15:34:28.043Z"); -const updatedAt = new Date("2018-04-17T15:34:28.043Z"); - -const mockVariants = [ - { - _id: internalVariantIds[0], - ancestors: [internalCatalogProductId], - barcode: "barcode", - createdAt, - height: 0, - index: 0, - isDeleted: false, - isVisible: true, - length: 0, - metafields: [ - { - value: "value", - namespace: "namespace", - description: "description", - valueType: "valueType", - scope: "scope", - key: "key" - } - ], - minOrderQuantity: 0, - optionTitle: "Untitled Option", - originCountry: "US", - price: 0, - shopId: internalShopId, - sku: "sku", - taxCode: "0000", - taxDescription: "taxDescription", - title: "Small Concrete Pizza", - updatedAt, - variantId: internalVariantIds[0], - weight: 0, - width: 0 - }, - { - _id: internalVariantIds[1], - ancestors: [internalCatalogProductId, internalVariantIds[0]], - barcode: "barcode", - height: 2, - index: 0, - isDeleted: false, - isVisible: true, - length: 2, - metafields: [ - { - value: "value", - namespace: "namespace", - description: "description", - valueType: "valueType", - scope: "scope", - key: "key" - } - ], - minOrderQuantity: 0, - optionTitle: "Awesome Soft Bike", - originCountry: "US", - price: 2.99, - shopId: internalShopId, - sku: "sku", - taxCode: "0000", - taxDescription: "taxDescription", - title: "One pound bag", - variantId: internalVariantIds[1], - weight: 2, - width: 2 - } -]; - -const mockPriceRange = { - range: "2.99 - 5.99", - max: 5.99, - min: 2.99 -}; - -beforeAll(() => { - rewire$getVariantPriceRange(mockGetVariantPriceRange); -}); - -afterAll(() => { - restore$getVariantPriceRange(); -}); - -// expect a legit price range -test("expect to return a promise that resolves to a product price object", () => { - mockGetVariantPriceRange - .mockReturnValueOnce(mockPriceRange) - .mockReturnValueOnce(mockPriceRange); - const spec = getProductPriceRange("999", mockVariants); - expect(spec).toEqual(mockPriceRange); -}); - -// expect an empty price range -test("expect to throw an error if no product is found", () => { - try { - getProductPriceRange("badID", mockVariants); - } catch (error) { - expect(error).toEqual("Product not found"); - } -}); diff --git a/src/plugins/simple-pricing/util/getVariantPriceRange.js b/src/plugins/simple-pricing/util/getVariantPriceRange.js deleted file mode 100644 index 6b4fc76e958..00000000000 --- a/src/plugins/simple-pricing/util/getVariantPriceRange.js +++ /dev/null @@ -1,30 +0,0 @@ -import getPriceRange from "./getPriceRange.js"; - -/** - * - * @method getVariantPriceRange - * @summary Create a Product PriceRange object by taking the lowest variant price and the highest variant - * price to create the PriceRange. If only one variant use that variant's price to create the PriceRange - * @param {String} variantId - A product variant ID. - * @param {Object[]} variants - A list of documents from a Products.find call - * @returns {Object} Product PriceRange object - */ -export default function getVariantPriceRange(variantId, variants) { - const visibleOptions = variants.filter((option) => option.ancestors.includes(variantId) && - option.isVisible && !option.isDeleted); - - const allOptions = variants.filter((option) => option.ancestors.includes(variantId)); - - // If the variant has options, but they are not visible return a price range of 0 - if (allOptions.length && visibleOptions.length === 0) { - return getPriceRange([0]); - } - - if (visibleOptions.length === 0) { - const thisVariant = variants.find((option) => option._id === variantId); - return getPriceRange([(thisVariant && thisVariant.price) || 0]); - } - - const prices = visibleOptions.map((option) => option.price); - return getPriceRange(prices); -} diff --git a/src/plugins/simple-pricing/util/getVariantPriceRange.test.js b/src/plugins/simple-pricing/util/getVariantPriceRange.test.js deleted file mode 100644 index 2a1e8544210..00000000000 --- a/src/plugins/simple-pricing/util/getVariantPriceRange.test.js +++ /dev/null @@ -1,73 +0,0 @@ -import getVariantPriceRange from "./getVariantPriceRange.js"; - -const internalCatalogProductId = "999"; -const internalVariantIds = ["875", "874", "873"]; - -const mockVariants = [ - { - _id: internalVariantIds[0], - ancestors: [internalCatalogProductId], - isDeleted: false, - isVisible: true, - price: 2.99 - }, - { - _id: internalVariantIds[1], - ancestors: [internalCatalogProductId, internalVariantIds[0]], - isDeleted: false, - isVisible: true, - price: 5.99 - }, - { - _id: internalVariantIds[2], - ancestors: [internalCatalogProductId, internalVariantIds[0]], - isDeleted: false, - isVisible: true, - price: 3.99 - } -]; - -// expect topVariant price if no children -test("expect topVariants price string if no child variants", () => { - const spec = getVariantPriceRange(internalVariantIds[0], mockVariants.slice(0, 1)); - const success = { - range: "2.99", - max: 2.99, - min: 2.99 - }; - expect(spec).toEqual(success); -}); - -// expect child variant price if only one child variant -test("expect child variant price string if only one child variant", () => { - const spec = getVariantPriceRange(internalVariantIds[0], mockVariants.slice(0, 2)); - const success = { - range: "5.99", - max: 5.99, - min: 5.99 - }; - expect(spec).toEqual(success); -}); - -// expect a price rang string of the min price and max price -test("expect price range string if variants have different prices", () => { - const spec = getVariantPriceRange(internalVariantIds[0], mockVariants); - const success = { - range: "3.99 - 5.99", - max: 5.99, - min: 3.99 - }; - expect(spec).toEqual(success); -}); - -// expect variant min price if min and max price are equal -test("expect variant price string if variants have same price", () => { - mockVariants[2].price = 5.99; - const spec = getVariantPriceRange(internalVariantIds[0], mockVariants); - const success = { - range: "5.99", - max: 5.99, - min: 5.99 - }; - expect(spec).toEqual(success); -}); diff --git a/src/plugins/simple-pricing/util/mutateNewProductBeforeCreate.js b/src/plugins/simple-pricing/util/mutateNewProductBeforeCreate.js deleted file mode 100644 index 691987ebc4b..00000000000 --- a/src/plugins/simple-pricing/util/mutateNewProductBeforeCreate.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @summary Mutates a new top-level Product being created - * @param {Object} product Product object to mutate - * @returns {undefined} - */ -export default function mutateNewProductBeforeCreateForSimplePricing(product) { - if (!product.price) { - product.price = { - range: "0.00 - 0.00", - min: 0, - max: 0 - }; - } -} diff --git a/src/plugins/simple-pricing/util/mutateNewVariantBeforeCreate.js b/src/plugins/simple-pricing/util/mutateNewVariantBeforeCreate.js deleted file mode 100644 index 354856d2ba4..00000000000 --- a/src/plugins/simple-pricing/util/mutateNewVariantBeforeCreate.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @summary Mutates a new top-level Product being created - * @param {Object} variant Variant product object to mutate - * @returns {undefined} - */ -export default function mutateNewVariantBeforeCreateForSimplePricing(variant) { - if (!variant.price) variant.price = 0; -} diff --git a/src/plugins/simple-pricing/util/publishProductToCatalog.js b/src/plugins/simple-pricing/util/publishProductToCatalog.js deleted file mode 100644 index 553e68412e8..00000000000 --- a/src/plugins/simple-pricing/util/publishProductToCatalog.js +++ /dev/null @@ -1,78 +0,0 @@ -import CurrencyDefinitions from "@reactioncommerce/api-utils/CurrencyDefinitions.js"; -import getPriceRange from "./getPriceRange.js"; - -/** - * @summary Get the pricing object - * @param {Object} doc The Products collection document - * @param {Object} priceInfo A price range object, with `range`, `min`, and `max` fields - * @returns {Object} Object for `pricing` field for product, variant, or option - */ -function getPricingObject(doc, priceInfo) { - return { - compareAtPrice: doc.compareAtPrice || null, - displayPrice: priceInfo.range, - maxPrice: priceInfo.max, - minPrice: priceInfo.min, - price: typeof doc.price === "number" ? doc.price : null - }; -} - -/** - * @summary Functions of type "publishProductToCatalog" are expected to mutate the provided catalogProduct. - * This function is called every time a product is published to a catalog. - * @param {Object} catalogProduct The catalog product being built, to save in the Catalog collection. Mutates this. - * @param {Object} input Input object - * @param {Object} input.product The product being published, in Products collection schema - * @param {Object} input.shop The shop that owns the product being published, in Shops collection schema - * @param {Object[]} input.variants All variants and options of the product being published, in Products collection schema - * @returns {undefined} No return. Mutates `catalogProduct` object. - */ -export default function publishProductToCatalogForSimplePricing(catalogProduct, { product, shop, variants }) { - const shopCurrencyCode = shop.currency; - const shopCurrencyInfo = CurrencyDefinitions[shopCurrencyCode]; - - const prices = []; - - for (const variant of catalogProduct.variants) { - const { options } = variant; - - const sourceVariant = variants.find((productVariant) => productVariant._id === variant.variantId); - if (!sourceVariant) throw new Error(`Variant ${variant.variantId} not found in variants list`); - - let variantPriceInfo; - if (Array.isArray(options) && options.length) { - const optionPrices = []; - for (const option of options) { - const sourceOptionVariant = variants.find((productVariant) => productVariant._id === option.variantId); - if (!sourceOptionVariant) throw new Error(`Variant ${option.variantId} not found in variants list`); - - optionPrices.push(sourceOptionVariant.price); - const optionPriceInfo = getPriceRange([sourceOptionVariant.price], shopCurrencyInfo); - - // Mutate the option, adding pricing field - option.pricing = { - [shopCurrencyCode]: getPricingObject(sourceOptionVariant, optionPriceInfo) - }; - } - variantPriceInfo = getPriceRange(optionPrices, shopCurrencyInfo); - } else { - variantPriceInfo = getPriceRange([sourceVariant.price], shopCurrencyInfo); - } - prices.push(variantPriceInfo.min, variantPriceInfo.max); - - // Mutate the variant, adding pricing field - variant.pricing = { - [shopCurrencyCode]: getPricingObject(sourceVariant, variantPriceInfo) - }; - } - - const productPriceInfo = getPriceRange(prices, shopCurrencyInfo); - - // Mutate the product, adding pricing field - catalogProduct.pricing = { - [shopCurrencyCode]: getPricingObject(product, productPriceInfo) - }; - - // Make extra sure the product price is always `null` - catalogProduct.pricing[shopCurrencyCode].price = null; -} diff --git a/src/plugins/simple-pricing/util/xformPricingArray.js b/src/plugins/simple-pricing/util/xformPricingArray.js deleted file mode 100644 index bcff1927b8d..00000000000 --- a/src/plugins/simple-pricing/util/xformPricingArray.js +++ /dev/null @@ -1,12 +0,0 @@ -import { createRequire } from "module"; - -const require = createRequire(import.meta.url); - -const { assoc, compose, map, toPairs } = require("ramda"); - -// add `currencyCode` keys to each pricing info object -const xformPricingEntry = ([k, v]) => compose(assoc("currencyCode", k))(v); - -// map over all provided pricing info, provided in the format stored in our Catalog collection, -// and convert them to an array -export default compose(map(xformPricingEntry), toPairs); diff --git a/src/plugins/simple-pricing/xforms/id.js b/src/plugins/simple-pricing/xforms/id.js deleted file mode 100644 index 23ffe002218..00000000000 --- a/src/plugins/simple-pricing/xforms/id.js +++ /dev/null @@ -1,13 +0,0 @@ -import decodeOpaqueIdForNamespace from "@reactioncommerce/api-utils/decodeOpaqueIdForNamespace.js"; -import encodeOpaqueId from "@reactioncommerce/api-utils/encodeOpaqueId.js"; - -const namespaces = { - Product: "reaction/product", - Shop: "reaction/shop" -}; - -export const encodeProductOpaqueId = encodeOpaqueId(namespaces.Product); -export const encodeShopOpaqueId = encodeOpaqueId(namespaces.Shop); - -export const decodeProductOpaqueId = decodeOpaqueIdForNamespace(namespaces.Product); -export const decodeShopOpaqueId = decodeOpaqueIdForNamespace(namespaces.Shop); diff --git a/src/plugins/simple-pricing/xforms/xformProductPrice.js b/src/plugins/simple-pricing/xforms/xformProductPrice.js deleted file mode 100644 index 1ee7d854542..00000000000 --- a/src/plugins/simple-pricing/xforms/xformProductPrice.js +++ /dev/null @@ -1,7 +0,0 @@ -import Logger from "@reactioncommerce/logger"; - -export default (node) => { - Logger.warn("Using deprecated field `price` on type `Product`, please use field `pricing` instead."); - - return node.price; -}; diff --git a/src/plugins/simple-pricing/xforms/xformProductPricing.js b/src/plugins/simple-pricing/xforms/xformProductPricing.js deleted file mode 100644 index 1fa456b9d8c..00000000000 --- a/src/plugins/simple-pricing/xforms/xformProductPricing.js +++ /dev/null @@ -1,17 +0,0 @@ -import getCurrencyDefinitionByCode from "@reactioncommerce/api-utils/getCurrencyDefinitionByCode.js"; -import getDisplayPrice from "../util/getDisplayPrice.js"; - -export default async (node, context) => { - const { price } = node; - const { Shops } = context.collections; - const shop = await Shops.findOne({ _id: node.shopId }, { projection: { currency: 1 } }); - const currencyDefinition = getCurrencyDefinitionByCode(shop.currency); - - const pricing = { - displayPrice: getDisplayPrice(price.min, price.max, currencyDefinition), - maxPrice: price.max, - minPrice: price.min - }; - - return pricing; -}; diff --git a/src/plugins/simple-pricing/xforms/xformProductVariantCompareAtPrice.js b/src/plugins/simple-pricing/xforms/xformProductVariantCompareAtPrice.js deleted file mode 100644 index 2e687053693..00000000000 --- a/src/plugins/simple-pricing/xforms/xformProductVariantCompareAtPrice.js +++ /dev/null @@ -1,7 +0,0 @@ -import Logger from "@reactioncommerce/logger"; - -export default (node) => { - Logger.warn("Using deprecated field `compareAtPrice` on type `ProductVariant`, please use field `pricing` instead."); - - return node.compareAtPrice; -}; diff --git a/src/plugins/simple-pricing/xforms/xformProductVariantPrice.js b/src/plugins/simple-pricing/xforms/xformProductVariantPrice.js deleted file mode 100644 index b0db0cade84..00000000000 --- a/src/plugins/simple-pricing/xforms/xformProductVariantPrice.js +++ /dev/null @@ -1,19 +0,0 @@ -import Logger from "@reactioncommerce/logger"; - -export default (node) => { - let { price } = node; - // If a variant has options, then its price will become an object - // that includes the following props: min, max and range. This change - // in the underlying data structure will break the API as the variant - // field `price` will attempt to return an `Object` for a field that previously - // expected a `Float`. This field resolver mitigates this problem by returning - // a `Float` as expected. This will prevent the API and UI from breaking. Further, - // this field, is now deprecated in favor of the new `pricing` field. - if (typeof price === "object") { - price = null; - } - - Logger.warn("Using deprecated field `price` on type `ProductVariant`, please use field `pricing` instead."); - - return price; -}; diff --git a/src/plugins/simple-pricing/xforms/xformProductVariantPricing.js b/src/plugins/simple-pricing/xforms/xformProductVariantPricing.js deleted file mode 100644 index 7057fb9c993..00000000000 --- a/src/plugins/simple-pricing/xforms/xformProductVariantPricing.js +++ /dev/null @@ -1,31 +0,0 @@ -import accounting from "accounting-js"; -import getCurrencyDefinitionByCode from "@reactioncommerce/api-utils/getCurrencyDefinitionByCode.js"; -import getDisplayPrice from "../util/getDisplayPrice.js"; - -export default async (node, context) => { - const { Shops } = context.collections; - const shop = await Shops.findOne({ _id: node.shopId }, { projection: { currency: 1 } }); - const currencyDefinition = getCurrencyDefinitionByCode(shop.currency); - - let pricing = {}; - const { price } = node; - if (typeof price === "object") { - pricing = { - compareAtPrice: null, - displayPrice: getDisplayPrice(price.min, price.max, currencyDefinition), - maxPrice: price.max, - minPrice: price.min, - price: null - }; - } else { - pricing = { - compareAtPrice: node.compareAtPrice || 0, - displayPrice: accounting.formatMoney(price, currencyDefinition.symbol), - maxPrice: price || 0, - minPrice: price || 0, - price: price || 0 - }; - } - - return pricing; -}; diff --git a/tests/util/factory.js b/tests/util/factory.js index bd7b0364ad5..32bb9c52dd8 100644 --- a/tests/util/factory.js +++ b/tests/util/factory.js @@ -55,6 +55,10 @@ import { Payment } from "@reactioncommerce/api-plugin-orders/src/simpleSchemas.js"; +import { + extendSimplePricingSchemas +} from "@reactioncommerce/api-plugin-pricing-simple/src/simpleSchemas.js"; + import { Product, ProductVariant @@ -92,10 +96,6 @@ import { extendTaxesSchemas } from "../../src/core-services/taxes/simpleSchemas.js"; -import { - extendSimplePricingSchemas -} from "../../src/plugins/simple-pricing/simpleSchemas.js"; - import FulfillmentMethod from "../../src/plugins/shipping-rates/util/methodSchema.js"; import Restriction from "../../src/plugins/shipping-rates/util/restrictionSchema.js";