docs: improved commerce modules [4/n] (#9517)
Improve pricing, product, and promotion modules docs [4/n]
This commit is contained in:
1 parent
eb364834de
commit
f6d3453e6d
27 files changed
+1767
-341
No files matched your search
@@ -4,11 +4,13 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you’ll learn about the main concepts in the Pricing Module, and how data is stored and related.
|
||||
In this document, you’ll learn about the main concepts in the Pricing Module.
|
||||
|
||||
## Price Set
|
||||
|
||||
A [PriceSet](/references/pricing/models/PriceSet) represents a collection of prices that are linked to a resource (for example, a product or a shipping option). Each of these prices are represented by the [Price data module](/references/pricing/models/Price).
|
||||
A [PriceSet](/references/pricing/models/PriceSet) represents a collection of prices that are linked to a resource (for example, a product or a shipping option).
|
||||
|
||||
Each of these prices are represented by the [Price data module](/references/pricing/models/Price).
|
||||
|
||||

|
||||
|
||||
@@ -16,6 +18,8 @@ A [PriceSet](/references/pricing/models/PriceSet) represents a collection of pri
|
||||
|
||||
## 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.
|
||||
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 that indicate the date range in which a price list can be applied.
|
||||
|
||||
Its associated prices are represented by the `Price` data model.
|
||||
@@ -13,16 +13,15 @@ In this document, you’ll find common examples of how you can use the Pricing M
|
||||
<CodeTabs groupId="app-type">
|
||||
<CodeTab value="medusa" label="Medusa API Router">
|
||||
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function POST(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -84,16 +83,15 @@ export async function POST(request: Request) {
|
||||
<CodeTabs groupId="app-type">
|
||||
<CodeTab value="medusa" label="Medusa API Router">
|
||||
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function GET(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -130,16 +128,15 @@ export async function GET(request: Request) {
|
||||
<CodeTabs groupId="app-type">
|
||||
<CodeTab value="medusa" label="Medusa API Router">
|
||||
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function GET(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -176,16 +173,15 @@ export async function GET(request: Request) {
|
||||
<CodeTabs groupId="app-type">
|
||||
<CodeTab value="medusa" label="Medusa API Router">
|
||||
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function POST(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -255,7 +251,7 @@ export async function POST(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -330,16 +326,15 @@ export async function POST(request: Request) {
|
||||
<CodeTabs groupId="app-type">
|
||||
<CodeTab value="medusa" label="Medusa API Router">
|
||||
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function POST(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
export const metadata = {
|
||||
title: `Links between Pricing Module and Other Modules`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
This document showcases the module links defined between the Pricing Module and other commerce modules.
|
||||
|
||||
## Fulfillment Module
|
||||
|
||||
The Fulfillment Module provides fulfillment-related functionalities, including shipping options that the customer chooses from when they place their order. However, it doesn't provide pricing-related functionalities for these options.
|
||||
|
||||
Medusa defines a link between the `PriceSet` and `ShippingOption` data models. A shipping option's price is stored as a price set.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Product Module
|
||||
|
||||
The Product Module doesn't store or manage the prices of product variants.
|
||||
|
||||
Medusa defines a link between the `ProductVariant` and the `PriceSet`. A product variant’s prices are stored as prices belonging to a price set.
|
||||
|
||||

|
||||
|
||||
So, when you want to add prices for a product variant, you create a price set and add the prices to it.
|
||||
|
||||
You can then benefit from adding rules to prices or using the `calculatePrices` method to retrieve the price of a product variant within a specified context.
|
||||
@@ -6,7 +6,7 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
The Pricing Module is the `@medusajs/medusa/pricing` NPM package that provides pricing-related features in your Medusa and Node.js applications.
|
||||
The Pricing Module provides pricing-related features in your Medusa and Node.js applications.
|
||||
|
||||
## How to Use Pricing Module's Service
|
||||
|
||||
@@ -15,18 +15,33 @@ You can use the Pricing Module's main service by resolving from the Medusa conta
|
||||
For example:
|
||||
|
||||
<CodeTabs groupId="resource-type">
|
||||
<CodeTab label="Workflow Step" value="workflow-step">
|
||||
|
||||
```ts title="src/workflows/hello-world/step1.ts"
|
||||
import { createStep } from "@medusajs/framework/workflows-sdk"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
const step1 = createStep("step-1", async (_, { container }) => {
|
||||
const pricingModuleService = container.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
const priceSets = await pricingModuleService.listPriceSets()
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="API Route" value="api-route">
|
||||
|
||||
```ts title="src/api/store/custom/route.ts"
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts title="src/api/store/custom/route.ts"
|
||||
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export async function GET(
|
||||
request: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
): Promise<void> {
|
||||
const pricingModuleService: IPricingModuleService = request.scope.resolve(
|
||||
const pricingModuleService = request.scope.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
@@ -39,35 +54,17 @@ export async function GET(
|
||||
</CodeTab>
|
||||
<CodeTab label="Subscriber" value="subscribers">
|
||||
|
||||
```ts title="src/subscribers/custom-handler.ts"
|
||||
import { SubscriberArgs } from "@medusajs/framework"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
```ts title="src/subscribers/custom-handler.ts"
|
||||
import { SubscriberArgs } from "@medusajs/framework"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
export default async function subscriberHandler({ container }: SubscriberArgs) {
|
||||
const pricingModuleService: IPricingModuleService = container.resolve(
|
||||
const pricingModuleService = container.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
const priceSets = await pricingModuleService.listPriceSets()
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="Workflow Step" value="workflow-step">
|
||||
|
||||
```ts title="src/workflows/hello-world/step1.ts"
|
||||
import { createStep } from "@medusajs/framework/workflows-sdk"
|
||||
import { IPricingModuleService } from "@medusajs/framework/types"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
const step1 = createStep("step-1", async (_, { container }) => {
|
||||
const pricingModuleService: IPricingModuleService = container.resolve(
|
||||
Modules.PRICING
|
||||
)
|
||||
|
||||
const priceSets = await pricingModuleService.listPriceSets()
|
||||
})
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
@@ -79,7 +76,7 @@ const step1 = createStep("step-1", async (_, { container }) => {
|
||||
|
||||
### Price Management
|
||||
|
||||
With the Pricing Module, store the prices of a resource and manage them through the main service's methods.
|
||||
Store the prices of a resource and manage them through the main service's methods.
|
||||
|
||||
Prices are grouped in a price set, allowing you to add more than one price for a resource based on different conditions, such as currency code.
|
||||
|
||||
@@ -122,7 +119,9 @@ const priceSet = await pricingModuleService.addPrices({
|
||||
|
||||
### Price Lists
|
||||
|
||||
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.
|
||||
Group prices and apply them only in specific conditions with price lists.
|
||||
|
||||
You can also use them to override existing prices for specified conditions, or create a sale.
|
||||
|
||||
```ts
|
||||
const priceList = await pricingModuleService.createPriceLists([
|
||||
|
||||
@@ -6,7 +6,7 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you'll learn how prices are calculated when you use the `calculatePrices` method of the Pricing Module's main service.
|
||||
In this document, 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
|
||||
|
||||
@@ -14,9 +14,7 @@ The [calculatePrices method](/references/pricing/calculatePrices) accepts as par
|
||||
|
||||
It returns a price object with the best matching price for each price set.
|
||||
|
||||
---
|
||||
|
||||
## Calculation Context
|
||||
### Calculation Context
|
||||
|
||||
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.
|
||||
|
||||
@@ -34,16 +32,18 @@ const price = await pricingModuleService.calculatePrices(
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
In this example, you retrieve the prices in a price set for the specified currency code and region ID.
|
||||
|
||||
## Returned Price Object
|
||||
### Returned Price Object
|
||||
|
||||
For each price set, the method selects two prices:
|
||||
For each price set, the `calculatePrices` method selects two prices:
|
||||
|
||||
- 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.
|
||||
- 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 the price list it belongs to is of type `override`;
|
||||
- Or a price that doesn't belong to a price list and best matches the specified context.
|
||||
|
||||
Both prices are returned in an object along with the following properties:
|
||||
Both prices are returned in an object that has the following properties:
|
||||
|
||||
<TypeList
|
||||
types={[
|
||||
|
||||
@@ -8,24 +8,26 @@ In this document, you'll learn about price rules for price sets and price lists.
|
||||
|
||||
## Price Rule
|
||||
|
||||
Prices can be restricted by rules. Each rule of a price is represented by the [PriceRule data model](/references/pricing/models/PriceRule).
|
||||
You can restrict prices by rules. 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.
|
||||
|
||||

|
||||
|
||||
For exmaple, you create a price restricted to `10557` zip codes.
|
||||
|
||||
A price can have multiple price rules. For example:
|
||||

|
||||
|
||||

|
||||
A price can have multiple price rules.
|
||||
|
||||
For example, a price can be restricted by a region and a zip code.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Price List Rules
|
||||
|
||||
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.
|
||||
Rules 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.
|
||||
|
||||

|
||||
@@ -1,23 +0,0 @@
|
||||
export const metadata = {
|
||||
title: `Relations between Pricing Module and Other Modules`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
This document showcases the link modules defined between the Pricing Module and other commerce modules.
|
||||
|
||||
## Fulfillment Module
|
||||
|
||||
A shipping option's price is stored as a price set. Medusa defines a link module that builds a relationship between the `PriceSet` and `ShippingOption` data models.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Product Module
|
||||
|
||||
A product variant’s prices are stored as prices belonging to a price set. Medusa defines a link module that builds a relationship between the `ProductVariant` and the `PriceSet`.
|
||||
|
||||

|
||||
|
||||
So, when you want to add prices for a product variant, you create a price set and add the prices to it. You can then benefit from adding rules to prices or using the `calculatePrices` method to retrieve the price of a product variant within a specified context.
|
||||
@@ -4,19 +4,19 @@ export const metadata = {
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
In this document, you’ll learn about tax-inclusive pricing and how it's used during prices calculation.
|
||||
In this document, you’ll learn about tax-inclusive pricing and how it's used when calculating prices.
|
||||
|
||||
## What is Tax-Inclusive Pricing?
|
||||
|
||||
A tax-inclusive price is a price that includes taxes. The tax amount is calculated from the price rather than added to it.
|
||||
A tax-inclusive price is a price of a resource that includes taxes. Medusa calculates the tax amount from the price rather than adds the amount to it.
|
||||
|
||||
For example, if a product’s price is $50 and the tax rate is 2%, then the tax-inclusive price is $49, and the applied tax amount is $1.
|
||||
For example, if a product’s price is $50, the tax rate is 2%, and tax-inclusive pricing is enabled, then the product's price is $49, and the applied tax amount is $1.
|
||||
|
||||
---
|
||||
|
||||
## How is Tax-Inclusive Pricing Set?
|
||||
|
||||
The `PricePreference` data model holds the tax-inclusive setting for a context. It has two properties that indicate the context:
|
||||
The [PricePreference data model](/references/pricing/PricePreference) holds the tax-inclusive setting for a context. It has two properties that indicate the context:
|
||||
|
||||
- `attribute`: The name of the attribute to compare against. For example, `region_id` or `currency_code`.
|
||||
- `value`: The attribute’s value. For example, `reg_123` or `usd`.
|
||||
@@ -55,6 +55,12 @@ To get accurate tax results, pass the `region_id` and / or `currency_code` in th
|
||||
|
||||
The `calculatePrices` method returns two properties related to tax-inclusivity:
|
||||
|
||||
<Note title="Tip">
|
||||
|
||||
Learn more about the returned properties in [this guide](../price-calculation/page.mdx#returned-price-object).
|
||||
|
||||
</Note>
|
||||
|
||||
- `is_calculated_price_tax_inclusive`: Whether the selected `calculated_price` is tax-inclusive.
|
||||
- `is_original_price_tax_inclusive` : Whether the selected `original_price` is tax-inclusive.
|
||||
|
||||
@@ -65,10 +71,8 @@ A price is considered tax-inclusive if:
|
||||
|
||||
### Tax Context Precedence
|
||||
|
||||
If:
|
||||
A region’s price preference’s `is_tax_inclusive`'s value takes higher precedence in determining whether a price is tax-inclusive if:
|
||||
|
||||
- both the `region_id` and `currency_code` are provided in the calculation context;
|
||||
- the selected price belongs to the region;
|
||||
- and the region has a price preference
|
||||
|
||||
Then, the region’s price preference’s `is_tax_inclusive`'s value takes higher precedence in determining whether a price is tax-inclusive.
|
||||
Reference in new issue
Block a user