I’ve had a love/hate/hate/hate relationship with Google Checkout and Magento for a long long time. Today marks a new low in our relationship. I’ve wasted so much time on this bug that I have made up a pie graph that illustrates the situation using Google’s charting API:
I’ve been on a journey to the bowels of the Magento Tax system and having spent the better part of 6 hours debugging through my issue I can safely say I will not do that again. The issue is that the totals are only collected once per address so depending on how many addresses you have and whether they are shippable or not, you get all sorts of weird results out of the shipping tax calculation. My issue was the calculated VAT amount on merchant calculated shipping in Google Checkout was wrong by a factor of tax % on shipping. So for £10 shipping in the UK, £1.75. Annoyingly it meant that Google would charge less than Magento recorded the order as being worth so now I have all sorts of mismatched order totals to deal with too. The issue could manifest itself as shipping tax being charged in Magento but not in Google Checkout too, if the tax was calculated on paid method, but the customer chooses a free method, for example.
I’ve reported the bug, so I really really hope it gets fixed soon – if someone else goes through what I just did, it would be a travesty.
Extra for Experts
Here’s the meat of my bug presented with code highlighting in case anyone cares or is battling with this error themselves and there’s no fix yet.
In app/code/core/Mage/GoogleCheckout/Model/Api/Xml/Callback.php
Magento sets up each GC address and then runs collectTotals()
on each. This is supposed to calculate the tax based on the $address->getShippingMethod();
if you look in Mage_Tax_Model_Sales_Total_Quote_Tax
, particularly the function _calculateShippingTax(Mage_Sales_Model_Quote_Address $address, $taxRateRequest)
you’ll see it relies on these being set:
$shippingAmount = $address->getShippingAmount(); $baseShippingAmount = $address->getBaseShippingAmount(); |
These will not be set if you have any addresses that do not have shipping methods available. For example checkout with a US, UK and German address saved in GC in a store that doesn’t ship to the US and you will see that during the calculation for a not-available country, the shipping method is set to empty by this code around line 663 of Mage_Sales_Model_Quote_Address
:
if (!$found) { $this->setShippingAmount(0) ->setBaseShippingAmount(0) ->setShippingMethod('') ->setShippingDescription(''); } |
From then on the shipping method and amount is never set back to the right amount, and never re-collected so the amounts used in the callback tax calculation on line line 238 of Mage_GoogleCheckout_Model_Api_Xml_Callback
will be wrong.
The fix it seems is to set the shipping method, and rate, then recollect right before we grab the shipping tax amounts in order to calculate the correct tax for the current rate. Take a look at this code which I have used around line 238:
$address->setShippingMethod($rateCodes[$methodName]); $address->setShippingAmount($rates[$methodName]); $address->setBaseShippingAmount($rates[$methodName]); $address->collectTotals(); |
It now correctly sets the current rate and method, then collects the totals to get the right amount of tax (including tax on shipping). I’m not sure if that’s the best *fix* from a Magento codebase point of view, but it gets the right tax numbers for me, and at this point, any love is good love.
Conclusion
For all my complaining, I realize that part of working with an open source ecommerce platform is that although you get to do whatever you like to it you also have to do it. So at least with Magento I can fix the issue instead of waiting for some tech support and if I want to, I can make other changes that suit our business too. So I’m not about to trade Magento for some off-the-shelf solution!
It’s fixed on the dev 1.4.x-devel-79607
* Fixed Google Chekout: Discount for shipping amount doesn’t apply
** onepage checkout recalculates shipping charges after setting the payment method (not solved yet in multishipping)
** added warning about Carrier Calculated Shipping in Google Checkout system configuration
** GC API callback now sets the payment method to quote on requests
😉
Hah! So many feelings…
Thanks for pointing it out, at least now I can check my fix is at least close to the core fix. I couldn’t find any mention of 1.4.x-devel-79607 or “Fixed Google Chekout: Discount for shipping amount doesn’t apply” on Google – where did you see that? I think my next train project should be to make it index-able by Google.
Here are the release notes for that version of Magento with the fix: http://svn.magentocommerce.com/source/branches/1.4-trunk/RELEASE_NOTES.txt
And download it like this: “svn checkout http://svn.magentocommerce.com/source/branches/1.4-trunk“
Thanks Jeff – I see the fix is the same as mine, except I had some possibly spurious setShippingAmount() calls. I’ll take some small comfort in that…
Man, I just love those graphs! Truly! So much so I almost want to steal them. 🙂
I agree with your conclusions. Magento CE, as open source, is not sufficiently supported by Magento or the so-called “community” where help is very intermittent but can occasionally be found. So I pretty much have to figure out most things for myself.
Because those graphs are so cool, I’m going to read as much of your blog as I possibly can.