In most countries there is one man you don’t want to stuff around – the Taxman. Unfortunately Magento has had a long string of issues around taxation. Admittedly it is not easy to write a system that works with all ideas every Taxman has ever come up with around the world. So my first advice is to not trust the numbers or if you have to, really stress test those numbers.
Once an order is placed, Magento saves a tax “summary” of the order and the tax amounts and percentages on the order items – that’s all. Some pitfalls I have
discovered fell into:
“summary” is incomplete
The tax summary only contains the tax amounts and the tax percentages. Since you don’t know if the tax amount was rounded and if so which way you can’t work backwards to get the amount the tax was charged on. You also can’t use this info to verify if Magento made a mistake or not. Collecting the tax amounts yourself by looping over the order items did the trick for me.
Shipping Tax Rate / Shipping Tax Percentage
If you are tasked to display the tax rate for the shipping costs after the order has been placed either a) run for the hills or b) quote high. The problem is that this information is simply not saved. The only information available once the order is placed is the shipping amount and shipping tax amount. Again trying to work backwards with the amounts you will be off by a few cents depending on how the amount was (in/correctly) rounded in the first place. Trying to look up the settings in your current settings has the downside that his information might have changed over time. The best solution I could come up with so far was to sum up all tax amounts of the order items and then compare this to the tax summary. Let me know if you know a better a way.
Item Tax Rates
Magento saves the tax percentage with each order item. In most scenarios this is sufficient to work out what tax rate applies. However in some scenarios you might be using multiple tax rates with the same percentage but you need to keep them separate (for example selling into Netherlands and Germany – both have a sales tax of 19%). This can only be solved retrospectively if you had no setting changes on your system. The way to do is to reload the initial quote that got converted to the order:
$quote = Mage::getModel('sales/quote')->load($order->getQuoteId());
and then reconstruct the tax calculation process (subject for a different post). Going forward you could create a new order item column and save the rate information when the order is being converted.
Looking at the numbers they don’t make sense any way you look at them. I hear you say but what about the hidden_tax_amount, Kristof. Of course the hidden tax amount! and it all makes sense now – well at least you can work out how the row total is made up RowTotal = Subtotal – Discount Amount – Hidden Tax Amount; My understanding of the hidden_tax_amount is that it is the amount of tax that would have been applied on the discount. (on a sidenote – in previous versions this information was stored slightly differently in tax_before_discount)
If you look closely all items have the same tax inclusive price. However one row is discounted and taxed differently to the others. This is some tax-foo introduced by the setting System > Calculation > Tax > Tax Calculation Based On > Total.
More hidden taxes or wysiNwyg
One other example I have come across only showed itself on the db level. A particular order had a shipping tax amount but no shipping amount.
In general if you have a spare moment I suggest to have a look at the inner workings of Magento at the db level. The table sales_flat_order_item is full of info what Magento does behind the back and saves for each item.
What to do
While your mileage may vary I suggest creating a set of sample orders which you test for each Magento version you deploy. A lot of rounding errors only show when using cents. In my view a good test order includes:
- Multiple items with various cent amounts (ie. $9.75, $4.99)
- Items with high quantities
The more test orders you have the more confident you’ll be that you have covered all the corner cases. One further item to verify is that what your customer sees in the basket matches up with what ends up being the final order. You may also want to invest some initial time into setting up some form of automation for this (for example Selenium for Firefox)
In general I’ve had more predictable outcomes with using tax exclusive amounts in the back-end and using the tax calculation method row total. What has your experience been so far?
And lastly: petition Magento to finally include unit and functional tests in their development process.
Originally published on magebase.com. Copyright © 2010 Magebase - All Rights Reserved.