I'm trying to achieve the following scenario, and am not sure how to configure the store's tax classes, as anyone tried to achieve the following:
I've tried to create 2 separate tax classes:
However how do I ensure International is not applied to country Y? It does not appear to allow you to remove a country from the list.
Working with complex tax logic in Kentico is going to require some custom development (at least in v7 and I believe v8 hasn't changed much as far as tax calculation goes). If you will watch this webinar, there's a section that talks about custom TaxClassInfoProviders. It also includes some code samples that you can download to get you started.
Here's one approach to modifying the tax calculation process. It's based on one of the sample files from the webinar linked above:
public class CustomTaxClassInfoProvider : TaxClassInfoProvider
{
#region Properties
private ShoppingCartInfo Cart
{
get
{
return ECommerceContext.CurrentShoppingCart;
}
}
private string CustomerZipCode
{
get
{
AddressInfo customerAddress = AddressInfoProvider.GetAddressInfo(Cart.ShoppingCartShippingAddressID);
if(customerAddress != null)
return customerAddress.AddressZip;
return null;
}
}
#endregion
/// <summary>
/// Returns DataSet with all the taxes which should be applied to the shopping cart items.
/// </summary>
/// <param name="cart">Shopping cart</param>
protected override DataSet GetTaxesInternal(ShoppingCartInfo cart)
{
DataSet taxDataSet = new DataSet();
// Create an empty taxes table
DataTable table = GetNewTaxesTable();
List<TaxRow> taxRows = new List<TaxRow>();
foreach (ShoppingCartItemInfo item in cart.CartItems)
{
TaxRow row = new TaxRow();
row.SKUID = item.SKU.SKUID;
row.SKUGUID = item.SKU.SKUGUID;
taxRows.Add(row);
}
foreach (TaxRow row in taxRows)
{
double rate = 0;
string name = "";
// Add conditions for different tax rates here
// --------------------------------------------
// For Example
if (cart.Customer.CustomerCountryID == countryYouWantToExclude)
{
rate = yourTaxRate;
name = "Name for the tax";
}
else
{
rate = 0;
name = "";
}
row.TaxRate = rate;
row.TaxName = name;
}
BuildTaxTable(ref table, taxRows);
// Return our dataset with the taxes
taxDataSet.Tables.Add(table);
return taxDataSet;
}
private void BuildTaxTable(ref DataTable table, List<TaxRow> taxRows)
{
foreach (TaxRow row in taxRows)
{
AddTaxRow(table, row.SKUID, row.TaxName, row.TaxRate);
}
}
private DataTable GetNewTaxesTable()
{
DataTable table = new DataTable();
// Add required columns
table.Columns.Add("SKUID", typeof(int));
table.Columns.Add("TaxClassDisplayName", typeof(string));
table.Columns.Add("TaxValue", typeof(double));
return table;
}
private void AddTaxRow(DataTable taxTable, int skuId, string taxName, double taxValue, bool taxIsFlat, bool taxIsGlobal, bool zeroTaxIfIDSupplied)
{
DataRow row = taxTable.NewRow();
// Set required columns
row["SKUID"] = skuId;
row["TaxClassDisplayName"] = taxName;
row["TaxValue"] = taxValue;
// Set optional columns
//row["TaxIsFlat"] = taxIsFlat;
//row["TaxIsGlobal"] = taxIsGlobal;
//row["TaxClassZeroIfIDSupplied"] = taxIsGlobal;
taxTable.Rows.Add(row);
}
private void AddTaxRow(DataTable taxTable, int skuId, string taxName, double taxValue)
{
AddTaxRow(taxTable, skuId, taxName, taxValue, false, false, false);
}
}
/// <summary>
/// Represents a DataRow to be inserted into the tax calculation data table
/// </summary>
public class TaxRow
{
public int SKUID { get; set; }
public Guid SKUGUID { get; set; }
public string TaxName { get; set; }
public double TaxRate { get; set; }
public TaxRow()
{
}
}
Then you'll need to setup your CMSModuleLoader class, which is also one of the sample files from the link above:
/// <summary>
/// Sample e-commerce module class. Partial class ensures correct registration.
/// </summary>
[SampleECommerceModuleLoader]
public partial class CMSModuleLoader
{
#region "Macro methods loader attribute"
/// <summary>
/// Module registration
/// </summary>
private class SampleECommerceModuleLoaderAttribute : CMSLoaderAttribute
{
/// <summary>
/// Constructor
/// </summary>
public SampleECommerceModuleLoaderAttribute()
{
// Require E-commerce module to load properly
RequiredModules = new string[] { ModuleEntry.ECOMMERCE };
}
/// <summary>
/// Initializes the module
/// </summary>
public override void Init()
{
TaxClassInfoProvider.ProviderObject = new CustomTaxClassInfoProvider();
}
}
#endregion
}
Add these files anywhere in AppCode and you should be good to go. Let me know if you have any questions.