diff --git a/www/apps/resources/app/commerce-modules/pricing/concepts/page.mdx b/www/apps/resources/app/commerce-modules/pricing/concepts/page.mdx index b40e38ff06..5fe0b50c82 100644 --- a/www/apps/resources/app/commerce-modules/pricing/concepts/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/concepts/page.mdx @@ -14,36 +14,6 @@ A [PriceSet](/references/pricing/models/PriceSet) represents a collection of pri --- -## Rule Type - -Each price within a price set can be applied for different conditions. These conditions are represented as rule types. - -A [RuleType](/references/pricing/models/RuleType) defines custom conditions. A rule type has a unique `rule_attribute` which indicates the property this rule applies on. For example, `region_id`. - -This is referenced when setting a rule of a price. For example: - -export const ruleTypeHighlights = [ - ["8", "region_id", "Reference a rule type by its `rule_attribute`."], - ["8", `"PL"`, "The value of this rule."] -] - -```ts highlights={ruleTypeHighlights} -const priceSet = await pricingModuleService.addPrices({ - priceSetId, - prices: [ - { - amount: 500, - currency_code: "EUR", - rules: { - region_id: "PL", - }, - }, - ], -}) -``` - ---- - ## Price List A [PriceList](/references/pricing/models/PriceList) is a group of prices only enabled if their conditions and rules are satisfied. A price list has optional `start_date` and `end_date` properties, which indicate the date range in which a price list can be applied. diff --git a/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx b/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx index 3871402efa..f12ee76334 100644 --- a/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx @@ -25,17 +25,14 @@ In this document, you’ll find common examples of how you can use the Pricing M const pricingModuleService: IPricingModuleService = request.scope.resolve(ModuleRegistrationName.PRICING) - // A rule type with \`rule_field=region_id\` should - // already be present in the database const priceSet = await pricingModuleService.createPriceSets([ { - rules: [{ rule_field: "region_id" }], prices: [ { - currency_code: request.body.currency_code, - amount: request.body.amount, + currency_code: "eur", + amount: 10, rules: { - region_id: request.body.region_id, + region_id: "reg_123", }, }, ], @@ -60,17 +57,14 @@ In this document, you’ll find common examples of how you can use the Pricing M const pricingModuleService = await initializePricingModule() const body = await request.json() - // A rule type with \`rule_field=region_i\` should - // already be present in the database const priceSet = await pricingModuleService.createPriceSets([ { - rules: [{ rule_field: "region_id" }], prices: [ { - currency_code: body.currency_code, - amount: body.amount, + currency_code: "eur", + amount: 10, rules: { - region_id: body.region_id, + region_id: "reg_123", }, }, ], @@ -151,7 +145,7 @@ In this document, you’ll find common examples of how you can use the Pricing M request.scope.resolve(ModuleRegistrationName.PRICING) const priceSet = await pricingModuleService.retrievePriceSet( - request.params.id + "pset_123" ) res.json({ price_set: priceSet }) @@ -168,20 +162,13 @@ In this document, you’ll find common examples of how you can use the Pricing M initialize as initializePricingModule, } from "@medusajs/pricing" - type ContextType = { - params: { - id: string - } - } - export async function GET( request: Request, - { params }: ContextType ) { const pricingModuleService = await initializePricingModule() const priceSet = await pricingModuleService.retrievePriceSet( - params.id + "pset_123" ) return NextResponse.json({ price_set: priceSet }) @@ -193,61 +180,6 @@ In this document, you’ll find common examples of how you can use the Pricing M --- -## Create a Rule Type - - - - - ```ts - import { MedusaRequest, MedusaResponse } from "@medusajs/medusa" - import { IPricingModuleService } from "@medusajs/types" - import { ModuleRegistrationName } from "@medusajs/modules-sdk" - - export async function POST( - request: MedusaRequest, - res: MedusaResponse - ): Promise { - const pricingModuleService: IPricingModuleService = - request.scope.resolve(ModuleRegistrationName.PRICING) - - const ruleType = await pricingModuleService.createRuleTypes([{ - name: "Customer Group", - rule_attribute: "customer_group_id", - }]) - - res.json({ rule_type: ruleType }) - } - ``` - - - - - ```ts - import { NextResponse } from "next/server" - - import { - initialize as initializePricingModule, - } from "@medusajs/pricing" - - export async function POST( - request: Request - ) { - const pricingModuleService = await initializePricingModule() - - const ruleType = await pricingModuleService.createRuleTypes([{ - name: "Customer Group", - rule_attribute: "customer_group_id", - }]) - - return NextResponse.json({ rule_type: ruleType }) - } - ``` - - - - ---- - ## Add Prices with Rules @@ -266,13 +198,13 @@ In this document, you’ll find common examples of how you can use the Pricing M request.scope.resolve(ModuleRegistrationName.PRICING) const priceSet = await pricingModuleService.addPrices({ - priceSetId: request.body.price_set_id, + priceSetId: "pset_123", prices: [ { amount: 500, currency_code: "USD", rules: { - region_id: request.body.region_id, + region_id: "reg_123", }, }, ], @@ -297,13 +229,13 @@ In this document, you’ll find common examples of how you can use the Pricing M const body = await request.json() const priceSet = await pricingModuleService.addPrices({ - priceSetId: body.price_set_id, + priceSetId: "pset_123", prices: [ - { + { amount: 500, currency_code: "USD", rules: { - region_id: body.region_id, + region_id: "reg_123", }, }, ], @@ -325,10 +257,8 @@ In this document, you’ll find common examples of how you can use the Pricing M ```ts collapsibleLines="1-8" expandButtonLabel="Show Imports" import { MedusaRequest, MedusaResponse } from "@medusajs/medusa" - import { - IPricingModuleService, - PriceListType, - } from "@medusajs/types" + import { IPricingModuleService } from "@medusajs/types" + import { PriceListType } from "@medusajs/utils" import { ModuleRegistrationName } from "@medusajs/modules-sdk" export async function POST( @@ -347,7 +277,7 @@ In this document, you’ll find common examples of how you can use the Pricing M starts_at: Date.parse("01/10/2023").toString(), ends_at: Date.parse("31/10/2023").toString(), rules: { - region_id: ["DE", "DK"], + region_id: ["reg_123", "reg_321"], }, prices: [ { @@ -373,11 +303,12 @@ In this document, you’ll find common examples of how you can use the Pricing M import { initialize as initializePricingModule, } from "@medusajs/pricing" + import { PriceListType } from "@medusajs/utils" export async function POST(request: Request) { const pricingModuleService = await initializePricingModule() - const priceLists = + const priceLists = await pricingModuleService.createPriceLists([ { title: "My Sale", @@ -386,7 +317,7 @@ In this document, you’ll find common examples of how you can use the Pricing M starts_at: Date.parse("01/10/2023").toString(), ends_at: Date.parse("31/10/2023").toString(), rules: { - region_id: ["DE", "DK"], + region_id: ["reg_123", "reg_321"], }, prices: [ { @@ -426,11 +357,11 @@ In this document, you’ll find common examples of how you can use the Pricing M const price = await pricingModuleService.calculatePrices( { - id: [request.params.id], + id: ["pset_123"], }, { context: { - currency_code: request.params.currency_code, + currency_code: "eur", }, } ) @@ -449,26 +380,21 @@ In this document, you’ll find common examples of how you can use the Pricing M initialize as initializePricingModule, } from "@medusajs/pricing" - type ContextType = { - params: { - id: string - currency_code: string - } - } - export async function GET( request: Request, - { params }: ContextType ) { const pricingModuleService = await initializePricingModule() - const price = await pricingModuleService.calculatePrices({ - id: [params.id], - }, { - context: { - currency_code: params.currency_code, + const price = await pricingModuleService.calculatePrices( + { + id: ["pset_123"], }, - }) + { + context: { + currency_code: "eur", + }, + } + ) return NextResponse.json({ price }) } diff --git a/www/apps/resources/app/commerce-modules/pricing/page.mdx b/www/apps/resources/app/commerce-modules/pricing/page.mdx index ba5b800d93..1f37865466 100644 --- a/www/apps/resources/app/commerce-modules/pricing/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/page.mdx @@ -18,9 +18,8 @@ Prices are grouped in a price set, allowing you to add more than one price for a ```ts const priceSet = await pricingModuleService.createPriceSets({ - rules: [], prices: [ - { + { amount: 500, currency_code: "USD", }, @@ -37,24 +36,17 @@ const priceSet = await pricingModuleService.createPriceSets({ ### Advanced Rule Engine -Create custom rules and apply them to prices. This gives you more flexibility in how you condition prices, filter them, and ensure the best prices are retrieved for custom contexts. - -```ts -const ruleTypes = await pricingModuleService.createRuleTypes([ - { - name: "Region", - rule_field: "region_id", - }, -]) +Create prices with custom rules. This gives you more flexibility in how you condition prices, filter them, and ensure the best prices are retrieved for custom contexts. +```ts highlights={[["8"]]} const priceSet = await pricingModuleService.addPrices({ - priceSetId, + priceSetId: "pset_123", prices: [ - { + { amount: 500, currency_code: "EUR", rules: { - region_id: "PL", + region_id: "reg_123", }, }, ], @@ -66,22 +58,23 @@ const priceSet = await pricingModuleService.addPrices({ Price lists allow you to group prices and apply them only in specific conditions. You can also use them to override existing prices for the specified conditions. ```ts -const priceList = await pricingModuleService.createPriceLists({ +const priceList = await pricingModuleService.createPriceLists([{ title: "My Sale", + description: "Sale on selected items.", type: "sale", - starts_at: Date.parse("01/10/2023"), - ends_at: Date.parse("31/10/2023"), + starts_at: Date.parse("01/10/2023").toString(), + ends_at: Date.parse("31/10/2023").toString(), rules: { - region_id: ["DE", "DK"], + region_id: ["reg_123", "reg_321"], }, prices: [ { amount: 400, currency_code: "EUR", - price_set_id: priceSet.id, + price_set_id: "pset_123", }, ], -}) +}]) ``` ### Price Calculation Strategy @@ -90,11 +83,11 @@ Retrieve the best price in a given context and for the specified rule values. ```ts const price = await pricingModuleService.calculatePrices( - { id: [priceSetId] }, + { id: ["pset_123"] }, { context: { currency_code: "EUR", - region_id: "PL", + region_id: "reg_123", }, } ) diff --git a/www/apps/resources/app/commerce-modules/pricing/price-calculation/page.mdx b/www/apps/resources/app/commerce-modules/pricing/price-calculation/page.mdx index bb3249a9c1..a16ed77950 100644 --- a/www/apps/resources/app/commerce-modules/pricing/price-calculation/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/price-calculation/page.mdx @@ -8,15 +8,17 @@ export const metadata = { In this document, you'll learn how prices are calculated when you use the `calculatePrices` method of the Pricing Module's main service. -## Overview +## calculatePrices Method -The [calculatePrices method](/references/pricing/calculatePrices) accepts the ID of one or more price sets and a context. It returns a price object with the best matching price for each price set. +The [calculatePrices method](/references/pricing/calculatePrices) accepts as parameters the ID of one or more price sets and a context. + +It returns a price object with the best matching price for each price set. --- ## Calculation Context -The context is an object passed as a second parameter to the `calculatePrices` method. It must contain at least the `currency_code`. Only prices in the price sets with the same currency code are considered for the price selection. +The calculation context is an optional object passed as a second parameter to the `calculatePrices` method. It accepts rules to restrict the selected prices in the price set. For example: @@ -26,22 +28,7 @@ const price = await pricingModuleService.calculatePrices( { context: { currency_code: currencyCode, - }, - } -) -``` - -The context object can also contain any custom rules, with the key being the `rule_attribute` of a rule type and its value being the rule's value. - -For example: - -```ts -const price = await pricingModuleService.calculatePrices( - { id: [priceSetId] }, - { - context: { - currency_code: currencyCode, - region_id: "US", + region_id: "reg_123", }, } ) @@ -53,12 +40,10 @@ const price = await pricingModuleService.calculatePrices( For each price set, the method selects two prices: -- The calculated price: a price that belongs to a price list. If there are no prices associated with a price list, it’ll be the same as the original price. -- The original price: If the calculated price's price list type is `override`, then the original price will be the same as the calculated price. Otheriwse, a price that doesn't belong to a price list. +- The calculated price: Either the best context-matching price that belongs to a price list or the same as the original price. +- The original price: Either the same as the calculated price if its price list is of type `override`, or the best context-matching price that doesn't belong to a price list. -After the original and calculated prices are selected, the method will use them to create a price object for each price set. - -The price object has the following properties: +Both prices are returned in an object along with the following properties: -### Exact Match Rule in Context +### Calculate Prices with Rules @@ -295,70 +265,7 @@ const priceSet = await pricingModuleService.createPriceSets({ { context: { currency_code: "EUR", - region_id: "PL" - } - } - ) - ``` - - - - - The returned price is: - - ```ts - const price = { - id: "", - is_calculated_price_price_list: false, - calculated_amount: 400, - - is_original_price_price_list: false, - original_amount: 400, - - currency_code: "EUR", - - 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 the second price of the price set has the same context as the provided one, it's selected as the original price. - - Calculated price selection: since there are no associated price lists, the calculated price is set to the original price. - - - - - -### Context without Exact Matching Rules - - - - Code - Result - - - - - ```ts - const price = await pricingModuleService.calculatePrices( - { id: [priceSet.id] }, - { - context: { - currency_code: "EUR", - region_id: "PL", + region_id: "reg_123", city: "krakow" } } @@ -399,12 +306,7 @@ const priceSet = await pricingModuleService.createPriceSets({ } ``` - - Original price selection: The fourth price in the price list is selected based on the following process: - - There are no prices having the same rules as the context. - - Retrieve all prices matching some combination of the rules in the context. - - Sort the prices in descending order by their number of rules, each rule type's default priority, and the priority of the rule values. - - All rule types, in this case, don't have a priority. So, the sorting depends on the number of rules each price has. - - The fourth price has two rules, and the second and third have one rule. So, the fourth price is selected as the original price. + - Original price selection: The fourth price in the price list 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. @@ -422,14 +324,15 @@ const priceSet = await pricingModuleService.createPriceSets({ ```ts - const priceList = pricingModuleService.createPriceLists({ - name: "Test Price List", - starts_at: Date.parse("01/10/2023"), - ends_at: Date.parse("31/10/2023"), + 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: ['PL'] }, - type: "sale" + type: "sale", prices: [ { amount: 400, @@ -442,7 +345,7 @@ const priceSet = await pricingModuleService.createPriceSets({ price_set_id: priceSet.id, }, ], - }); + }]); const price = await pricingModuleService.calculatePrices( { id: [priceSet.id] }, @@ -490,10 +393,8 @@ const priceSet = await pricingModuleService.createPriceSets({ } ``` - - Original price selection: The process is explained in the Context without Exact Matching Rules section. - - Calculated price selection: The first price of the price list is selected based on the following process: - - The price set has a price list associated with it. So, retrieve its prices and sort them in ascending order by their amount. - - Since the first price of the price list has the lowest amount, it's selected as the calculated price. + - Original price selection: The fourth price in the price list is selected as the best price. + - Calculated price selection: The first price of the price list is selected as the best price. diff --git a/www/apps/resources/app/commerce-modules/pricing/price-rules/page.mdx b/www/apps/resources/app/commerce-modules/pricing/price-rules/page.mdx index 9108687baf..8d9ed16d78 100644 --- a/www/apps/resources/app/commerce-modules/pricing/price-rules/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/price-rules/page.mdx @@ -8,33 +8,19 @@ In this document, you'll learn about price rules for price sets and price lists. ## Price Rule -Each rule of a price within a price set is represented by the [PriceRule data model](/references/pricing/models/PriceRule), which holds the value of a rule type. The `Price` data model has a `rules_count` property, which indicates how many rules, represented by `PriceRule`, are applied to the price. +Prices can be restricted by rules. Each rule of a price is represented by the [PriceRule data model](/references/pricing/models/PriceRule). -![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648772/Medusa%20Resources/price-rule-1_vy8bn9.jpg) +The `Price` data model has a `rules_count` property, which indicates how many rules, represented by `PriceRule`, are applied to the price. -For example, you create a `zip_code` rule type. Then, a price within the price set can have the rule value `10557`, indicating that the price can only be applied within the `10557` zip code. +![A diagram showcasing the relation between the PriceRule and Price](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648772/Medusa%20Resources/price-rule-1_vy8bn9.jpg) -Each price within the price set can have different values for the same rule type. +For exmaple, you create a price restricted to `10557` zip codes. -For example: +A price can have multiple price rules. For example: -![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709648884/Medusa%20Resources/price-rule-2_b6fuyb.jpg) +![A diagram showcasing the relation between the PriceRule and Price with multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649296/Medusa%20Resources/price-rule-3_pwpocz.jpg) -Each price can have multiple rules applied to it as well. - -For example, a price can have the rules `zip_code` and `region_id` applied to it. In this case, the value of each rule is represented by a `PriceRule`. - -![A diagram showcasing the relation between the PriceRule, PriceSet, Price, and RuleType with multiple rules.](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649296/Medusa%20Resources/price-rule-3_pwpocz.jpg) - ---- - -## Restrict Price Rules - -The [PriceSetRuleType data model](/references/pricing/models/PriceSetRuleType) indicates what rules the prices can have within a price set. It creates a relation between the `PriceSet` and `RuleType` data models. - -For example, to use the `zip_code` rule type on a price in a price set, the rule type must first be enabled on the price set through the `PriceSetRuleType`. - -![A diagram showcasing the relation between the PriceSet, PriceRule, Price, RuleType, and PriceSetRuleType](https://res.cloudinary.com/dza7lstvk/image/upload/v1709649375/Medusa%20Resources/price-set-rule-type_cqqt0u.jpg) +For example, a price can be restricted by a region and a zip code. --- @@ -42,6 +28,4 @@ For example, to use the `zip_code` rule type on a price in a price set, the rule Rules that can be applied to a price list are represented by the [PriceListRule data model](/references/pricing/models/PriceListRule). The `rules_count` property of a `PriceList` indicates how many rules are applied to it. -Each rule of a price list can have more than one value, representing its values by the [PriceListRuleValue data model](/references/pricing/models/PriceListRuleValue). - ![A diagram showcasing the relation between the PriceSet, PriceList, Price, RuleType, and PriceListRuleValue](https://res.cloudinary.com/dza7lstvk/image/upload/v1709641999/Medusa%20Resources/price-list_zd10yd.jpg)