docs: migrate guides to TSDoc references (#6100)
This commit is contained in:
@@ -29,7 +29,7 @@ The [Local Event Bus module](../../../development/events/modules/local.md) works
|
||||
|
||||
As mentioned in the overview, this guide illustrates how to send the email using SendGrid. If you intend to follow along, you must have the [SendGrid plugin](../../../plugins/notifications/sendgrid.mdx) installed and configured.
|
||||
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../development/notification/create-notification-provider.md).
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
---
|
||||
|
||||
@@ -141,6 +141,6 @@ Where `<NOTIFICATION_PROVIDER_IDENTIFIER>` is the identifier for your notifica
|
||||
|
||||
:::note
|
||||
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md).
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
:::
|
||||
|
||||
@@ -31,7 +31,7 @@ It's assumed that you already have a Medusa backend installed and set up. If not
|
||||
|
||||
### Notification Provider
|
||||
|
||||
To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an [existing plugin](../../../plugins/notifications/index.mdx) or [create your own](../../../development/notification/create-notification-provider.md).
|
||||
To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an [existing plugin](../../../plugins/notifications/index.mdx) or [create your own](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
---
|
||||
|
||||
@@ -149,6 +149,6 @@ Where `<NOTIFICATION_PROVIDER_IDENTIFIER>` is the identifier for your notifica
|
||||
|
||||
:::note
|
||||
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md).
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
:::
|
||||
|
||||
@@ -27,7 +27,7 @@ It's assumed that you already have a Medusa backend installed and set up. If not
|
||||
|
||||
### Notification Provider
|
||||
|
||||
To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../../../development/notification/create-notification-provider.md).
|
||||
To send an email or another type of notification method, you must have a notification provider installed or configured. You can either install an existing plugin or [create your own](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
This document has an example using the [SendGrid](../../../plugins/notifications/sendgrid.mdx) plugin.
|
||||
|
||||
@@ -153,7 +153,7 @@ Where `<NOTIFICATION_PROVIDER_IDENTIFIER>` is the identifier for your notifica
|
||||
|
||||
:::note
|
||||
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md).
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ The [Local Event Bus module](../../../development/events/modules/local.md) works
|
||||
|
||||
As mentioned in the overview, this guide illustrates how to send the email using SendGrid. If you intend to follow along, you must have the [SendGrid plugin](../../../plugins/notifications/sendgrid.mdx) installed and configured.
|
||||
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../development/notification/create-notification-provider.md).
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
---
|
||||
|
||||
@@ -153,6 +153,6 @@ Where `<NOTIFICATION_PROVIDER_IDENTIFIER>` is the identifier for your notifica
|
||||
|
||||
:::note
|
||||
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md).
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
:::
|
||||
|
||||
-295
@@ -1,295 +0,0 @@
|
||||
---
|
||||
description: 'Learn how to override the price selection strategy. The price selection strategy is used to determine the best price based on a specific context.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
import ParameterTypes from "@site/src/components/ParameterTypes"
|
||||
|
||||
# How to Override Price Selection Strategy
|
||||
|
||||
In this document, you’ll learn how to override Medusa’s price selection strategy to create a custom pricing strategy.
|
||||
|
||||
:::note
|
||||
|
||||
If you’re interested in learning what a price selection strategy is and how it works, check out [this documentation](../price-selection-strategy.md) instead.
|
||||
|
||||
:::
|
||||
|
||||
## 1. Create Class
|
||||
|
||||
Create a TypeScript or JavaScript file in `src/strategies` of your Medusa backend project with a class that extends the `AbstractPriceSelectionStrategy` class:
|
||||
|
||||
```ts title="src/strategies/price.ts"
|
||||
import {
|
||||
AbstractPriceSelectionStrategy,
|
||||
PriceSelectionContext,
|
||||
PriceSelectionResult,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
TaxServiceRate,
|
||||
} from "@medusajs/medusa/dist/types/tax-service"
|
||||
|
||||
export default class MyStrategy extends
|
||||
AbstractPriceSelectionStrategy {
|
||||
|
||||
async calculateVariantPrice(
|
||||
data: {
|
||||
variantId: string;
|
||||
taxRates: TaxServiceRate[];
|
||||
quantity?: number
|
||||
}[],
|
||||
context: PriceSelectionContext
|
||||
): Promise<Map<string, PriceSelectionResult>> {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Resolve Resources
|
||||
|
||||
You can resolve resources like services or repositories using [dependency injection](../../../development/fundamentals/dependency-injection.md).
|
||||
|
||||
For example:
|
||||
|
||||
```ts title="src/strategies/price.ts"
|
||||
import {
|
||||
AbstractPriceSelectionStrategy,
|
||||
CustomerService,
|
||||
PriceSelectionContext,
|
||||
PriceSelectionResult,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
TaxServiceRate,
|
||||
} from "@medusajs/medusa/dist/types/tax-service"
|
||||
|
||||
type InjectedDependencies = {
|
||||
customerService: CustomerService
|
||||
}
|
||||
|
||||
export default class MyStrategy extends
|
||||
AbstractPriceSelectionStrategy {
|
||||
|
||||
protected customerService_: CustomerService
|
||||
|
||||
constructor(container: InjectedDependencies) {
|
||||
super(container)
|
||||
this.customerService_ = container.customerService
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Implement calculateVariantPrice
|
||||
|
||||
In this method, you can implement your price selection strategy.
|
||||
|
||||
### Parameters
|
||||
|
||||
You can learn more about optional properties and the meaning behind every property [here](../price-selection-strategy.md#calculatevariantprice-method).
|
||||
|
||||
<ParameterTypes parameters={[
|
||||
{
|
||||
name: "data",
|
||||
type: "object[]",
|
||||
description: "Holds the data necessary to perform the price selection for each variant ID.",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "variantId",
|
||||
type: "string",
|
||||
description: "The ID of the variant to retrieve the prices for.",
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
name: "taxRates",
|
||||
type: "object[]",
|
||||
description: "The tax rates to be applied. This is only used for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "rate",
|
||||
type: "number | null",
|
||||
description: "The tax rate",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
description: "The name of the tax rate",
|
||||
optional: false
|
||||
},
|
||||
{
|
||||
name: "code",
|
||||
type: "string | null",
|
||||
description: "The code of the tax rate",
|
||||
optional: false
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "quantity",
|
||||
type: "number",
|
||||
description: "The quantity of the variant",
|
||||
optional: true
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "context",
|
||||
type: "[PriceSelectionContext](../price-selection-strategy.md#context-object)",
|
||||
description: "The context of the price selection",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "cart_id",
|
||||
type: "string",
|
||||
description: "The ID of the customer’s cart. This is used when the prices are being retrieved for the variant of a line item, as it is used to determine the current region and currency code of the context.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "customer_id",
|
||||
type: "string",
|
||||
description: "The ID of the customer. This is used to filter out price lists for a customer group that this customer doesn’t belong to.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "region_id",
|
||||
type: "string",
|
||||
description: "The ID of the region the customer is using.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "quantity",
|
||||
type: "number",
|
||||
description: "The quantity of the item in the cart. This is used to filter out price lists that have `min_quantity` or `max_quantity` conditions set.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "currency_code",
|
||||
type: "string",
|
||||
description: "The currency code the customer is using.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "include_discount_prices",
|
||||
type: "boolean",
|
||||
description: "Whether the price list's prices should be retrieved or not.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "taxRates",
|
||||
type: "object[]",
|
||||
description: "The tax rates to be applied. This is only used for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "rate",
|
||||
type: "number | null",
|
||||
description: "The tax rate",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
description: "The name of the tax rate",
|
||||
optional: false
|
||||
},
|
||||
{
|
||||
name: "code",
|
||||
type: "string | null",
|
||||
description: "The code of the tax rate",
|
||||
optional: false
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ignore_cache",
|
||||
type: "boolean",
|
||||
description: "Whether to calculate the prices even if the value of an earlier price calculation is available in the cache.",
|
||||
optional: true
|
||||
},
|
||||
]
|
||||
}
|
||||
]} />
|
||||
|
||||
### Returns
|
||||
|
||||
<ParameterTypes parameters={[
|
||||
{
|
||||
name: "Promise",
|
||||
type: "Promise<Map<string, PriceSelectionResult>>",
|
||||
description: "A map, each key is an ID of a variant, and its value is an object holding the price selection result.",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "PriceSelectionResult",
|
||||
type: "PriceSelectionResult",
|
||||
description: "The price selection result of a variant.",
|
||||
optional: false,
|
||||
children: [
|
||||
{
|
||||
name: "originalPrice",
|
||||
type: "number | null",
|
||||
description: "The original price of the variant which depends on the selected region or currency code in the context object. If both region ID and currency code are available in the context object, the region has higher precedence.",
|
||||
optional: false
|
||||
},
|
||||
{
|
||||
name: "originalPriceIncludesTax",
|
||||
type: "boolean | null",
|
||||
description: "Whether the original price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "calculatedPrice",
|
||||
type: "number | null",
|
||||
description: "The lowest price among the prices of the product variant retrieved using the context object.",
|
||||
optional: false
|
||||
},
|
||||
{
|
||||
name: "calculatedPriceIncludesTax",
|
||||
type: "boolean | null",
|
||||
description: "Whether the calculated price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "calculatedPriceType",
|
||||
type: "enum",
|
||||
description: "Either `default` if the `calculatedPrice` is the original price, or the type of the price list applied, which can be `override` or `sale`.",
|
||||
optional: true
|
||||
},
|
||||
{
|
||||
name: "prices",
|
||||
type: "[MoneyAmount](../../../references/entities/classes/entities.MoneyAmount.mdx)[]",
|
||||
description: "The prices of the variant retrieved using the `context` object. It can include its original price and its price lists if there are any.",
|
||||
optional: false
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## 3. Run Build Command
|
||||
|
||||
In your terminal, run the build command to transpile the files in the `src` directory into the `dist` directory:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test it Out
|
||||
|
||||
Run your backend to test it out:
|
||||
|
||||
```bash npm2yarn
|
||||
npx medusa develop
|
||||
```
|
||||
|
||||
Then, try out your strategy using any of the [Products](https://docs.medusajs.com/api/store#products) or [Carts](https://docs.medusajs.com/api/store#carts) API Routes which include retrieving product variants and line items respectively. You should then see the prices in the response based on your implemented strategy.
|
||||
@@ -45,7 +45,7 @@ Developers can change the default logic behind how prices are selected to be sho
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
href: '/modules/price-lists/backend/override-price-selection-strategy',
|
||||
href: '/modules/price-lists/price-selection-strategy',
|
||||
label: 'Backend: Override Price Selection',
|
||||
customProps: {
|
||||
icon: Icons['users-solid'],
|
||||
|
||||
@@ -45,11 +45,11 @@ You can use any of the following conditions:
|
||||
|
||||
## How are Price Lists Applied
|
||||
|
||||
When a product or a line item is retrieved or manipulated on the storefront, Medusa determines its price using a Price Selection Strategy. The price selection strategy determines the best price to apply in a given [context](./price-selection-strategy.md#context-object). Part of determining the price depends on the price list.
|
||||
When a product or a line item is retrieved or manipulated on the storefront, Medusa determines its price using a Price Selection Strategy. The price selection strategy determines the best price to apply in a given context. Part of determining the price depends on the price list.
|
||||
|
||||
:::info
|
||||
|
||||
This section explains how the price selection strategy uses price lists when it determines the price of a product variant. If you want full details on how the price selection strategy works, check out this documentation instead.
|
||||
This section explains how the [price selection strategy](../../references/price_selection/interfaces/price_selection.IPriceSelectionStrategy.mdx) uses price lists when it determines the price of a product variant. If you want full details on how the price selection strategy works, check out [this documentation](../../references/price_selection/interfaces/price_selection.IPriceSelectionStrategy.mdx) instead.
|
||||
|
||||
:::
|
||||
|
||||
@@ -59,7 +59,7 @@ When the strategy calculates the prices of a product variant, it retrieves both
|
||||
|
||||
The original price depends on the selected region or currency code in the current context, where the region has higher precedence.
|
||||
|
||||
The calculated price is the lowest price among all retrieved prices. Retrieved prices can include the original price and the price lists that can be applied. Prices are retrieved based on the [context](./price-selection-strategy.md#context-object).
|
||||
The calculated price is the lowest price among all retrieved prices. Retrieved prices can include the original price and the price lists that can be applied. Prices are retrieved based on the provided context, such as region ID or currency code.
|
||||
|
||||
In the [Get Product](https://docs.medusajs.com/api/store#products_getproductsproduct) and [List Product](https://docs.medusajs.com/api/store#products_getproducts) API Routes, you must pass either the `region_id` or `currency_code` to retrieve the correct prices, as they are part of the price selection strategy context.
|
||||
|
||||
@@ -87,5 +87,5 @@ Since the line item belongs to a cart, there’s no need to pass the `region_id`
|
||||
|
||||
## See Also
|
||||
|
||||
- [Price Selection Strategy Overview](./price-selection-strategy.md)
|
||||
- [Price Selection Strategy](../../references/price_selection/classes/price_selection.AbstractPriceSelectionStrategy.mdx)
|
||||
- [Manage price lists using the admin APIs](./admin/manage-price-lists.mdx)
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
description: 'Learn what the price selection strategy is in the Medusa backend. The price selection strategy retrieves the best price for a product variant for a specific context.'
|
||||
---
|
||||
|
||||
# Price Selection Strategy
|
||||
|
||||
In this document, you’ll learn what a price selection strategy is.
|
||||
|
||||
:::note
|
||||
|
||||
If you’re interested to learn how to override the price selection strategy, check out [this documentation](./backend/override-price-selection-strategy.mdx) instead.
|
||||
|
||||
:::
|
||||
|
||||
## What's a Price Selection Strategy
|
||||
|
||||
Medusa provides many features and different ways to control the price of a product variant. This includes price lists and their different conditions, products’ original prices, and taxes.
|
||||
|
||||
Medusa uses the `PriceSelectionStrategy` class to retrieve the best price for a product variant for a specific context. This strategy is used whenever products and line items are retrieved or manipulated on the storefront.
|
||||
|
||||
---
|
||||
|
||||
## PriceSelectionStrategy Overview
|
||||
|
||||
The `PriceSelectionStrategy` class extends the `AbstractPriceSelectionStrategy` class. Its main method is the `calculateVariantPrice`.
|
||||
|
||||
### calculateVariantPrice Method
|
||||
|
||||
Medusa uses this method to retrieve one or more product variants' prices. This method is used when retrieving product variants or their associated line items. It's also used when retrieving other entities that product variants and line items belong to, such as products and carts respectively.
|
||||
|
||||
This method accepts two parameters:
|
||||
|
||||
1. The first parameter is an array of objects, each object having the following properties:
|
||||
1. `variantId`: a string indicating the ID of the variant to calculate the price for.
|
||||
2. `quantity`: an optional number indicating the quantity of the variant.
|
||||
2. A [context](#context-object) object.
|
||||
|
||||
The method retrieves all the available prices of the variant based on the conditions in the context object.
|
||||
|
||||
It returns an object with the following properties:
|
||||
|
||||
1. `originalPrice`: The original price of the variant which depends on the selected region or currency code in the context object. If both region ID and currency code are available in the context object, the region has higher precedence.
|
||||
2. `originalPriceIncludesTax`: A boolean value indicating whether the original price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../taxes/inclusive-pricing.md).
|
||||
3. `calculatedPrice`: The lowest price among the prices of the product variant retrieved using the context object.
|
||||
4. `calculatedPriceIncludesTax`: A boolean value indicating whether the calculated price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../taxes/inclusive-pricing.md).
|
||||
5. `calculatedPriceType`: Either `default` if the `calculatedPrice` is the original price, or the type of the price list applied.
|
||||
6. `prices`: an array of all the prices of the variant retrieved using the context object. It can include its original price and its price lists if there are any.
|
||||
|
||||
:::info
|
||||
|
||||
You can learn more about price lists and how they’re used in [this documentation](./price-lists.md).
|
||||
|
||||
:::
|
||||
|
||||
### Context Object
|
||||
|
||||
The context that is passed to the `calculateVariantPrice` method is an object that has the following optional properties:
|
||||
|
||||
- `cart_id`: A string indicating the ID of the customer’s cart. This is used when the prices are being retrieved for the variant of a line item, as it is used to determine the current region and currency code of the context.
|
||||
- `customer_id`: A string indicating the ID of the customer. This is used to filter out price lists for a customer group that this customer doesn’t belong to.
|
||||
- `quantity`: A number indicating the quantity of the item in the cart. This is used to filter out price lists that have `min_quantity` or `max_quantity` conditions set.
|
||||
- `region_id`: A string indicating the ID of the region the customer is using.
|
||||
- `currency_code`: A string indicating the currency code the customer is using.
|
||||
- `include_discount_prices`: A boolean value indicating whether price list prices should be retrieved or not.
|
||||
- `tax_rates`: An array of objects indicating the tax rates to be applied. This is only used for [Tax-Inclusive Pricing](../taxes/inclusive-pricing.md).
|
||||
- `ignore_cache`: a boolean value indicating whether to calculate the prices even if the value of an earlier price calculation is available in the cache.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Override the Price Selection Strategy](./backend/override-price-selection-strategy.mdx)
|
||||
@@ -86,5 +86,5 @@ The relation is available on the `PaymentCollection` entity by expanding the `cu
|
||||
|
||||
## See Also
|
||||
|
||||
- [Price Selection Strategy](../price-lists/price-selection-strategy.md)
|
||||
- [Price Selection Strategy](../../references/price_selection/classes/price_selection.AbstractPriceSelectionStrategy.mdx)
|
||||
- [Tax-Inclusive Pricing](../taxes/inclusive-pricing.md)
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
---
|
||||
description: 'Learn how to create a tax provider. You can create a tax provider in a Medusa backend or a plugin.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# How to Create a Tax Provider
|
||||
|
||||
In this document, you’ll learn how to create a tax provider.
|
||||
|
||||
## Overview
|
||||
|
||||
A tax provider is used to retrieve the tax lines in a cart. The Medusa backend provides a default `system` provider. You can create your own tax provider, either in a plugin or directly in your Medusa backend, then use it in any region.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create Tax Provider Class
|
||||
|
||||
A tax provider class should be defined in a TypeScript or JavaScript file under `src/services` and the class should extend `AbstractTaxService` imported from `@medusajs/medusa`.
|
||||
|
||||
For example, you can create the file `src/services/my-tax.ts` with the following content:
|
||||
|
||||
```ts title="src/services/my-tax.ts"
|
||||
import {
|
||||
AbstractTaxService,
|
||||
ItemTaxCalculationLine,
|
||||
ShippingTaxCalculationLine,
|
||||
TaxCalculationContext,
|
||||
} from "@medusajs/medusa"
|
||||
import {
|
||||
ProviderTaxLine,
|
||||
} from "@medusajs/medusa/dist/types/tax-service"
|
||||
|
||||
class MyTaxService extends AbstractTaxService {
|
||||
async getTaxLines(
|
||||
itemLines: ItemTaxCalculationLine[],
|
||||
shippingLines: ShippingTaxCalculationLine[],
|
||||
context: TaxCalculationContext):
|
||||
Promise<ProviderTaxLine[]> {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
}
|
||||
|
||||
export default MyTaxService
|
||||
```
|
||||
|
||||
Since the class extends `AbstractTaxService`, it must implement its abstract method `getTaxLines`, which is explained later in this guide.
|
||||
|
||||
### Using a Constructor
|
||||
|
||||
You can use a constructor to access services and resources registered in the dependency container using dependency injection. For example:
|
||||
|
||||
```ts title="src/services/my-tax.ts"
|
||||
// ...
|
||||
import { LineItemService } from "@medusajs/medusa"
|
||||
|
||||
type InjectedDependencies = {
|
||||
lineItemService: LineItemService
|
||||
}
|
||||
|
||||
class MyTaxService extends AbstractTaxService {
|
||||
protected readonly lineItemService_: LineItemService
|
||||
|
||||
constructor({ lineItemService }: InjectedDependencies) {
|
||||
super()
|
||||
this.lineItemService_ = lineItemService
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
export default MyTaxService
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Define Identifier
|
||||
|
||||
Every tax provider must have a unique identifier. The identifier is defined as a static property in the class, and its value is used when registering the tax provider in the database and in the dependency container.
|
||||
|
||||
Add the static property `identifier` in your tax provider class:
|
||||
|
||||
```ts title="src/services/my-tax.ts"
|
||||
class MyTaxService extends AbstractTaxService {
|
||||
static identifier = "my-tax"
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to change `my-tax` to the name of your tax provider.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Implement getTaxLines Method
|
||||
|
||||
The `getTaxLines` method is the only required method in a tax provider. It’s used when retrieving the tax lines for line items and shipping methods, typically during checkout or when calculating totals, for example, for orders, swaps, or returns.
|
||||
|
||||
The method accepts three parameters. The first parameter is an array of tax calculation objects for line items. Each object having the following properties:
|
||||
|
||||
- `item`: a line item object.
|
||||
- `rates`: an array of objects, each object having the following properties:
|
||||
- `rate`: an optional number indicating the tax rate.
|
||||
- `name`: a string indicating the name of the tax rate.
|
||||
- `code`: an optional string indicating the tax code.
|
||||
|
||||
The second parameter is an array of tax calculation objects for shipping methods. Each object having the following properties:
|
||||
|
||||
- `shipping_method`: a shipping method object.
|
||||
- `rates`: an array of objects, each object having the following properties:
|
||||
- `rate`: an optional number indicating the tax rate.
|
||||
- `name`: a string indicating the name of the tax rate.
|
||||
- `code`: an optional string indicating the tax code.
|
||||
|
||||
The third parameter is a context object that can be helpful for the tax calculation. The object can have the following properties:
|
||||
|
||||
- `shipping_address`: an optional address object used for shipping.
|
||||
- `customer`: an optional customer object.
|
||||
- `region`: an optional region object.
|
||||
- `is_return`: a boolean value that determines whether the taxes are being calculated for a return flow.
|
||||
- `shipping_methods`: an array of shipping methods being used in the current context.
|
||||
- `allocation_map`: an object that indicates the gift cards and discounts applied on line items. Each object key or property is an ID of a line item, and the value is an object having the following properties:
|
||||
- `gift_card`: an optional object indicating the gift card applied on the line item.
|
||||
- `discount`: an optional object indicating the discount applied on the line item.
|
||||
|
||||
This method is expected to return an array of line item tax line or shipping method tax line objects.
|
||||
|
||||
The line item tax line object has the following properties:
|
||||
|
||||
- `rate`: a number indicating the tax rate.
|
||||
- `name`: a string indicating the name of the tax rate.
|
||||
- `code`: a string indicating the tax code.
|
||||
- `item_id`: the ID of the line item.
|
||||
- `metadata`: an optional object that can hold any necessary additional data to be added to the line item tax lines.
|
||||
|
||||
:::note
|
||||
|
||||
Tax lines for line item must have a unique `code` and `item_id` combination. Otherwise, the tax lines will be applied multiple times.
|
||||
|
||||
:::
|
||||
|
||||
The shipping method tax line object has the following properties:
|
||||
|
||||
- `rate`: a number indicating the tax rate.
|
||||
- `name`: a string indicating the name of the tax rate.
|
||||
- `code`: a string indicating the tax code.
|
||||
- `shipping_method_id`: the ID of the shipping method.
|
||||
- `metadata`: an optional object that can hold any necessary additional data to be added to the shipping method tax lines.
|
||||
|
||||
:::note
|
||||
|
||||
Tax lines for a shipping method must have a unique `code` and `shipping_method_id` combination. Otherwise, the tax lines will be applied multiple times.
|
||||
|
||||
:::
|
||||
|
||||
The returned array would be a combination of both the line item tax lines and shipping method tax lines.
|
||||
|
||||
:::note
|
||||
|
||||
The Medusa backend determines whether an object in the returned array is a shipping method tax line item, depending on the availability of the `shipping_method_id` attribute. For line items, it depends on the availability of the `item_id` attribute.
|
||||
|
||||
:::
|
||||
|
||||
For example, the `system` tax provider returns the tax calculation line items in the first parameter and the tax calculation shipping methods in the second parameter as is:
|
||||
|
||||
```ts title="src/services/my-tax.ts"
|
||||
// ...
|
||||
|
||||
class SystemTaxService extends AbstractTaxService {
|
||||
// ...
|
||||
|
||||
async getTaxLines(
|
||||
itemLines: ItemTaxCalculationLine[],
|
||||
shippingLines: ShippingTaxCalculationLine[],
|
||||
context: TaxCalculationContext
|
||||
): Promise<ProviderTaxLine[]> {
|
||||
let taxLines: ProviderTaxLine[] = itemLines.flatMap((l) => {
|
||||
return l.rates.map((r) => ({
|
||||
rate: r.rate || 0,
|
||||
name: r.name,
|
||||
code: r.code,
|
||||
item_id: l.item.id,
|
||||
}))
|
||||
})
|
||||
|
||||
taxLines = taxLines.concat(
|
||||
shippingLines.flatMap((l) => {
|
||||
return l.rates.map((r) => ({
|
||||
rate: r.rate || 0,
|
||||
name: r.name,
|
||||
code: r.code,
|
||||
shipping_method_id: l.shipping_method.id,
|
||||
}))
|
||||
})
|
||||
)
|
||||
|
||||
return taxLines
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Run the Build Command
|
||||
|
||||
In the directory of the Medusa backend, run the `build` command to transpile the files in the `src` directory into the `dist` directory:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test it Out
|
||||
|
||||
Run your backend to test it out:
|
||||
|
||||
```bash npm2yarn
|
||||
npx medusa develop
|
||||
```
|
||||
|
||||
Before you can test out your tax provider, you must enable it in a region. You can do that either using the [Medusa Admin dashboard](../../../user-guide/taxes/manage.md#change-tax-provider) or using the [Update Region admin API Route](../admin/manage-tax-settings.mdx#change-tax-provider-of-a-region).
|
||||
|
||||
Then, you can test out the tax provider by simulating a checkout process in that region. You should see the line item tax lines in the cart’s `items`, as each item object has a `tax_lines` array which are the tax lines that you return in the `getTaxLines` method for line items.
|
||||
|
||||
Similarly, you should see the shipping method tax lines in the cart’s `shipping_methods`, as each shipping method object has a `tax_lines` array which are the tax lines that you return in the `getTaxLines` method for shipping methods.
|
||||
@@ -1,132 +0,0 @@
|
||||
---
|
||||
description: 'Learn how to create a tax provider. You can create a tax provider in a Medusa backend or a plugin.'
|
||||
addHowToData: true
|
||||
---
|
||||
|
||||
# How to Override a Tax Calculation Strategy
|
||||
|
||||
In this document, you’ll learn how to override a tax calculation strategy.
|
||||
|
||||
## Overview
|
||||
|
||||
A tax calculation strategy is used to calculate taxes when calculating totals. The Medusa backend provides a tax calculation strategy that handles calculating the taxes accounting for defined tax rates, and settings such as whether tax-inclusive pricing is enabled.
|
||||
|
||||
You can override the tax calculation strategy to implement different calculation logic or to integrate a third-party service that handles the tax calculation. You can override it either in a Medusa backend setup or in a plugin.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create Strategy Class
|
||||
|
||||
A tax calculation strategy should be defined in a TypeScript or JavaScript file created under the `src/strategies` directory. The class must also implement the `ITaxCalculationStrategy` interface imported from the `@medusajs/medusa` package.
|
||||
|
||||
For example, you can create the file `src/strategies/tax-calculation.ts` with the following content:
|
||||
|
||||
```ts title="src/strategies/tax-calculation.ts"
|
||||
import {
|
||||
ITaxCalculationStrategy,
|
||||
LineItem,
|
||||
LineItemTaxLine,
|
||||
ShippingMethodTaxLine,
|
||||
TaxCalculationContext,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
class TaxCalculationStrategy
|
||||
implements ITaxCalculationStrategy {
|
||||
|
||||
async calculate(
|
||||
items: LineItem[],
|
||||
taxLines: (ShippingMethodTaxLine | LineItemTaxLine)[],
|
||||
calculationContext: TaxCalculationContext
|
||||
): Promise<number> {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default TaxCalculationStrategy
|
||||
```
|
||||
|
||||
Note that you add a basic implementation of the `calculate` method because it’s required by the `ITaxCalculationStrategy` interface. You’ll learn about the method later in the guide.
|
||||
|
||||
### Using a Constructor
|
||||
|
||||
You can use a constructor to access services and resources registered in the dependency container using dependency injection. For example:
|
||||
|
||||
```ts title="src/strategies/tax-calculation.ts"
|
||||
// ...
|
||||
import {
|
||||
LineItemService,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
type InjectedDependencies = {
|
||||
lineItemService: LineItemService
|
||||
}
|
||||
|
||||
class TaxCalculationStrategy
|
||||
implements ITaxCalculationStrategy {
|
||||
|
||||
protected readonly lineItemService_: LineItemService
|
||||
|
||||
constructor({ lineItemService }: InjectedDependencies) {
|
||||
this.lineItemService_ = lineItemService
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Implement the calculate Method
|
||||
|
||||
A tax calculation strategy is only required to implement the `calculate` method. This method is used whenever the totals are calculated.
|
||||
|
||||
:::tip
|
||||
|
||||
If automatic tax calculation is disabled, then the tax calculation strategy will only be used when taxes are calculated manually as explain [this guide](../storefront/manual-calculation.md).
|
||||
|
||||
:::
|
||||
|
||||
The `calculate` method expects three parameters:
|
||||
|
||||
- `items`: the first parameter is an array of [line item](../../../references/entities/classes/entities.LineItem.mdx) objects.
|
||||
- `taxLines`: the second parameter is an array of either [shipping method tax line](../../../references/entities/classes/entities.ShippingMethodTaxLine.mdx) or [line item tax line](../../../references/entities/classes/entities.LineItemTaxLine.mdx) objects.
|
||||
- `calculationContext`: an object holding the context of the tax calculation. The object has the following properties:
|
||||
- `shipping_address`: an optional address object used for shipping.
|
||||
- `customer`: an optional customer object.
|
||||
- `region`: an optional region object.
|
||||
- `is_return`: a boolean value that determines whether the taxes are being calculated for a return flow.
|
||||
- `shipping_methods`: an array of shipping methods being used in the current context.
|
||||
- `allocation_map`: an object that indicates the gift cards and discounts applied on line items. Each object key or property is an ID of a line item, and the value is an object having the following properties:
|
||||
- `gift_card`: an optional object indicating the gift card applied on the line item.
|
||||
- `discount`: an optional object indicating the discount applied on the line item.
|
||||
|
||||
The method returns a number, being the tax amount for the line items, tax lines, and context provided.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Run Build Command
|
||||
|
||||
In the directory of the Medusa backend, run the `build` command to transpile the files in the `src` directory into the `dist` directory:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Test it Out
|
||||
|
||||
Run your backend to test it out:
|
||||
|
||||
```bash npm2yarn
|
||||
npx medusa develop
|
||||
```
|
||||
|
||||
To test it out, you can simulate a checkout flow and check the calculated taxes to see if it matches the logic you implemented in the `calculate` method.
|
||||
|
||||
:::tip
|
||||
|
||||
As mentioned earlier, if automatic calculation of taxes is disabled in the region, you have to manually trigger tax calculation as explained in [this guide](../storefront/manual-calculation.md).
|
||||
|
||||
:::
|
||||
@@ -27,7 +27,7 @@ The [Local Event Bus module](../../../development/events/modules/local.md) works
|
||||
|
||||
As mentioned in the overview, this guide illustrates how to send the email using SendGrid. If you intend to follow along, you must have the [SendGrid plugin](../../../plugins/notifications/sendgrid.mdx) installed and configured.
|
||||
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../development/notification/create-notification-provider.md).
|
||||
You can also find other available Notification provider plugins in the [Plugins directory](https://medusajs.com/plugins/), or [create your own](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
---
|
||||
|
||||
@@ -147,6 +147,6 @@ Where `<NOTIFICATION_PROVIDER_IDENTIFIER>` is the identifier for your notifica
|
||||
|
||||
:::note
|
||||
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../development/notification/create-notification-provider.md).
|
||||
You can learn more about handling events with the Notification Service using [this documentation](../../../references/notification/classes/notification.AbstractNotificationService.mdx).
|
||||
|
||||
:::
|
||||
|
||||
Reference in New Issue
Block a user