chore: reorganize docs apps (#7228)

* reorganize docs apps

* add README

* fix directory

* add condition for old docs
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-05-03 17:36:38 +03:00
1 parent 224ebb2154
commit 4fe28f5a95
6187 files changed
+601447 -598226

No files matched your search

@@ -0,0 +1,503 @@
import { Tabs, TabsList, TabsTrigger, TabsContent, TabsContentWrapper } from "docs-ui"
export const metadata = {
title: `Prices Calculation`,
}
# {metadata.title}
In this document, you'll learn how prices are calculated under the hood when you use the `calculatePrices` method of the Pricing Module interface.
## Overview
The `calculatePrices` method accepts the ID of one or more price sets and a context. For each price set, it selects two types of prices that best match the context; one belongs to a price list, and one doesn't.
Then, it returns an array of price objects, each price for every supplied price set ID.
---
## Calculation Context
The context is an object passed 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.
For example:
```ts
import {
initialize as initializePricingModule,
} from "@medusajs/pricing"
async function calculatePrice(
priceSetId: string,
currencyCode: string
) {
const pricingModuleService = await initializePricingModule()
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
},
}
)
}
```
The context object can also contain any custom rules, with the key being the `rule_field` of a rule type and its value being the rule's value.
For example:
```ts
import {
initialize as initializePricingModule,
} from "@medusajs/pricing"
async function calculatePrice(
priceSetId: string,
currencyCode: string
) {
const pricingModuleService = await initializePricingModule()
const price = await pricingModuleService.calculatePrices(
{ id: [priceSetId] },
{
context: {
currency_code: currencyCode,
region_id: "US",
},
}
)
}
```
---
## Prices Selection
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: a price that doesn't belong to a price list.
### Calculated Price Selection Process
![A diagram showcasing the calculated price selection process.](https://res.cloudinary.com/dza7lstvk/image/upload/v1700574799/Medusa%20Docs/Diagrams/calculated-price_vjnx3j.jpg)
- Find the price set’s associated valid price lists. A price list is considered valid if:
- The current date is between its start and end dates.
- The price list's rules satisfy the context's rules.
- If valid price lists are found, the prices within them are sorted by their amount in ascending order. The one having the lowest amount is selected as the calculated price.
- If no valid price list is found, the selected calculated price will be the same as the original price.
### Original Price Selection Process
![A diagram showcasing the original price selection process.](https://res.cloudinary.com/dza7lstvk/image/upload/v1700574800/Medusa%20Docs/Diagrams/original-price_i47fso.jpg)
- If the price list associated with the calculated price is of type `override`, the selected original price is set to the calculated price.
- If no rules are provided in the context other than the `currency_code`, the default price is selected as the original price. The default price is a price having no rules applied to it.
- Otherwise, if a price exists in any price set with the same rules provided in the context, it's selected as the original price.
- If no price exists with the same rules as the context, all prices satisfying any combination of the provided rules are retrieved.
- The prices are sorted in descending order by the associated `Price`'s `rules_count`, the `default_priority` of the rule types, and the `priority` of the associated `PriceRule`. The `priority` field has a higher precedence than the `default_priority`.
- The highest price sorted is selected as the original price since it's considered the best price.
---
## Returned Calculated Price
After the original and calculated prices are selected, the method will use them to create the following price object for each pr
```ts
const price = {
id: priceSetId,
is_calculated_price_price_list:
!!calculatedPrice?.price_list_id,
calculated_amount: parseInt(
calculatedPrice?.amount || ""
) || null,
is_original_price_price_list:
!!originalPrice?.price_list_id,
original_amount: parseInt(
originalPrice?.amount || ""
) || null,
currency_code: calculatedPrice?.currency_code || null,
calculated_price: {
price_id: calculatedPrice?.id || null,
price_list_id: calculatedPrice?.price_list_id || null,
price_list_type: calculatedPrice?.price_list_type || null,
min_quantity: parseInt(
calculatedPrice?.min_quantity || ""
) || null,
max_quantity: parseInt(
calculatedPrice?.max_quantity || ""
) || null,
},
original_price: {
price_id: originalPrice?.id || null,
price_list_id: originalPrice?.price_list_id || null,
price_list_type: originalPrice?.price_list_type || null,
min_quantity: parseInt(
originalPrice?.min_quantity || ""
) || null,
max_quantity: parseInt(
originalPrice?.max_quantity || ""
) || null,
},
}
```
Where:
- `id`: The ID of the price set from which the price was selected.
- `is_calculated_price_price_list`: whether the calculated price belongs to a price list. As mentioned earlier, if no valid price list is found, the calculated price is set to the original price, which doesn't belong to a price list.
- `calculated_amount`: The amount of the calculated price, or `null` if there isn't a calculated price.
- `is_original_price_price_list`: whether the original price belongs to a price list. As mentioned earlier, if the price list of the calculated price is of type `override`, the original price will be the same as the calculated price.
- `original_amount`: The amount of the original price, or `null` if there isn't an original price.
- `currency_code`: The currency code of the calculated price, or `null` if there isn't a calculated price.
- `calculated_price`: An object containing the calculated price's price details and potentially its associated price list.
- `original_price`: An object containing the original price's price details and potentially its associated price list.
The method returns an array of these price objects.
---
## Example
Consider the following rule types and price sets:
```ts
const ruleTypes = await pricingModuleService.createRuleTypes([
{
name: "Region",
rule_field: "region_id",
},
{
name: "City",
rule_field: "city",
},
])
const priceSet = await pricingModuleService.create({
rules: [
{ rule_field: "region_id" },
{ rule_field: "city" },
],
prices: [
//default
{
amount: 500,
currency_code: "EUR",
rules: {},
},
// prices with rules
{
amount: 400,
currency_code: "EUR",
rules: {
region_id: "PL",
},
},
{
amount: 450,
currency_code: "EUR",
rules: {
city: "krakow",
},
},
{
amount: 500,
currency_code: "EUR",
rules: {
city: "warsaw",
region_id: "PL",
},
},
],
})
```
### Default Price 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: {
currency_code: "EUR"
}
}
)
```
</TabsContent>
<TabsContent value="result">
The returned price is:
```ts
const price = {
id: "<PRICE_SET_ID>",
is_calculated_price_price_list: false,
calculated_amount: 500,
is_original_price_price_list: false,
original_amount: 500,
currency_code: "EUR",
calculated_price: {
price_id: "<DEFAULT_PRICE_ID>",
price_list_id: null,
price_list_type: null,
min_quantity: null,
max_quantity: null,
},
original_price: {
price_id: "<DEFAULT_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.
- Calculated price selection: since there are no associated price lists, the calculated price is set to the original price.
</TabsContent>
</TabsContentWrapper>
</Tabs>
### Exact Match Rule in Context
<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: {
currency_code: "EUR",
region_id: "PL"
}
}
)
```
</TabsContent>
<TabsContent value="result">
The returned price is:
```ts
const price = {
id: "<PRICE_SET_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: "<SECOND_PRICE_ID>",
price_list_id: null,
price_list_type: null,
min_quantity: null,
max_quantity: null,
},
original_price: {
price_id: "<SECOND_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.
</TabsContent>
</TabsContentWrapper>
</Tabs>
### Context without Exact Matching Rules
<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: {
currency_code: "EUR",
region_id: "PL",
city: "krakow"
}
}
)
```
</TabsContent>
<TabsContent value="result">
The returned price is:
```ts
const price = {
id: "<PRICE_SET_ID>",
is_calculated_price_price_list: false,
calculated_amount: 500,
is_original_price_price_list: false,
original_amount: 500,
currency_code: "EUR",
calculated_price: {
price_id: "<FOURTH_PRICE_ID>",
price_list_id: null,
price_list_type: null,
min_quantity: null,
max_quantity: null,
},
original_price: {
price_id: "<FOURTH_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 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.
- 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">
<TabsList>
<TabsTrigger value="code">Code</TabsTrigger>
<TabsTrigger value="result">Result</TabsTrigger>
</TabsList>
<TabsContentWrapper>
<TabsContent value="code">
```ts
const priceList = pricingModuleService.createPriceList({
name: "Test Price List",
starts_at: Date.parse("01/10/2023"),
ends_at: Date.parse("31/10/2023"),
rules: {
region_id: ['PL']
},
type: "sale"
prices: [
{
amount: 400,
currency_code: "EUR",
price_set_id: priceSet.id,
},
{
amount: 450,
currency_code: "EUR",
price_set_id: priceSet.id,
},
],
});
const price = await pricingModuleService.calculatePrices(
{ id: [priceSet.id] },
{
context: {
currency_code: "EUR",
region_id: "PL",
city: "krakow"
}
}
)
```
</TabsContent>
<TabsContent value="result">
The returned price is:
```ts
const price = {
id: "<PRICE_SET_ID>",
is_calculated_price_price_list: true,
calculated_amount: 400,
is_original_price_price_list: false,
original_amount: 500,
currency_code: "EUR",
calculated_price: {
price_id: "<FOURTH_PRICE_ID>",
price_list_id: null,
price_list_type: null,
min_quantity: null,
max_quantity: null,
},
original_price: {
price_id: "<PL_PRICE_ID_1>",
price_list_id: "<PRICE_LIST_ID>",
price_list_type: "sale",
min_quantity: null,
max_quantity: null,
},
}
```
- 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.
</TabsContent>
</TabsContentWrapper>
</Tabs>