Lightroom 3 is out »

How to Configure Local Taxes in VirtueMart?

Have you ever wonder how to configure local taxes in Virtuemart? Well, you can not (at least not in version 1.1.5). You have to alter the core code in Virtuemart in order to do that.

What do I mean by "local taxes"? When you become an online merchant in the United States, you also become a part-time tax collector for your "home state". The home state is the state in which your online business is based. You help your state collect sales tax and you send this collected tax back to your state once a quarter (every three months). Consult your tax advisor on this.

So if a customer orders a product and it is shipped to an address in your home state, then you charge tax on that product. If it is shipped elsewhere other than your home state, then generally you do not have to charge tax.

You have to call your state tax board and ask them what their rules are. Although the rules may vary from state to state in the United States, we will be using Nevada as the home state in this example (because I had called their tax call center). But many other states are similar.

Okay, so we are supposed to charge tax when a product is shipped into Nevada, our home state. But what tax rate do we charge? Nevada has many different local tax rates depending on what county you are in. See their nice chart here. So depending on the county that the shipping address falls in, you are supposed to charge that particular sales tax for that county.

If the item is being shipped to Humboldt county, you charge 6.850%. If the item is being shipped to Pershing county, you charge 7.1%.

The problem is we do not know the county in which the item is being shipped to. When the customer fills in the shipping address, he/she types in the city only. They do not type in a county.

So now you have to map each and every city of Nevada to their county to figure out what tax to charge for each city. There are about a couple hundred cities in Nevada -- and it is not considered a large state either. Fortunately, they gave us a list (scroll down on the pdf) of all the cities in Nevada and what county it falls in.

Okay, so we now know what tax to charge based what Nevada city the customer had typed in for their shipping address.

VirtueMart Setup

Now we start setting this up in VirtueMart.

1. In "Administrator -> Components -> VirtueMart -> Admin -> Configuration -> Global" checkmark "Virtue Tax" and select Tax Mode based on shipping address.

virtuemart tax setup

2. Set up one tax rate for NV (Nevada) in "Tax -> Add Tax Rate" ...

virtuemart set tax rate

I just put in 6.85% as 0.06850. That percentage is the state's base rate. The correct rate will be higher for certain ship destination cities. And we now write code that will override this base rate based on the city that was entered in the shipping address.

3. Now in each of your products, make sure you set "VAT Id" to the a percentage value and not leave it 0. Otherwise the below code will not work.

VirtueMart Code if Using VAT

Disclaimer: Use this code at your own risk as I will not be liable. Just because it worked for me does not mean that it will work for you. You need to test thoroughly. This code was written for Virtuemart 1.1.5 and Joomla 1.5.22. So if your version is not that, then it may not work. This code is only for shipping-address based taxation, not store-based taxation.

4. The tax rate is retrieved in the vm_ps_product class in the file...
/administrator/com_virtuemart/classes/ps_product.php

I added a public variable array called $localTaxArray where the key is the city and the value is the tax rate in decimal...

tax array in virtuemart

Note also that I have made all the city name in lowercase. (You see why later)

5. In the get_taxrate function of the vm_ps_product class, adjust the two SQL statements to retrieve the city in addition to the state and country...

6. I inserted the following code ...

Because all the city in the $localTaxArray is in lower case, we convert the $city to lowercase so that we don't have to worry about capital letters and mis-capitalizations. $city is the city that the customer typed into the shipping address.

Using array_key_exists, if the city is found in the array key, then we found the city. They value is the tax rate for that city. We assign that tax rate to session variable used by VirtueMart ...

$_SESSION['taxrate'][$ps_vendor_id]

In the event that an exact match is not found, it may be due to situations where the city name is "Palamino Valley", but the customer type in "Palamino". That is why when constructing the $localTaxArray, use the shorter form of the city in the array. So use "palamino" as the array key.

The foreach loop will search through every element of the array. If the array key is a substring of $city (what the customer typed in), then we call it a match and perform the assignment of the rate to the session variable.

So for example, if array key is "palamino", the foreach loop will match if the customer types in "Palomino", "Palomino City", or "Palomino Valley".

In that event, that the customer mis-types the city in such a way that even the foreach loop does not get a match, then (if the state is NV) the base tax as set in the VirtueMart tax rule (in step 2) will be used.

VirtueMart Code if NOT Using VAT

7. For merchants in the United States that do not use VAT. Set each of their products with "VAT Id" set to 0.

If you do that. Then instead of steps 4 thur 6 above, you do the following steps instead.

8. Add the $localTaxArray to the vm_ps_checkout class in file ...
administrator/components/com_virtuemart/classes/ps_checkout.php

9. Find this piece of code in the calc_order_tax function of the ps_checkout.php file...

10. And re-write it to the equivalent code as shown here ...

11. Insert the following code that will look up the local tax and over-ride the retrieved tax rate.

12. We still need to alter the SQL query to retrieve the city into the $city variable...

13. Comment out the following line, since our code is already calculating the $tax_rate...