I'm trying to get 'tax_calculation_rate_id' by iterating through ordered products.

The following code works ok, but the problem arises when there are multiple ids assigned to the same percentage values (e.g. "VAT exempt rate" at 0% and "EC Sales rate" at 0%)

Is there a better way to get the rate ids calculated?

Thank you for your help!

// $line_item and $address come as arguments 

$store = Mage::app()->getStore();
$product_class= Mage::getModel('catalog/product')
$tax_model = Mage::getSingleton('tax/calculation');
$request = $tax_model->getRateRequest($address, null, null, $store);
$percent = $tax_model->getRate($request->setProductClassId($product_class));

$rates = Mage::getModel("tax/calculation_rate")
                         ->addFieldToFilter('rate', array('eq'=>$percent));
foreach ($rates as $rate)
    $mage_rate_id = $rate->getTaxCalculationRateId();
    // if more than 1 rate exits it obviously picks the last one

I guess, you will need to get the dedicated tax rates not only by percentage but also by code. I would say you can to call $tax_model->getAppliedRates($request->setProductClassId($product_class)) instead of $tax_model->getRate($request->setProductClassId($product_class)). With that call you will get an array with all rates - but as far as I see the tax_calculation_rate_id is not in this array (for what ever reason). Therfore you will need to get the rates with an additional call to $tax_model->getRates($ruleId).

I suppose the code for that would look like this - but I haven't tested it:

$tax_model = Mage::getSingleton('tax/calculation');
$request = $tax_model->getRateRequest($address, null, null, $store);
$appliedRates = $tax_model->getAppliedRates($request->setProductClassId($product_class));

foreach ($appliedRates as $appliedRate){
    foreach ($appliedRate['rates'] as $oneRate){
        //returns an array of all applied rate ids
        $rates = $tax_model->getRates($oneRate['rule_id']);

Anyway, I quess alternatively you can get all the data you need by using the following 3 tables: sales_order_tax_item, sales_order_tax and tax_calculation_rate. Each order item has entries for each applied tax rate in sales_order_tax_item, therefore you just need to consider the corresponding rows in that table. This should work, if you have unique codes for your tax rates.

//assuming your parameter $line_item is an order item you can load the entries 
//for that order item from sales_order_tax_item table
$taxItemCollection = Mage::getModel('tax/sales_order_tax_item')
                    ->addFieldToFilter('item_id', array('eq'=>$line_item->getId()));

//iterate through the collection items and load the corresponding sales_order_tax entry
//and based on that the corresponding tax_calculation_rate entry
foreach ($taxItemCollection as $taxItem) {
    $tax = Mage::getModel('tax/sales_order_tax')->load($taxItem->getTaxId());
    $rate = Mage::getModel("tax/calculation_rate")-loadByCode($tax->getCode());
    $mage_rate_id = $rate->getTaxCalculationRateId();
  • Thank you for your reply. They both work but only if the tax rate is more than 0. – Mike Mar 30 '19 at 0:38
  • I might need to implement an if statement and add an algorithm to handle 0% cases. Any suggestions? – Mike Mar 30 '19 at 0:45
  • 1
    That's strange. The first approach $tax_model->getAppliedRates() just joins the tables tax_calculation, tax_calculation_rule, tax_calculation_rate and gets the corresponding data whitout taking care of the percentage of the rate. I would suggest to dump the array $appliedRates and see what's inside. If you don't see the data there, check the generated SQL in Mage_Tax_Model_Resource_Calculation::getCalculationProcess() – HelgeB Mar 30 '19 at 7:56
  • You are right. $appliedRates is empty if there's no relevant tax rule set up. Thank you every so much! – Mike Mar 31 '19 at 1:32
  • 1
    From the stores I worked with I don't know any case with more than one rate for a product but I would not exclude that there are such situations depending on tax laws in other countries. But be aware you get the rule id not the rate id in $appliedRates and therefore you will have to call getRates based on the rule id. – HelgeB Mar 31 '19 at 8:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.