Programmatically Creating and Editing Magento Tax Rules/Rates

Published by John on March 3, 2017 Under Magento

Magento LogoWhile working on a Magento Site, I found myself needing to programmatically create tax rules, rates, and then later edit them. After a little trial and error, I was able to successfully create the tax rule, using the ‘tax/calculation_rule’ model.

However, whenever I added or removed a tax rate and then saved the existing tax rule, it would clear out all the settings for the tax rule. So, anytime I called the ->save() function on the tax rule, instead of modifying the rule, it had the effect of apparently deleting all settings. And, upon viewing the tax rule in the Magento admin section, the only thing that remained was the rule name, with everything else, like the Customer Tax Class, Product Tax Class, and Tax Rate being blanked out and no longer selected.

While I haven’t digged deep enough to figure out why this is happening, I did observe some differences between what ‘getData()’ returns on a newly created tax rule and what it returns on an existing tax rule loaded via ID. Basically, the fields that are represented as array’s during creation, like Customer Tax Class and Tax Rate, return as single variables after the rule is loaded.

For me, the fix(which is described in more detail below) was to re-initiate all the fields during edit in the same way I did when creating the rule prior to saving. Again, I’ve not really dug into what is going on, so this may not be the correct way to do things, but it does allow for editing an existing Magento Tax Rule via PHP.

Table of Contents

Programmatically Creating a Tax Rate

The below describes how to create a tax rate Programmatically for the state of North Carolina(NC). You can modify it as needed to create a rate:


/* Helper Function for Getting a Region ID from a state code(NC) */

function get_region_id_from_state($state){

		$region_data = Mage::getModel('directory/region')->loadByCode($state, 'US');
		
		if(!$region_data  || $region_data->getId() <= 0){
			return false;
		}
		
		return $region_data->getId();

}

function create_tax_rate($rate_name, $state=false, $zipcode=false, $tax_percent){
                
		if(empty($rate_name) || $tax_percent <= 0 || (empty($state) && empty($zipcode))){
			return false;
		}
		
		if(!empty($state)){
			$region_id = get_region_id_from_state($state);
		
			if(empty($region_id)){
			    return false;
			}
		} else{
			$region_id = 0;
		}
		
		$tax_rate = Mage::getModel('tax/calculation_rate');
		
		$tax_rate->setCode($rate_name);
		$tax_rate->setTaxCountryId('US');
		
		if(!empty($zipcode)){
			$tax_rate->setTaxRegionId($region_id);
			$tax_rate->setTaxPostcode($zipcode);
		} else{
			$tax_rate->setTaxRegionId($region_id);
			$tax_rate->setTaxPostcode('*');
		}
		$tax_rate->setRate($tax_percent);
		$tax_rate->setZipIsRange(0);
		$tax_rate->save();
		
		return $tax_rate;

}

Programmatically Creating a Tax Rate

In order to create a tax rule, you need to know the numeric ID of at least one tax rate, along with the numeric ID of a product tax class and customer tax class. You can find these a few ways, for the purpose of this example, we are creating a rule for an existing product tax class. The example would be similar when doing a customer tax class.

Note that on your install, you will at minimum need to verify the $default_customer_tax_class and $default_product_tax_class variables are correct.


function get_tax_rate_by_name($tax_rate_name){

		$tax_rate = $search_results = Mage::getModel('tax/calculation_rate')->load($tax_rate_name, 'code');
		return $tax_rate;
}

function get_tax_rule_by_name($tax_rule_name){

		$tax_rule = Mage::getModel('tax/calculation_rule')->load($tax_rule_name, 'code');
		return $tax_rule;
}

function get_tax_class_by_name($tax_class_name){
		
		$tax_class = Mage::getModel('tax/class')->load($tax_class_name, 'class_name');
		return $tax_class;		
	}

function create_tax_rule($rule_name, $rate_id){

		//The customer tax class for a retail customer is 3 for my magento install. You may need to verify this by logging into the backend. 		
		$default_customer_tax_class = 3;

		//The product tax class name. You will need to setup/add a tax class(or use one of the defaults.)backend. 		
		$default_product_tax_class = 'my_custom_tax_class_name';

		if(!is_array($rate_id)){
			$rate_id = intval($rate_id);
		}
		
		if(empty($rule_name) || (!is_array($rate_id) && $rate_id <= 0)){
			return false;
		}
		
		$existing_rule = get_tax_rule_by_name($rule_name);
		
		if($existing_rule && $existing_rule->getId() > 0){
			echo 'A rule with this name already exists';
			return false;
		}
		
		$tax_class = get_tax_class_by_name($default_product_tax_class);
		
		if(!$tax_class && $tax_class->getId() <= 0){
			echo 'This tax class is invalid';
			return false;
		}
		
		$new_rule = Mage::getModel('tax/calculation_rule');
		
		$new_rule->setCode($rule_name);
		$new_rule->setTaxCustomerClass(array($default_customer_tax_class));
		$new_rule->setTaxProductClass(array($tax_class->getId()));
		
		if(is_array($rate_id)){
			$new_rule->setTaxRate($rate_id);
		}else{
			$new_rule->setTaxRate(array($rate_id));
		}
				
		$new_rule->setPriority(0);
		$new_rule->setPosition(0);
		$new_rule->save();
		
		return $new_rule;
		
		
	}

Programmatically Editing Tax Rate

Here is where I ran into issues initially and noticed the difference between both getData and GetTaxRate between a newly created rule and one loaded via the load function. Specifically, when retrieving the rates, you need to use getRates to get an array of tax rates and the other variables, like getTaxCustomerClass were not returning arrays, but were instead returning strings.

The fix ended up being doing the edit in the same manner as the creation. See below:

		$default_product_tax_class = 'my_custom_tax_class_name';
		$default_customer_tax_class = 3;
		$tax_rate = get_tax_rate_by_name('my_new_tax_rate');

		if($tax_rate && $tax_rate->getId() > 0){
			echo 'Error getting tax rate.';
			return false;
		}  

		$tax_class = get_tax_class_by_name($default_product_tax_class);
		
		if(!$tax_class && $tax_class->getId() <= 0){
			echo 'This tax class is invalid';
			return false;
		}                      

		$tax_rule = get_tax_rule_by_name($tax_rule_name);

		if($tax_rule && $tax_rule->getId() > 0){
			echo 'Error getting tax rule.';
			return false;
		}  

		$tax_rates = $tax_rule->getRates();
		$tax_rates[] = $tax_rate->getId();
		$tax_rule->setTaxCustomerClass(array($default_customer_tax_class));
		$tax_rule->setTaxProductClass(array($tax_class->getId());
		$tax_rule->setTaxRate($tax_rates);
						
		$tax_rule->setPriority(0);
		$tax_rule->setPosition(0);
		$tax_rule->save();

No Comments |

Add a Comment