Magento – How to update the grand total amount manually

magento-1.7onepage-checkout

I'm in the last step of Magento's default one page checkout. There I check whether taxes are applied or not due to the VAT rules within the EU for B2B customers. It was a battle till that point but now I'm feeling that I have entered the dragon's lair. The last big step is to update the grant total amount but I don't see any way to do that in a more or less easy way.

For the quote of Mage::getSingleton('checkout/session')->getQuote() I was expecting some kind of setters but it seems to me that there are no one.

Creating a whole new order quote seems to be possible but is a lot of overhead and looks quite fault-prone to me.

So another idea was to remove the items of a quote and put in custom (duplicated) items with prices without tax. But before trying this out I would like to ask you if there's a smoother way to update the grant total amount. Thank you in advance!

Best Answer

I have found that the best way to manipulate how Magento calculates taxes is to just let Magento do what it wants to do.

As a developer, your tendency might be to think "hey, I have this quote, now I need to access some kind of setTaxAmount() method". This might ultimately be backwards thinking.

Magento's collectTotals() method does a lot of stuff each time an order/quote is accessed, so simply setting a tax amount on a quote is not going to be the best route.

In your case, I assume that your customer models include information about taxability... ie, you might have a customer group that has to pay taxes and another group that is tax exempt. If you manipulate the associated admin config values so that users in the tax exempt group aren't charged tax, you would be halfway home. Then during checkout at the desired step, assign the user to the proper customer group, and then when collectTotals() fires, the existing logic for taxable customer groups will work out whether the customer should be charged tax or not.


To think of a specific example of my own, I am working on a module that will call a third-party tax service, pass it a validated address to determine local tax rates, a list of cart items, and the service returns how much tax the order should have.

While initially working on this, I thought similar to you... I should call this service, get the tax amount, and then I will simply set this tax amount on the quote.

This was problematic.

Ultimately what I decided to do was to fire my own observer method that gets called before collectTotals(), and then rely on all the built-in logic to handle various tax situations. When a user submit's their shipping address during checkout, I will then use that address and their cart items to call the tax service and return me a tax amount. Based on this value, I then calculate what their tax rate is (ie. 3.7%) since the service only returns a tax amount and not a tax rate.

Once I have a tax rate that I want to use, I then programmatically create a new tax zone and rate in Magento based on the user's postal code (Zip+4 in my case).

Again, since this happens before collectTotals() I am able add new tax zones and rates on the fly based on a user's information. As collectTotals() gets called, it has no idea what I've done, all it knows is that this user's postal code matches a tax zone, so it should apply the proper tax rate to their quote.