Using EPiServer.Commerce 10.2.3:
We started the migration to the new order APIs and we are trying to register our ITaxCalculator implementation. The challenge is we use a third party provider for calculating taxes and the way current implementation is for calculating cart totals results in performance decrease and service charges increase. (As the tax provider charges per call)
Every time the cart is saved, the GetTotals function is being called resulting in calling tax calculation four times at least (If you have only one order form in your order group).
This is a partial snap shot of the default function implementation:
Money subTotal = this._orderGroupCalculator.GetSubTotal(orderGroup);
Money total = this._orderGroupCalculator.GetTotal(orderGroup);
Money shippingTotal = this._shippingCalculator.GetShippingCost(orderGroup, market, currency);
Money taxTotal = this._taxCalculator.GetTaxTotal(orderGroup, market, currency);
Money handlingTotal = this._orderGroupCalculator.GetHandlingTotal(orderGroup);
The GetTotal and GetTaxTotal will result in callind the tax provider twice; and then there is a for loop on order forms that does exact same thing as above snap shot but for order forms. (Now, the provider has been called four times)
We want to calculate taxes only in the checkout page and not every time I add item to my cart. Any suggestions?
My second question, how can we achieve a single call to the tax provider in the GetTotals function so we save the charges and increase the performance?
Last one, out of curiosity, why there is a call to GetTotal instead of populating the total variable with subtotal + shippingTotal + taxTotal + handlingTotal? The implementation of GetTotal is already the sum of all these fields.
Thanks guys for any help!
In addition to above, we are showing tax charges in a report for placed orders.
I cannot find a property in IPurchaseOrder to get calculated taxes. I have to call GetTaxTotal which recalculates taxes after order has been placed.
Is there a way to get the taxes that was calculated during placing the order instead of recalculating it?
Your help is highly appreciated!
Your TaxCalculator is really a challenge for me, I digged into this but didn't find a perfect solution. However, I have an idea and you could improve it.
We known that IOrderGroup, IOrderForm, IShipment inherits from IExtendedProperties, so we could store your tax data to those properties.
IOrderGroup.Properties["TaxValue"] = <CalculatedTaxAmount>;
IOrderForm.Properties["TaxValue"] = <CalculatedTaxAmountForForm>;
IShipment.Properties["TaxValue"] = <CalculatedTaxAmountForShipment>;
And as you did - customize DefaultOrderGroupTotalsCalculator (IOrderGroupTotalsCalculator): was defined in this document http://world.episerver.com/documentation/developer-guides/commerce/orders/calculating-orders/ , you could check Properties["TaxValue"] was exist and has value before calculate it.
I didn't have sample code for this solution, just a suggestion.
I think you have a good point but it kills the purpose of being able to customize the tax calculator. So now we will have to, in addition to build our own tax calculator, be responsible for calling it from all the required places.
Specially the way tax calculator is called multiple times, (With every save) will overcharge the client if they are using a third party calulator like Avalara.
Thank you for your information and I think you're in good position to customize your own tax calculator.
After tax value was calculator, you could store it to Property, so that you don't need to call re-calculate everytime but whenever it's needed.
For example, with a lineitem was added, tax for this lineitem was calculated and store to ILineItem.Properties["TaxValue"]
ILineItem.Properties["TaxValue"] = CustomizedTaxCalculator.GetTax(item);
This is first time calling tax caculator and we won't call it anymore:
if (ILineItem.Properties["TaxValue"] == null || decimal.Parse(ILineItem.Properties["TaxValue"]) ==0)
// Calculate tax and store it.
When calculate IOrderForm, we could get order form tax from those LineItem
IOrderForm.Properties["TaxValue"] = IOrderForm.GetAllLineItems().Sum(lineItem => lineItem.Properties["TaxValue"]) + IOrderForm.Shipments.Sum(shipment => shipment.Properties["TaxValue"])
The same with calculating with IOrderGroup...
When I have a free time, I'd like to dig into this topic one or several more times :)