Prices Calculation

In this guide, you'll learn how prices are calculated when you use the calculatePrices method of the Pricing Module's main service.

calculatePrices Method#

The calculatePrices method accepts the ID of one or more price sets and a context as parameters.

It returns a price object with the best-matching price for each price set.

The calculatePrices method is useful for retrieving the prices of a product variant or a shipping option that matches a specific context, such as a currency code, in your backend customizations.

Calculation Context#

The calculation context is an optional object passed as the second parameter to the calculatePrices method. It accepts rules as key-value pairs to restrict the selected prices in the price set.

For example:

Code
1const price = await pricingModuleService.calculatePrices(2  { id: [priceSetId] },3  {4    context: {5      currency_code: "eur",6      region_id: "reg_123",7    },8  }9)

In this example, you retrieve the prices in a price set for the specified currency code and region ID.

Returned Price Object#

For each price set, the calculatePrices method selects two prices:

  • A calculated price: Either a price that belongs to a price list and best matches the specified context, or the same as the original price.
  • An original price, which is either:
    • The same price as the calculated price if it belongs to a price list of type override;
    • Otherwise, a price that doesn't belong to a price list and best matches the specified context.

Both prices are returned in an object with the following properties:

idstring
The ID of the price set from which the price was selected.
is_calculated_price_price_listboolean
Whether the calculated price belongs to a price list.
calculated_amountnumber
The amount of the calculated price, or null if there isn't a calculated price. This is the amount shown to the customer.
is_original_price_price_listboolean
Whether the original price belongs to a price list.
original_amountnumber
The amount of the original price, or null if there isn't an original price. This amount is useful for comparing with the calculated_amount, such as to check for a discounted value.
currency_codestring
The currency code of the calculated price, or null if there isn't a calculated price.
is_calculated_price_tax_inclusiveboolean
Whether the calculated price is tax inclusive. Learn more about tax inclusivity in this document
is_original_price_tax_inclusiveboolean
Whether the original price is tax inclusive. Learn more about tax inclusivity in this document
calculated_priceobject
The calculated price's price details.
original_priceobject
The original price's price details.

Original Price Selection Logic#

When the calculated price isn't from a price list of type override, the original price is selected based on the following logic:

Diagram illustrating the original price selection logic

  1. If the context doesn't have any rules, select the default price (the price without any rules).
  2. If the context has rules and there's a price that matches all the rules, select that price.
  3. If the context has rules and there's no price that matches all the rules:
    • Find all the prices whose rules match at least one rule in the context.
    • Sort the matched prices by the number of matched rules in descending order.
    • Select the first price in the sorted list (the one that matches the most rules).

Examples#

Consider the following price set, which has a default price, prices with rules, and tiered pricing:

Code
1const priceSet = await pricingModuleService.createPriceSets({2  prices: [3    // default price4    {5      amount: 5,6      currency_code: "eur",7      rules: {},8    },9    // prices with rules10    {11      amount: 4,12      currency_code: "eur",13      rules: {14        region_id: "reg_123",15      },16    },17    {18      amount: 4.5,19      currency_code: "eur",20      rules: {21        city: "krakow",22      },23    },24    {25      amount: 3.5,26      currency_code: "eur",27      rules: {28        city: "warsaw",29        region_id: "reg_123",30      },31    },32    // tiered price33    {34      amount: 2,35      currency_code: "eur",36      min_quantity: 100,37    },38  ],39})

Default Price Selection#

Code
1const price = await pricingModuleService.calculatePrices(2  { id: [priceSet.id] },3  {4    context: {5      currency_code: "eur"6    }7  }8)

Calculate Prices with Exact Match#

Code
1const price = await pricingModuleService.calculatePrices(2  { id: [priceSet.id] },3  {4    context: {5      currency_code: "eur",6      region_id: "reg_123",7      city: "warsaw"8    }9  }10)

Calculate Prices with Partial Match#

Code
1const price = await pricingModuleService.calculatePrices(2  { id: [priceSet.id] },3  {4    context: {5      currency_code: "eur",6      region_id: "reg_123",7      city: "krakow"8    }9  }10)

Tiered Pricing Selection#

Code
1const price = await pricingModuleService.calculatePrices(2  { id: [priceSet.id] },3  {4    context: {5      cart: {6        items: [7          {8            id: "item_1",9            quantity: 150,10            // assuming the price set belongs to this variant11            variant_id: "variant_1",12            // ...13          }14        ],15        // ...16      }17    }18  }19)

Price Selection with Price List#

Code
1const priceList = pricingModuleService.createPriceLists([{2  title: "Summer Price List",3  description: "Price list for summer sale",4  starts_at: Date.parse("01/10/2023").toString(),5  ends_at: Date.parse("31/10/2023").toString(),6  rules: {7    region_id: ['region_123', 'region_456'],8  },9  type: "sale",10  prices: [11    {12      amount: 2,13      currency_code: "eur",14      price_set_id: priceSet.id,15    },16    {17      amount: 1.5,18      currency_code: "usd",19      price_set_id: priceSet.id,20    }21  ],22}]);23
24const price = await pricingModuleService.calculatePrices(25  { id: [priceSet.id] },26  {27    context: {28      currency_code: "eur",29      region_id: "reg_123",30      city: "krakow"31    }32  }33)
Was this page helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break