Skip to main content
Skip to main content

AbstractTaxCalculationStrategy

Overview

A tax calculation strategy is used to calculate taxes when calculating a cart's totals. The Medusa backend provides a tax calculation strategy that handles calculating the taxes, taking into account the 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.

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:

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

constructor

You can use the constructor of your tax calculation strategy to access the different services in Medusa through dependency injection.

You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the service. Additionally, if you’re creating your tax calculation strategy as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin, you can access it in the constructor.

Example

import {
ITaxCalculationStrategy,
LineItemService,
} from "@medusajs/medusa"

type InjectedDependencies = {
lineItemService: LineItemService
}

class TaxCalculationStrategy
implements ITaxCalculationStrategy {

protected readonly lineItemService_: LineItemService

constructor({ lineItemService }: InjectedDependencies) {
this.lineItemService_ = lineItemService
}

// ...
}

export default TaxCalculationStrategy

Parameters

containerRecord<string, unknown>Required
An instance of MedusaContainer that allows you to access other resources, such as services, in your Medusa backend.
configRecord<string, unknown>
If this tax calculation strategy is created in a plugin, the plugin's options are passed in this parameter.

Properties

containerRecord<string, unknown>Required
An instance of MedusaContainer that allows you to access other resources, such as services, in your Medusa backend.
manager_EntityManagerRequired
transactionManager_undefined | EntityManagerRequired
__container__anyRequired
configRecord<string, unknown>
If this tax calculation strategy is created in a plugin, the plugin's options are passed in this parameter.
__configModule__Record<string, unknown>
__moduleDeclaration__Record<string, unknown>

Accessors

activeManager_

Returns

EntityManagerEntityManagerRequired

Methods

calculate

This method calculates the tax amount for a given set of line items under applicable tax conditions and calculation contexts.

This method is used whenever taxes are calculated. If automatic tax calculation is disabled in a region, then it's only triggered when taxes are calculated manually as explained in this guide.

Example

An example of the general implementation of this method in the Medusa backend's tax calculation strategy:

async calculate(
items: LineItem[],
taxLines: (ShippingMethodTaxLine | LineItemTaxLine)[],
calculationContext: TaxCalculationContext
): Promise<number> {
const lineItemsTaxLines = taxLines.filter(
(tl) => "item_id" in tl
) as LineItemTaxLine[]
const shippingMethodsTaxLines = taxLines.filter(
(tl) => "shipping_method_id" in tl
) as ShippingMethodTaxLine[]

const lineItemsTax = this.calculateLineItemsTax(
items,
lineItemsTaxLines,
calculationContext
)

const shippingMethodsTax = this.calculateShippingMethodsTax(
calculationContext.shipping_methods,
shippingMethodsTaxLines
)

return Math.round(lineItemsTax + shippingMethodsTax)
}

Parameters

itemsLineItem[]Required
The line items to calculate the tax total for.
The tax lines used for the calculation
calculationContextTaxCalculationContextRequired
Other details relevant for the calculation

Returns

PromisePromise<number>Required
The calculated tax total

withTransaction

Parameters

transactionManagerEntityManager

Returns

thisthisRequired

shouldRetryTransaction_

Parameters

errRecord<string, unknown> | objectRequired

Returns

booleanbooleanRequired

atomicPhase_

Wraps some work within a transactional block. If the service already has a transaction manager attached this will be reused, otherwise a new transaction manager is created.

Type Parameters

TResultobjectRequired
TErrorobjectRequired

Parameters

work(transactionManager: EntityManager) => Promise<TResult>Required
the transactional work to be done
isolationOrErrorHandlerIsolationLevel | (error: TError) => Promise<void | TResult>
the isolation level to be used for the work.
maybeErrorHandlerOrDontFail(error: TError) => Promise<void | TResult>
Potential error handler

Returns

PromisePromise<TResult>Required
the result of the transactional work
Was this section helpful?