Note: This section explains how to work with tax calculations using the older APIs. Episerver recommends using the abstraction APIs to manage tax calculations, as described in Tax calculator.
Episerver Commerce includes a tax subsystem, incorporated into checkout workflows, that calculates a cart's totals, including discounts, shipping costs, and pricing applicable to a particular customer. The tax subsystem, configurable via Commerce Manager, lets you set rates for different locations and SKU tax category.
Classes in this topic are available in the following namespaces:
- Mediachase.Commerce.Workflow.Activities.Cart. Contains CalculateTaxActivity.
- Mediachase.Commerce.Workflow. Contains CartPrepareWorkflow.
- Mediachase.Commerce.Catalog.Managers. Contains CatalogTaxManager.
- Mediachase.Commerce.Orders. Contains OrderContext.
Key classes and files
- CartPrepareWorkflow.xml. Executed after shipping addresses are provided. It includes a cart's tax calculation and other checkout activities.
- CalculateTaxActivity.cs. Part of the CartPrepareWorkflow workflow, performs a cart's tax calculations.
- CatalogTaxManager.cs. Provides tax category information for SKUs.
- OrderContext.cs. Provides the GetTaxes() method to return the tax rate for items based on tax category and jurisdiction.
How it works
During checkout, Microsoft Workflow Foundation workflows calculate the cart total. One workflow, CartPrepare, is run prior to rendering the page where customers confirm their order.
This workflow performs these tasks:
- Determines whether the item is still available, based on the Active status and the item's start and end dates. If the items is not available, it is removed from the cart and an error message is returned and displayed in the CartView.ascx.
- Determines whether the cart items are still available based on remaining stock in inventory, reserved inventory stock, and whether backordering is permitted. If not available, the items are removed and an error message is returned.
- The price for each cart item, based on tiered pricing. If pricing has changed, a message regarding the change is returned, which can be displayed to the user.
- Calculates the extended price for each cart item, for instance multiplying the price by the quantity purchased.
- Calculates discounts.
- Splits line items into their respective shipments, if multiple shipments are created.
- Adds shipping costs to the cart.
- Adds applicable taxes to the cart.
The last action, adding applicable taxes, is done inside the CalculateTaxActivity activity.
Tax calculations are performed in the CalculateTaxes method. For each shipment in a cart, applicable taxes are applied to the Orderform of the cart, based on whether the shipping address is in a jurisdiction with taxes and its tax category. You can apply multiple tax rates (for example, a state and city tax).
The CalculateTaxes method ultimately calls the TaxManager.GetTaxes() method, which executes a stored procedure called ecf_GetTaxes. This procedure retrieves the rows of data from the Tax table where shipping address properties (for instance country or state) and tax category match a tax entry's properties and tax category, and where a shipping address property is null in the shipping address or tax rate rows.
Tax rates are based on jurisdiction parameters (which designate a physical region) and SKU tax categories.
The parameters are:
- Country
- State
- ZipPostalCodeStart
- ZipPostalCodeEnd
- District
- County
- City
- TaxCategory
The stored procedure only matches tax rates for a shipping address, where the property of the rate matches the properties of the shipping address. Null/empty values do not prevent a match. For example, if a tax rate for the State of New Jersey had the following settings:
- Country = US
- State = NJ
- ZipPostalCodeStart = empty
- ZipPostalCodeEnd = empty
- District = empty
- County = empty
- City = empty
- TaxCategory = empty
This tax rate matches all shipping addresses going to New Jersey, US.
Here is another scenario:
- Country = US
- State = CO
- ZipPostalCodeStart = 80101
- ZipPostalCodeEnd = 80113
- District = empty
- County = empty
- City = empty
- TaxCategory = empty
This tax rate only applies to shipping addresses in Colorado, US with zip codes ranging between 80101 and 80113. It does not apply to the zip code 80115, for example. If the zip code range is invalid for the State of Colorado, it does not apply to any shipping addresses.
Conversely, you can apply a tax rate for all shipping addresses in UK for products with a tax category of "Soda" like this:
- Country = UK
- State = empty
- ZipPostalCodeStart = empty
- ZipPostalCodeEnd = empty
- District = empty
- County = empty
- City = empty
- TaxCategory = Soda
Configuring a tax system
To set up tax rates, add or import them through Commerce Manager or use the TaxImportExport class. For more information about configuring tax rates and jurisdictions, see Configuring Taxes in the Commerce User Guide.
Example: using TaxImportExport class to import Tax rates.
using Mediachase.Commerce.Orders.ImportExport;
public void ImportTaxes()
{
var taxImportExport= new TaxImportExport();
var csvFilePath = "[the file path of imported csv file]";
taxImportExport.Import(csvFilePath, ',');
}
The format of csv file is described below. Download a sample csv file.Order | Column name | Description |
1 | JurisdictionName | The jurisdiction name |
2 | StateProvinceCode | The state or province code |
3 | CountryCode | The country code |
4 | ZipPostalCodeStart | The zip/postal code start |
5 | ZipPostalCodeEnd | The zip/postal code end |
6 | City | The city |
7 | District | The district |
8 | County | The county |
9 | GeoCode | The geo code |
10 | JurisdictionCode | The jurisdiction code |
11 | JurisdictionGroupName | The jurisdiction group name |
12 | JurisdictionGroupCode | The jurisdiction group code |
13 | TaxNativeName | The tax native name |
14 | TaxName | The tax name |
15 | SortOrder | The sort order |
16 | LanguageCode | The language code |
17 | TaxCategory | The tax category |
18 | Percentage | The percentage |
19 | EffectiveDate | The effective date |
20 | TaxType | The tax type: SalesTax or ShippingTax |
Customizing taxes
To customize tax calculations, create a workflow that mirrors CartPrepareWorkflow, but substitute the CalculateTaxActivity activity with your own implementation.
Your implementation can access any internal or external tax calculation service. For the activity to work properly with other activities that calculate cart totals, your activity must set the TotalTax property of each OrderForm in the cart.
Related topic
Last updated: Apr 01, 2021