Cause analysis
The order price of Magento is calculated by executing the set pricing model under the global/sales/quote/totals node configured in config in sequence, the execution sequence is controlled by the after and before nodes of each model. For example, we can see the following code in the native app/code/core/Mage/Tax/etc/config. xml configuration file:
<Global>
...
<Sales>
<Quote>
<Totals>
<Tax_subtotal>
<Class> tax/sales_total_quote_subtotal </class>
<After> freeshipping </after>
<Before> tax, discount </before>
</Tax_subtotal>
<Tax_shipping>
<Class> tax/sales_total_quote_shipping </class>
<After> shipping, tax_subtotal </after>
<Before> tax, discount </before>
</Tax_shipping>
<Tax>
<Class> tax/sales_total_quote_tax </class>
<After> subtotal, shipping </after>
<Before> grand_total </before>
<Renderer> tax/checkout_tax </renderer>
<Admin_renderer> adminhtml/sales_order_create_totals_tax </admin_renderer>
</Tax>
<Subtotal>
<Renderer> tax/checkout_subtotal </renderer>
<Admin_renderer> adminhtml/sales_order_create_totals_subtotal </admin_renderer>
</Subtotal>
<Shipping>
<Renderer> tax/checkout_shipping </renderer>
<Admin_renderer> adminhtml/sales_order_create_totals_shipping </admin_renderer>
</Shipping>
<Discount>
<Renderer> tax/checkout_discount </renderer>
<Admin_renderer> adminhtml/sales_order_create_totals_discount </admin_renderer>
</Discount>
<Grand_total>
<Renderer> tax/checkout_grandtotal </renderer>
<Admin_renderer> adminhtml/sales_order_create_totals_grandtotal </admin_renderer>
</Grand_total>
</Totals>
...
</Quote>
</Sales>
...
</Global>
We can note that the before node of the tax model specifies grand_total, which means that the tax model should be executed before the grand_total model. The results of program execution are not deceptive, so the problem arises. What is the reason for the problems mentioned in the beginning?
Let's take a look at several important steps in the computer system of the total order price. It mainly involves the following methods:
Total shopping cart price calculation:
Mage_Sales_Model_Quote: collectTotals
Calculate the total price of each address in the shopping cart respectively (the address-by-address calculation is used to realize the multi-address shipping function, different addresses can correspond to different prices), and then sum:
Mage_Sales_Model_Quote_Address: collectTotals
When calculating the total price of each address, you first configure all models under the global/sales/quote/totals node by searching config:
Mage_Sales_Model_Quote_Address: getTotalCollector
Mage_Sales_Model_Quote_Address_Total_Collector: getCollectors
Then execute the collect method of each model to calculate the relevant price, and use the parent class Mage_Sales_Model_Quote_Address_Total_Abstract (all valuation models inherit from this class) the _ addAmount and _ addBaseAmount methods of overlay the price to the total price.
When Mage_Sales_Model_Quote_Address: getTotalCollector is executed, the constructor of the Mage_Sales_Model_Quote_Address_Total_Collector class is executed. The ordering of each billing module is conducted here, using this method:
Mage_Sales_Model_Config_Ordered: _ getSortedCollectorCodes
The incorrect order of pricing also exists here. The key lies in the following behavior array sorting program, which does not sort all pricing models in the specified order:
Uasort ($ configArray, array ($ this, '_ compareTotals '));
Solution
The solution is relatively simple. You can create a custom component to override the Mage_Sales_Model_Quote_Address_Total_Collector class (the class actually used to sort the billing model, inherited from the _ getSortedCollectorCodes method of Mage_Sales_Model_Config_Ordered, on the basis of the original method, execute the sorting code mentioned above one or more times.