News:

Support the VirtueMart project and become a member

Main Menu

Canadian taxes on shipping : another rounding issue

Started by Khaostar, October 05, 2016, 17:26:58 PM

Previous topic - Next topic

Khaostar

Hi all,

Just read some topics on rounding problems, taxes, shipping etc and unfortunatly I can't find a solution to my problem.
This seems to be a popular subject and there is a lot of differences between countries, law, etc.
On my side, i'm at Quebec, Canada and I can't get the taxes to be rounded correctly

Here is my problem, in short.

my taxes are the taxes from Quebec, Canada.
Tax 1 (GST) : 5.00%
Tax 2 (TVQ) : 9.975%

now, here is an example of my cart with an error.

Product price : 55,90$
shipping price :13,50$

subtotal : 69,40$

Tax 1 : 3,48$
Tax 2 : 6,93$

Total : 79,80$

as you can see, there is multiple error here.
The real values should be :

Tax 1 : 3,47$
Tax 2 : 6,92$

Total : 79,79$

So there is a error of one penny on each taxes and also an error of one penny on the total price.

The problem is not always there. It depend on the price of the products in the cart and the shipping. Sometimes everything is perfect, sometimes there is an error on one taxe, but not in the total... etc. 

I really don't know how i'm supposed to deal with it. If someone could help me, that would be really appriciated.

Thanks!

Joomla 3.6.2
Virtuemart 3.0.16


GJC Web Design

isn't the vm admin -> prices  -> round only display setting?
GJC Web Design
VirtueMart and Joomla Developers - php developers https://www.gjcwebdesign.com
VM4 AusPost Shipping Plugin - e-go Shipping Plugin - VM4 Postcode Shipping Plugin - Radius Shipping Plugin - VM4 NZ Post Shipping Plugin - AusPost Estimator
Samport Payment Plugin - EcomMerchant Payment Plugin - ccBill payment Plugin
VM2 Product Lock Extension - VM2 Preconfig Adresses Extension - TaxCloud USA Taxes Plugin - Virtuemart  Product Review Component
https://extensions.joomla.org/profile/profile/details/67210
Contact for any VirtueMart or Joomla development & customisation

Khaostar


Khaostar

Anything else I can try?
This problem bothers me a lot!

Thanks

Khaostar

Finally, I managed to found the problem. It seems to be a bug directly in the core.

That's simple. Almost every calculations that need to be rounded use the "roundInternal" function. BUT, there is one place where the standard "round" php function is used and that's what is causing the problem.

In calculationh.php, arrond line 975.

Replace this :

$this->_cart->cartData['VatTax'][$rule['virtuemart_calc_id']]['result'] += round($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'];

by this :

$this->_cart->cartData['VatTax'][$rule['virtuemart_calc_id']]['result'] += $this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'];

And arround line 1070, replace this :

$discount += round($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'],$this->_currencyDisplay->_priceConfig['salesPrice'][1]);

By this :

$discount += $this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'];


This fix the rounding problem. I guess that another solution would be to replace the "round" function by the "roundInternal" function, but I haven't tried

So, if a Virtuemart developper could see this and fix it in the next version of virtuemart. That would be very appreciated.

Thanks!

Milbo

Sounds very valid. I will replace it with the roundInternal. Lets see how it works then.
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

Khaostar


Khaostar

Well, after some tests, I have another rounding issue. The problem seems to be really simple, but I can't manage to fix it.

Here wo go.

My taxes, using the same config as before :
Tax 1 (GST) : 5.00%
Tax 2 (TVQ) : 9.975%

Here is an example of what I get actually :
Product price : 13,50$
Tax 1 price : 0,68$
Tax 2 price : 1,35$
Total price : 15,52$

As you can see here, the total should be 15,53, not 15,52.

It seems that the taxes are diplayed rounded, but the total is calculted with the non rouded taxes.

Actually, this is what is happening

13,50*0,05 = 0,675 (tax 1 non rounded amount, displayed as 0,68 in the cart)
13,50*0.09975 = 1,346625 (tax 2 non rounded amount, displayed as 1,35 in the cart)
13,50+0,675+1,346625=15.521625.
So the rounded total is 15,52$

What I need is this :

13,50*0,05 = 0,68 (rounded)
13,50*0.09975 = 1,35 (rounded)
13,50+0,68+1,35=15.53$

So I need the taxes to be rounded when they are added together and added to the final price. I tried to uncheck the "round only display" in the config, but it doesn't change anything.

Am I missing something? Or is it something that can't be done actually? I'm not sure what to do with that.

Thanks!



Milbo

Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

Khaostar

Sadly, it seems the file you sent us still produces some 1 cent differences.

Also, we had a "problem" that the calculation was "too precise" if we compared it to the rounded up display.

Exemple:
subtotal: 13.50
tax 1(5%): 0.675(display:0.68)
tax 2(9,975%): 1.346625(display:1.35)
total: 15.52

So, the calculation is good, but the display makes it look like its not.

Because of that, I returned to the original file and continued modifying it, now trying to make the result with the displayed values.

So, here is what I did:

$this->_cart->cartData['VatTax'][$rule['virtuemart_calc_id']]['result'] += round($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'],$this->_currencyDisplay->_priceConfig['salesPrice'][1]);
is now
$this->_cart->cartData['VatTax'][$rule['virtuemart_calc_id']]['result'] += $this->roundInternal($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'], "taxAmount");

$this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'] = $this->roundInternal($this->roundInternal($cOut) - $cIn);
is now
$this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'] = $this->roundInternal($this->roundInternal($cOut) - $cIn, "taxAmount");

$discount += round($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'],$this->_currencyDisplay->_priceConfig['salesPrice'][1]);
is now
$discount += $this->roundInternal($this->_cart->cartPrices[$rule['virtuemart_calc_id'] . 'Diff'], "taxAmount");

$tmp = $this->roundInternal($this->roundInternal($cOut) - $cIn);
is now
$tmp = $this->roundInternal($this->roundInternal($cOut) - $cIn, "taxAmount");

Basically, I just linked the rounding of taxes/calc_rules to something I could have a fair control from the admin panel.
To be fair, it may be because I do not quite know how $this->_internalDigits works but in the rounInternal function, it seems that if you don't have a "name" it rounds with the number of digits equal to this variable and it's seems always equal to 9 aka not really rounding(?)

As I said, I may be misunderstanding something.

In any way, this code is what I concluded to and it seems to work for me. What do you thing about it? I would truly like your opinion of those modifications.

Thank you!
Have a good day!




Milbo

Rounding is a complex issue and the main problem is that rounding is physics, not maths. When you round, you leave the exact math and you enter the natural space. the next problem is that a computer has problems to create an exact 2.0000.... You end up with 2.0000001 or so. Therefore we need the internal rounding.

When you use the internal rounding with "taxAmount" which is usually set to 2, then you just round to 2 numbers (the opposite of "round only display")

All what you did is to reduce the precision and that may work in your example, but is more wrong for other examples. The reason is that some mathematical basic rules do not work anylonger, when you round the numbers.

(a*c + b*c ) IS NOT [round(a) + round(b)] * round(c) !!!  Check the chapter "Distributivity and rounding" https://en.wikipedia.org/wiki/Distributive_property
Should I fix your bug, please support the VirtueMart project and become a member
______________________________________
Extensions approved by the core team: http://extensions.virtuemart.net/

Khaostar

It is true that the precision will be off by my last solution.

But, I didn't find a way to have both the precision of the calculation and the accuracy of the displayed calculation. My solution is far from perfect and I'd prefer being able to have precision and a good display.

If you have any idea of how to do so, I'm all ears.

encreplus

Im also from quebec could you share your solution ??

Also where you abble to put the taxes for shipping directly in TPS and TVQ or you use the standard option from VM ie ... total taxes for shipping beside shipping label on order page and invoice ?


Khaostar

Unfortunately, we haven't a 100% working solution for now. We are still having some bad calculations.

Otherwise, we have spotted the problem. ( I think )

Here in Quebec, Canada, we are calculating the taxes on the subtotal only. In VirtueMart, the taxes are calculated for the products, then for the shipping, and also for the payment method, if needed. After that, all the taxes are added together. That's where the problem is. That way, that's almost impossible to have the same result as the taxes on the subtotal only.

A really good option that should be added is to be able to calculate the taxes on the subtotal directly. That would fix every problem for the Canadian taxes. Of course, doing that we will have some problems with different taxes on different products or things like that, but we don't care here in Quebec as almost everything is taxed the same way, except for some products that are not taxable.

In my case, everything is taxable.
In the case of someone who would have some non-taxable products, it's not very complicated either: a taxable subtotal and a non-taxable subtotal. The taxes should be calculated on the taxable subtotal only and that's it.

Milbo, do you think this is something possible? We should have an option to calculate the taxes based on the subtotal and ignore every other tax calculation. I'm sure it will be useful for many other users.

Mathematically, it's simple, but I know it's probably much more complicated to integrate that in VirtueMart. Let me know if you can do something or if I can do something to help, too.

Oh and by the way, Happy new Year! :)
Thanks!


diri

#14
Hi and happy new year to all :)

@Khaostar:
You will ever have rounding issues when you calculate with single prices, sum them up and recalculate. Onliest chance I see is to multiply prices with a factor moving rounding issues at the very end of a large number and divide it afterwards. Those issues can get "lost" or minimized after division of this large number to get real amount back.

Let's asume you have a tax of 5.00% (factor 0.05). You need a precission of two decimals for display, three digits in calculation.

Now, instead of multiplying with 0.05 you could try to multiply the price with 1,000.00 first. Than multiply price with 500.00 (tax factor 0.05 multiplied with 10,000.00). Than divide result two times: 1,000.00 and 10,000.00. Have a look what happens.

Ex for 5%:
Price: 13.50
13.50 x 1,000.00 = 13,500.00
tax factor = 0.05 -> 500.00
tax amount:
13,500.00 * 500 = 6,750,000.00
1st division (/ 1,000.00) = 6,750.000whatever
2nd division (/ 10,000.00) = 0.675whatever

Didn't try it now with VM but, maybe you can introduce a rule working this way for your taxes (might need another name and some overrides for naming while tax for VM = 0.00000%).