Skip to main content
Skip to main content

AbstractTaxService

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.

A tax provider class is defined in a TypeScript or JavaScript file under the src/services directory and the class must extend the AbstractTaxService class imported from @medusajs/medusa. The file's name is the tax provider's class name as a slug and without the word Service.

For example, you can create the file src/services/my-tax.ts with the following content:

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

Identifier Property

The TaxProvider entity has 2 properties: identifier and is_installed. The identifier property in the tax provider service is used when the tax provider is added to the database.

The value of this property is also used to reference the tax provider throughout Medusa. For example, it is used to change the tax provider to a region.

src/services/my-tax.ts
class MyTaxService extends AbstractTaxService {
static identifier = "my-tax"
// ...
}

constructor

You can use the constructor of your tax provider 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 provider 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 { LineItemService } from "@medusajs/medusa"

type InjectedDependencies = {
lineItemService: LineItemService
}

class MyTaxService extends AbstractTaxService {
protected readonly lineItemService_: LineItemService

constructor({ lineItemService }: InjectedDependencies) {
super(arguments[0])
this.lineItemService_ = lineItemService

// you can also initialize a client that
// communicates with a third-party service.
this.client = new Client(options)
}

// ...
}

export default MyTaxService

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 provider is created in a plugin, the plugin's options are passed in this parameter.

Properties

identifierstringRequired
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 provider 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

getTaxLines

This method is used when retrieving the tax lines for line items and shipping methods. This occurs during checkout or when calculating totals for orders, swaps, or returns.

Example

An example of how this method is implemented in the system provider implemented in the Medusa backend:

// ...

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
}
}

Parameters

itemLinesItemTaxCalculationLine[]Required
The line item lines to calculate taxes for.
shippingLinesShippingTaxCalculationLine[]Required
The shipping method lines to calculate taxes for.
contextTaxCalculationContextRequired
Context relevant and useful for the taxes calculation.

Returns

PromisePromise<ProviderTaxLine[]>Required
The list of calculated line item and shipping method tax lines. If an item in the array has the shipping_method_id property, then it's a shipping method tax line. Otherwise, if it has the item_id property, then it's a line item tax line.

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?