docs: add missing details for tiered pricing (#12374)
* docs: add missing details for tiered pricing * adjustments
This commit is contained in:
+14387
-14240
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ Learn more about why modules are isolated in [this documentation](!docs!/learn/f
|
||||
- [Integrate Third-Party Fulfillment Providers](./fulfillment-provider/page.mdx): Create third-party fulfillment providers to provide customers with shipping options and fulfill their orders.
|
||||
- [Restrict By Location and Rules](./shipping-option/page.mdx): Shipping options can be restricted to specific geographical locations. You can also specify custom rules to restrict shipping options.
|
||||
- [Support Different Fulfillment Forms](./concepts/page.mdx): Support various fulfillment forms, such as shipping or pick up.
|
||||
- [Tiered Pricing and Price Rules](../pricing/price-rules/page.mdx): Set prices for shipping options with tiers and rules, allowing you to create complex pricing strategies.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Learn more about why modules are isolated in [this documentation](!docs!/learn/f
|
||||
## Pricing Features
|
||||
|
||||
- [Price Management](./concepts/page.mdx): Store and manage prices of a resource, such as a product or a variant.
|
||||
- [Advanced Rule Engine](./price-rules/page.mdx): Create prices with custom rules to condition prices based on different contexts.
|
||||
- [Advanced Rule Engine](./price-rules/page.mdx): Create prices with tiers and custom rules to condition prices based on different contexts.
|
||||
- [Price Lists](./concepts/page.mdx#price-list): Group prices and apply them only in specific conditions with price lists.
|
||||
- [Price Calculation Strategy](./price-calculation/page.mdx): Retrieve the best price in a given context and for the specified rule values.
|
||||
- [Tax-Inclusive Pricing](./tax-inclusive-pricing/page.mdx): Calculate prices with taxes included in the price, and Medusa will handle calculating the taxes automatically.
|
||||
|
||||
@@ -193,6 +193,11 @@ const priceSet = await pricingModuleService.createPriceSets({
|
||||
region_id: "reg_123",
|
||||
},
|
||||
},
|
||||
{
|
||||
amount: 200,
|
||||
currency_code: "EUR",
|
||||
min_quantity: 100,
|
||||
}
|
||||
],
|
||||
})
|
||||
```
|
||||
@@ -329,6 +334,83 @@ const priceSet = await pricingModuleService.createPriceSets({
|
||||
</TabsContentWrapper>
|
||||
</Tabs>
|
||||
|
||||
### Tiered Pricing Selection
|
||||
|
||||
<Tabs defaultValue="code">
|
||||
<TabsList>
|
||||
<TabsTrigger value="code">Code</TabsTrigger>
|
||||
<TabsTrigger value="result">Result</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContentWrapper>
|
||||
<TabsContent value="code">
|
||||
|
||||
```ts
|
||||
const price = await pricingModuleService.calculatePrices(
|
||||
{ id: [priceSet.id] },
|
||||
{
|
||||
context: {
|
||||
cart: {
|
||||
items: [
|
||||
{
|
||||
id: "item_1",
|
||||
quantity: 200,
|
||||
// assuming the price set belongs to this variant
|
||||
variant_id: "variant_1",
|
||||
// ...
|
||||
}
|
||||
],
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
</TabsContent>
|
||||
<TabsContent value="result">
|
||||
|
||||
The returned price is:
|
||||
|
||||
```ts
|
||||
const price = {
|
||||
id: "<PRICE_SET_ID>",
|
||||
is_calculated_price_price_list: false,
|
||||
calculated_amount: 200,
|
||||
|
||||
is_original_price_price_list: false,
|
||||
original_amount: 200,
|
||||
|
||||
currency_code: "EUR",
|
||||
|
||||
is_calculated_price_tax_inclusive: false,
|
||||
is_original_price_tax_inclusive: false,
|
||||
|
||||
calculated_price: {
|
||||
price_id: "<DEFAULT_PRICE_ID>",
|
||||
price_list_id: null,
|
||||
price_list_type: null,
|
||||
min_quantity: 100,
|
||||
max_quantity: null,
|
||||
},
|
||||
|
||||
original_price: {
|
||||
price_id: "<DEFAULT_PRICE_ID>",
|
||||
price_list_id: null,
|
||||
price_list_type: null,
|
||||
min_quantity: 100,
|
||||
max_quantity: null,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- Original price selection: the fifth price in the price list is selected as the best price because the cart item quantity is 200.
|
||||
- This is assuming the price set belongs to the cart item's variant.
|
||||
- Calculated price selection: since there are no associated price lists, the calculated price is set to the original price.
|
||||
|
||||
</TabsContent>
|
||||
</TabsContentWrapper>
|
||||
</Tabs>
|
||||
|
||||
### Price Selection with Price List
|
||||
|
||||
<Tabs defaultValue="code">
|
||||
|
||||
@@ -7,17 +7,161 @@ tags:
|
||||
- concept
|
||||
---
|
||||
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Price Rules`,
|
||||
title: `Price Tiers and Rules`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this Pricing Module guide, you'll learn about price rules for price sets and price lists, and how to add rules to a price.
|
||||
In this Pricing Module guide, you'll learn about tired prices, price rules for price sets and price lists, and how to add rules to a price.
|
||||
|
||||
## Tiered Pricing
|
||||
|
||||
Each price, represented by the [Price data model](/references/pricing/models/Price), has two optional properties that can be used to create tiered prices:
|
||||
|
||||
- `min_quantity`: The minimum quantity that must be in the cart for the price to be applied.
|
||||
- `max_quantity`: The maximum quantity that can be in the cart for the price to be applied.
|
||||
|
||||
This is useful to set tiered pricing for resources like product variants and shipping options.
|
||||
|
||||
For example, you can set a variant's price to:
|
||||
|
||||
- `$10` by default.
|
||||
- `$8` when the customer adds `10` or more of the variant to the cart.
|
||||
- `$6` when the customer adds `20` or more of the variant to the cart.
|
||||
|
||||
These price definitions would look like this:
|
||||
|
||||
```json title="Example Prices"
|
||||
[
|
||||
// default price
|
||||
{
|
||||
"amount": 10,
|
||||
"currency_code": "usd",
|
||||
},
|
||||
{
|
||||
"amount": 8,
|
||||
"currency_code": "usd",
|
||||
"min_quantity": 10,
|
||||
"max_quantity": 19,
|
||||
},
|
||||
{
|
||||
"amount": 6,
|
||||
"currency_code": "usd",
|
||||
"min_quantity": 20,
|
||||
},
|
||||
],
|
||||
```
|
||||
|
||||
### How to Create Tiered Prices?
|
||||
|
||||
When you create prices, you can specify a `min_quantity` and `max_quantity` for each price. This allows you to create tiered pricing, where the price changes based on the quantity of items in the cart.
|
||||
|
||||
For example:
|
||||
|
||||
<Note>
|
||||
|
||||
For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](../../../medusa-workflows-reference/page.mdx) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism.
|
||||
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="price-example">
|
||||
<CodeTab label="Using Medusa Workflows" value="workflows">
|
||||
|
||||
export const tieredPricingHighlights = [
|
||||
["16", "min_quantity", "The minimum quantity that must be in the cart for the price to be applied."],
|
||||
["17", "max_quantity", "The maximum quantity that can be in the cart for the price to be applied."],
|
||||
]
|
||||
|
||||
```ts highlights={tieredPricingHighlights}
|
||||
const { result } = await createProductsWorkflow(container)
|
||||
.run({
|
||||
input: {
|
||||
products: [{
|
||||
variants: [{
|
||||
id: "variant_1",
|
||||
prices: [
|
||||
// default price
|
||||
{
|
||||
amount: 10,
|
||||
currency_code: "usd",
|
||||
},
|
||||
{
|
||||
amount: 8,
|
||||
currency_code: "usd",
|
||||
min_quantity: 10,
|
||||
max_quantity: 19,
|
||||
},
|
||||
{
|
||||
amount: 6,
|
||||
currency_code: "usd",
|
||||
min_quantity: 20,
|
||||
},
|
||||
],
|
||||
// ...
|
||||
}]
|
||||
}],
|
||||
// ...
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Using the Pricing Module" value="pricing-module">
|
||||
|
||||
```ts
|
||||
const priceSet = await pricingModule.addPrices({
|
||||
priceSetId: "pset_1",
|
||||
prices: [
|
||||
// default price
|
||||
{
|
||||
amount: 10,
|
||||
currency_code: "usd",
|
||||
},
|
||||
// tiered prices
|
||||
{
|
||||
amount: 8,
|
||||
currency_code: "usd",
|
||||
min_quantity: 10,
|
||||
max_quantity: 19,
|
||||
},
|
||||
{
|
||||
amount: 6,
|
||||
currency_code: "usd",
|
||||
min_quantity: 20,
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
In this example, you create a product with a variant whose default price is `$10`. You also add two tiered prices that set the price to `$8` when the quantity is between `10` and `19`, and to `$6` when the quantity is `20` or more.
|
||||
|
||||
### How are Tiered Prices Applied?
|
||||
|
||||
The [price calculation](../price-calculation/page.mdx) mechanism considers the cart's items as a context when choosing the best price to apply.
|
||||
|
||||
For example, consider the customer added the `variant_1` product variant (created in the workflow snippet of the [above section](#how-to-create-tiered-prices)) to their cart with a quantity of `15`.
|
||||
|
||||
The price calculation mechanism will choose the second price, which is `$8`, because the quantity of `15` is between `10` and `19`.
|
||||
|
||||
<Note>
|
||||
|
||||
If there are other rules applied to the price, they may affect the price calculation. Keep reading to learn about other price rules, and refer to the [Price Calculation](../price-calculation/page.mdx) guide for more details on the calculation mechanism.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Price Rule
|
||||
|
||||
You can restrict prices by rules. Each rule of a price is represented by the [PriceRule data model](/references/pricing/models/PriceRule).
|
||||
You can also restrict prices by advanced rules, such as a customer's group, zip code, or a cart's total.
|
||||
|
||||
Each rule of a price is represented by the [PriceRule data model](/references/pricing/models/PriceRule).
|
||||
|
||||
The `Price` data model has a `rules_count` property, which indicates how many rules, represented by `PriceRule`, are applied to the price.
|
||||
|
||||
@@ -31,9 +175,7 @@ For example, a price can be restricted by a region and a zip code.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Price List Rules
|
||||
### Price List Rules
|
||||
|
||||
Rules applied to a price list are represented by the [PriceListRule data model](/references/pricing/models/PriceListRule).
|
||||
|
||||
@@ -41,17 +183,20 @@ The `rules_count` property of a `PriceList` indicates how many rules are applied
|
||||
|
||||

|
||||
|
||||
---
|
||||
### How to Create Prices with Rules?
|
||||
|
||||
## How to Set Rules on a Price?
|
||||
When you create prices, you can specify rules for each price. This allows you to create complex pricing strategies based on different contexts.
|
||||
|
||||
### Using Workflows
|
||||
For example:
|
||||
|
||||
Medusa uses the Pricing Module to store prices of different resources, such as product variants and shipping options.
|
||||
<Note>
|
||||
|
||||
When you manage one of these resources using [Medusa's workflows](../../../medusa-workflows-reference/page.mdx) or using the API routes that use them, you can set rules on a price using the `rules` property of the price object.
|
||||
For most use cases where you're building customizations in the Medusa application, it's highly recommended to use [Medusa's workflows](../../../medusa-workflows-reference/page.mdx) rather than using the Pricing Module directly. Medusa's workflows already implement extensive functionalities that you can re-use in your custom flows, with reliable roll-back mechanism.
|
||||
|
||||
For example, when creating a shipping option using the [createShippingOptionsWorkflow](!resources!/references/medusa-workflows/createShippingOptionsWorkflow) to create a shipping option, you can make the shipping price free based on the cart total:
|
||||
</Note>
|
||||
|
||||
<CodeTabs group="price-example">
|
||||
<CodeTab label="Using Medusa Workflows" value="workflows">
|
||||
|
||||
export const workflowHighlights = [
|
||||
["19", "rules", "The default price doesn't have rules."],
|
||||
@@ -95,19 +240,8 @@ const { result } = await createShippingOptionsWorkflow(container)
|
||||
})
|
||||
```
|
||||
|
||||
In this example, you create a shipping option whose default price is `$10`. When the total of the cart or order using this shipping option is greater than `$100`, the shipping option's price becomes free.
|
||||
|
||||
### Using Pricing Module's Service
|
||||
|
||||
<Note>
|
||||
|
||||
For most use cases, it's recommended to use [workflows](#using-workflows) instead of directly using the module's service.
|
||||
|
||||
</Note>
|
||||
|
||||
When adding a price using the [addPrices](!resources!/references/pricing/addPrices) method of the Pricing Module's service, pass the `rules` property to a price object.
|
||||
|
||||
For example:
|
||||
</CodeTab>
|
||||
<CodeTab label="Using the Pricing Module" value="pricing-module">
|
||||
|
||||
```ts
|
||||
const priceSet = await pricingModule.addPrices({
|
||||
@@ -134,7 +268,10 @@ const priceSet = await pricingModule.addPrices({
|
||||
})
|
||||
```
|
||||
|
||||
In this example, you set the default price of a resource (for example, a shipping option), to `$10`. You also add a conditioned price that sets the price to `0` when the cart or order's total is greater than or equal to `$100`.
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
|
||||
In this example, you create a shipping option whose default price is `$10`. When the total of the cart or order using this shipping option is greater than `$100`, the shipping option's price becomes free.
|
||||
|
||||
### How is the Price Rule Applied?
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ Learn more about why modules are isolated in [this documentation](!docs!/learn/f
|
||||
- [Products Management](/references/product/models/Product): Store and manage products. Products have custom options, such as color or size, and each variant in the product sets the value for these options.
|
||||
- [Product Organization](/references/product/models): The Product Module provides different data models used to organize products, including categories, collections, tags, and more.
|
||||
- [Bundled and Multi-Part Products](../inventory/inventory-kit/page.mdx): Create and manage inventory kits for a single product, allowing you to implement use cases like bundled or multi-part products.
|
||||
- [Tiered Pricing and Price Rules](../pricing/price-rules/page.mdx): Set prices for product variants with tiers and rules, allowing you to create complex pricing strategies.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const generatedEditDates = {
|
||||
"app/commerce-modules/fulfillment/item-fulfillment/page.mdx": "2024-10-08T14:38:15.496Z",
|
||||
"app/commerce-modules/fulfillment/module-options/page.mdx": "2024-10-15T12:51:56.118Z",
|
||||
"app/commerce-modules/fulfillment/shipping-option/page.mdx": "2025-04-24T09:21:52.540Z",
|
||||
"app/commerce-modules/fulfillment/page.mdx": "2025-04-17T08:48:19.367Z",
|
||||
"app/commerce-modules/fulfillment/page.mdx": "2025-05-06T10:33:48.708Z",
|
||||
"app/commerce-modules/inventory/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/inventory/_events/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/inventory/concepts/page.mdx": "2025-02-13T12:37:28.918Z",
|
||||
@@ -56,15 +56,15 @@ export const generatedEditDates = {
|
||||
"app/commerce-modules/pricing/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/pricing/_events/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/pricing/concepts/page.mdx": "2024-10-09T13:37:25.678Z",
|
||||
"app/commerce-modules/pricing/price-calculation/page.mdx": "2024-10-09T13:43:14.038Z",
|
||||
"app/commerce-modules/pricing/price-rules/page.mdx": "2025-04-17T14:31:26.650Z",
|
||||
"app/commerce-modules/pricing/price-calculation/page.mdx": "2025-05-06T10:31:48.476Z",
|
||||
"app/commerce-modules/pricing/price-rules/page.mdx": "2025-05-06T10:52:21.010Z",
|
||||
"app/commerce-modules/pricing/tax-inclusive-pricing/page.mdx": "2024-10-09T13:48:23.261Z",
|
||||
"app/commerce-modules/pricing/page.mdx": "2025-04-17T08:48:29.165Z",
|
||||
"app/commerce-modules/pricing/page.mdx": "2025-05-06T10:48:45.645Z",
|
||||
"app/commerce-modules/product/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/product/_events/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/product/guides/price/page.mdx": "2024-12-25T15:10:37.730Z",
|
||||
"app/commerce-modules/product/guides/price-with-taxes/page.mdx": "2024-12-25T15:10:40.879Z",
|
||||
"app/commerce-modules/product/page.mdx": "2025-04-17T08:48:20.755Z",
|
||||
"app/commerce-modules/product/page.mdx": "2025-05-06T10:33:30.948Z",
|
||||
"app/commerce-modules/promotion/_events/_events-table/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/promotion/_events/page.mdx": "2024-07-03T19:27:13+03:00",
|
||||
"app/commerce-modules/promotion/actions/page.mdx": "2024-10-09T14:49:01.645Z",
|
||||
|
||||
@@ -10182,7 +10182,7 @@ const generatedgeneratedCommerceModulesSidebarSidebar = {
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/commerce-modules/pricing/price-rules",
|
||||
"title": "Price Rules",
|
||||
"title": "Price Tiers and Rules",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ export const pricingSidebar = [
|
||||
{
|
||||
type: "link",
|
||||
path: "/commerce-modules/pricing/price-rules",
|
||||
title: "Price Rules",
|
||||
title: "Price Tiers and Rules",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
|
||||
Reference in New Issue
Block a user