Adding tax to the shipping charge
This article describes how to customize your E-commerce checkout process, so that tax (e.g. VAT) is applied on the shipping charge, not only on the products.
In summary, you could calculate tax in the
CalculateShipping method, where you can store the calculated tax into the
cart.ShoppingCartCustomData hashtable and then in the
EvaluateShoppingCartContent() method you can acquire it to display it in tax summary.
The
CalculateShipping method will ensure adding tax to shipping using information about the shipping address. The tax will be applied to shipping anytime shipping will be acquired.
You can find some more information and a similar example in the
E-commerce guide.
Please refer below to see the necessary steps with a sample code for the involved methods;
Complete modified codefiles are also included in
this zip package, where you can see placement of this code into these code files. It matches 5.x versions code. However, it will work in 4.x as well.
Important notes:
The code doesn't take into account subjects exempt from paying taxes (supplied Tax ID), but this can be done quite easily.
It also doesn't allow for flat fees (absolute tax value), but these are probably never used.
For future usage, some optimizations could be carried out.
1. Calculate tax in
CalculateShipping and
2. Store tax in Hashtable steps are in the
CalculateShipping method
(the code is in
CustomShippingOptionInfoProvider.cs from the custom ecommerce providers project.)
....
public double CalculateShipping(object cartObj, string siteName)
{
CMS.Ecommerce.ShoppingCartInfo cart = cartObj as CMS.Ecommerce.ShoppingCartInfo;
if (cart != null)
{
// Get shipping address details
CMS.Ecommerce.AddressInfo address = CMS.Ecommerce.
AddressInfoProvider.GetAddressInfo(cart.ShoppingCartShippingAddressID);
// Get shipping address country and state
CountryInfo country = CountryInfoProvider.GetCountryInfo(address.AddressCountryID);
StateInfo state = StateInfoProvider.GetStateInfo(address.AddressStateID);
// Add tax to standard shipping price for countries/states with specified "ShippingTax"
CMS.Ecommerce.TaxClassInfo shippingTaxClassInfo = TaxClassInfoProvider.GetTaxClassInfo("ShippingTax");
if (shippingTaxClassInfo != null)
{
// tax will be zero if no value found for state/country
double shippingTax = 0;
if (state != null)
{
CMS.Ecommerce.TaxClassStateInfo tcsi = CMS.Ecommerce.TaxClassStateInfoProvider.
GetTaxClassStateInfo(shippingTaxClassInfo.TaxClassID, state.StateID);
if (tcsi != null)
{
shippingTax = tcsi.TaxValue;
}
CMS.Ecommerce.TaxClassCountryInfo tcci = CMS.Ecommerce.TaxClassCountryInfoProvider.
GetTaxClassCountryInfo(country.CountryID, shippingTaxClassInfo.TaxClassID);
if (tcci != null)
{
shippingTax = tcci.TaxValue;
}
}
// Perform calculation of shipping charge for current shopping cart
double shippingWithoutTax = CMS.CMSEcommerce.ShippingOptionInfoProvider.CalculateShipping(cart, siteName);
// Calculate tax amount
double calculatedShippingTax = TaxClassInfoProvider.GetTaxValue(shippingWithoutTax, shippingTax, false);
// Store calculated tax amount into shop.cart custom data
cart.ShoppingCartCustomData["ShippingTax"] = calculatedShippingTax.ToString();
cart.UpdateShoppingCartCustomData();
// Return shipping charge including calculated tax
return shippingWithoutTax + calculatedShippingTax;
}
}
}
// Get standard shipping price in other cases
return CMS.CMSEcommerce.ShippingOptionInfoProvider.CalculateShipping(cart, siteName);
}
....
The next step - 3. Get tax into tax summary in
EvaluateShoppingCartContent (in
CustomShoppingCartInfoProvider.cs from the custom ecommerce providers project):
....
public void EvaluateShoppingCartContent(object shoppingCart, bool evaluateForInvoice)
{
//ShoppingCartInfoProvider.
//EvaluateShoppingCartContent((CMS.Ecommerce.ShoppingCartInfo)shoppingCart, evaluateForInvoice);
CMS.Ecommerce.ShoppingCartInfo cart = shoppingCart as CMS.Ecommerce.ShoppingCartInfo;
if (cart != null)
{
ShoppingCartInfoProvider.EvaluateShoppingCartContent(cart, evaluateForInvoice);
CMS.Ecommerce.TaxClassInfo tci = TaxClassInfoProvider.GetTaxClassInfo("ShippingTax");
if (cart.ShoppingCartCustomData["ShippingTax"] != null)
{
DataRow dr = cart.ShoppingCartTaxTable.NewRow();
dr["TaxClassID"] = tci.TaxClassID;
dr["TaxClassDisplayName"] = tci.TaxClassDisplayName;
// Get the added tax value from cart custom data hashtable
double taxValue = double.Parse(cart.ShoppingCartCustomData["ShippingTax"]);
// Add the shipping tax summary into the tax table
CMS.Ecommerce.ShoppingCartInfo.
AddTaxSummary(cart.ShoppingCartTaxTable, dr, taxValue);
}
}
}
...
Additional step:
add a call of the
ShoppingCartInfoProvider.EvaluateShoppingCartContent(ShoppingCartInfoObj) method before the "return true;" command within the "try" statement in the
ProcessStep() method in the
ShoppingCartPaymentShipping.ascx.cs file. (line approx. #170). It's located in
~\CMSModules\Ecommerce\Controls\ShoppingCart\ within the web project folder. It enforces the reloading of shopping cart content and loads the new value of the calculated tax.
Also add the following line in bold into the
~\CMSModules\Ecommerce\Controls\ShoppingCart\ShoppingCartPaymentShipping.ascx.cs file as shown below:
public override bool ProcessStep()
{
try
{
// Cleanup the ShoppingCart ViewState
this.ShoppingCartControl.SetTempValue(SHIPPING_OPTION_ID, null);
this.ShoppingCartControl.SetTempValue(PAYMENT_OPTION_ID, null);
ShoppingCartInfoObj.ShoppingCartShippingOptionID = ValidationHelper.GetInteger(drpShipping.SelectedValue, 0);
ShoppingCartInfoObj.ShoppingCartPaymentOptionID = ValidationHelper.GetInteger(drpPayment.SelectedValue, 0);
ShoppingCartInfoProvider.EvaluateShoppingCartContent(this.ShoppingCartInfoObj);
// Update changes in database only when on the live site
if (!ShoppingCartControl.IsInternalOrder)
{
ShoppingCartInfoProvider.SetShoppingCartInfo(ShoppingCartInfoObj);
}
return true;
}
catch (Exception ex)
{
lblError.Visible = true;
lblError.Text = ex.Message;
return false;
}
}
Finally, you will need to add the tax class in
CMSDesk -> Tools -> Ecommerce -> Configuration -> TaxClasses with codename "
ShippingTax" (it must be the same string as used in the code) and define values (in %) for the countries (states) where it should be applied.
-zc-
See also: Applies to: Kentico CMS 4.x, 5.x