import { Tabs, TabsList, TabsTrigger, TabsContent, TabsContentWrapper, TypeList } from "docs-ui" export const metadata = { title: `Prices Calculation`, } # {metadata.title} In this guide, you'll learn how prices are calculated when you use the [calculatePrices method](/references/pricing/calculatePrices) of the Pricing Module's main service. ## calculatePrices Method The [calculatePrices method](/references/pricing/calculatePrices) 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: ```ts const price = await pricingModuleService.calculatePrices( { id: [priceSetId] }, { context: { currency_code: "eur", region_id: "reg_123", }, } ) ``` 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](#original-price-selection-logic) the specified context. Both prices are returned in an object with the following properties: ### 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](https://res.cloudinary.com/dza7lstvk/image/upload/v1757058523/Medusa%20Resources/original-price-calculation_sxjw3l.jpg) 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: ```ts const priceSet = await pricingModuleService.createPriceSets({ prices: [ // default price { amount: 5, currency_code: "eur", rules: {}, }, // prices with rules { amount: 4, currency_code: "eur", rules: { region_id: "reg_123", }, }, { amount: 4.5, currency_code: "eur", rules: { city: "krakow", }, }, { amount: 3.5, currency_code: "eur", rules: { city: "warsaw", region_id: "reg_123", }, }, // tiered price { amount: 2, currency_code: "eur", min_quantity: 100, }, ], }) ``` ### Default Price Selection Code Result ```ts const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, { context: { currency_code: "eur" } } ) ``` The returned price is: ```ts const price = { id: "", is_calculated_price_price_list: false, calculated_amount: 5, is_original_price_price_list: false, original_amount: 5, currency_code: "eur", is_calculated_price_tax_inclusive: false, is_original_price_tax_inclusive: false, calculated_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, original_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, } ``` - Original price selection: Since there are no provided rules in the context, the original price is the default price of the price set. - Calculated price selection: Since there are no associated price lists, the calculated price is set to the original price. ### Calculate Prices with Exact Match Code Result ```ts const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, { context: { currency_code: "eur", region_id: "reg_123", city: "warsaw" } } ) ``` The returned price is: ```ts const price = { id: "", is_calculated_price_price_list: false, calculated_amount: 3.5, is_original_price_price_list: false, original_amount: 3.5, currency_code: "eur", is_calculated_price_tax_inclusive: false, is_original_price_tax_inclusive: false, calculated_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, original_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, } ``` - Original price selection: The fourth price in the price set is selected as the best price because it matches both the `region_id` and `city` rules. - Calculated price selection: Since there are no associated price lists, the calculated price is set to the original price. ### Calculate Prices with Partial Match Code Result ```ts const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, { context: { currency_code: "eur", region_id: "reg_123", city: "krakow" } } ) ``` The returned price is: ```ts const price = { id: "", is_calculated_price_price_list: false, calculated_amount: 4, is_original_price_price_list: false, original_amount: 4, currency_code: "eur", is_calculated_price_tax_inclusive: false, is_original_price_tax_inclusive: false, calculated_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, original_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, } ``` - Original price selection: The second price in the price set is selected as the best price because it matches the `region_id` rule. - Although the third price also matches a rule (`city`), the second price is selected because it appears first in the price set. - Calculated price selection: Since there are no associated price lists, the calculated price is set to the original price. ### Tiered Pricing Selection Code Result ```ts const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, { context: { cart: { items: [ { id: "item_1", quantity: 150, // assuming the price set belongs to this variant variant_id: "variant_1", // ... } ], // ... } } } ) ``` The returned price is: ```ts const price = { id: "", is_calculated_price_price_list: false, calculated_amount: 2, is_original_price_price_list: false, original_amount: 2, currency_code: "eur", is_calculated_price_tax_inclusive: false, is_original_price_tax_inclusive: false, calculated_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: 100, max_quantity: null, }, original_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: 100, max_quantity: null, }, } ``` - Original price selection: Since the cart's item quantity is `100` or more, the tiered price is selected as the best price. - Calculated price selection: Since there are no associated price lists, the calculated price is set to the original price. ### Price Selection with Price List Code Result ```ts const priceList = pricingModuleService.createPriceLists([{ title: "Summer Price List", description: "Price list for summer sale", starts_at: Date.parse("01/10/2023").toString(), ends_at: Date.parse("31/10/2023").toString(), rules: { region_id: ['region_123', 'region_456'], }, type: "sale", prices: [ { amount: 2, currency_code: "eur", price_set_id: priceSet.id, }, { amount: 1.5, currency_code: "usd", price_set_id: priceSet.id, } ], }]); const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, { context: { currency_code: "eur", region_id: "reg_123", city: "krakow" } } ) ``` The returned price is: ```ts const price = { id: "", is_calculated_price_price_list: true, calculated_amount: 2, is_original_price_price_list: false, original_amount: 4, currency_code: "eur", is_calculated_price_tax_inclusive: false, is_original_price_tax_inclusive: false, calculated_price: { price_id: "", price_list_id: null, price_list_type: null, min_quantity: null, max_quantity: null, }, original_price: { price_id: "", price_list_id: "", price_list_type: "sale", min_quantity: null, max_quantity: null, }, } ``` - Original price selection: The second price in the price set is selected as the best price because it matches the `region_id` rule. - Although the third price also matches a rule (`city`), the second price is selected because it appears first in the price set. - Calculated price selection: The price from the price list is selected as the calculated price because it matches the `region_id` rule of the price list.