diff --git a/.changeset/real-pianos-eat.md b/.changeset/real-pianos-eat.md new file mode 100644 index 0000000000..de3137cfa7 --- /dev/null +++ b/.changeset/real-pianos-eat.md @@ -0,0 +1,5 @@ +--- +"@medusajs/pricing": patch +--- + +fix(pricing): pricing context calculations only takes into account existing rule attributes diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index 8cf153e2fc..d8dde6d158 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -613,6 +613,15 @@ medusaIntegrationTestRunner({ }) ) + await api.post( + `/store/carts/${cart.id}/line-items`, + { + variant_id: product.variants[0].id, + quantity: 100, + }, + storeHeaders + ) + let cartAfterExpensiveShipping = ( await api.post( `/store/carts/${cart.id}/shipping-methods`, @@ -631,7 +640,7 @@ medusaIntegrationTestRunner({ }), ]), payment_collection: expect.objectContaining({ - amount: 6398, + amount: 156398, }), }) ) diff --git a/packages/modules/pricing/src/repositories/pricing.ts b/packages/modules/pricing/src/repositories/pricing.ts index 96ee57a903..70ad954ce7 100644 --- a/packages/modules/pricing/src/repositories/pricing.ts +++ b/packages/modules/pricing/src/repositories/pricing.ts @@ -4,6 +4,7 @@ import { MedusaError, MikroOrmBase, PriceListStatus, + promiseAll, } from "@medusajs/framework/utils" import { @@ -60,12 +61,38 @@ export class PricingRepository return [] } - const flattenedContext = Object.entries( - flattenObjectToKeyValuePairs(context) - ).filter( - ([key, value]) => - (isPresent(value) && !Array.isArray(value)) || - (Array.isArray(value) && value.flat(1).length) + // We query the rule tables to get all whitelisted rule attributes + // This will help cleanup the query and do a db query on only necessary rule attributes. + const priceRuleAttributesQuery = knex("price_rule") + .distinct("attribute") + .pluck("attribute") + + const priceListRuleAttributesQuery = knex("price_list_rule") + .distinct("attribute") + .pluck("attribute") + + const [ruleAttributes, priceListRuleAttributes] = await promiseAll([ + priceRuleAttributesQuery, + priceListRuleAttributesQuery, + ]) + + const allowedRuleAttributes = [ + ...ruleAttributes, + ...priceListRuleAttributes, + ] + + const flattenedKeyValuePairs = flattenObjectToKeyValuePairs(context) + + const flattenedContext = Object.entries(flattenedKeyValuePairs).filter( + ([key, value]) => { + const isValuePresent = !Array.isArray(value) && isPresent(value) + const isArrayPresent = Array.isArray(value) && value.flat(1).length + + return ( + allowedRuleAttributes.includes(key) && + (isValuePresent || isArrayPresent) + ) + } ) // Gets all the prices where rules match for each of the contexts