1
votes

I have a problem with rounding of tax class amounts in WooCommerce 3.2.3 on Wordpress 4.8.3.

The sums of each of the 2 tax classes are both correctly displayed with 2 decimal points when displayed in the cart and checkout page.
However, during calculation of the cart total sum, the tax class sums are added together in the tax subtotal sum using 4 decimal point values and then rounded up.
This can cause a 0,01 rounding error, as explained in the example below, where if you add the item subtotal together with the displayed tax class sums, you get 221,61 €, and not the displayed 221,62 €.


Example (prices without tax, no shipping involved):
Product XXX (belong to 19% tax class): 161,28 €
Product YYY (belong to 7% tax class): 27,75 €
Product items subtotal = 189,03 €

MwSt. 19% 30,64 €
MwSt. 7% 1,94 €

Cart sum total: 221,62 €


The question:
How can I force WooCommerce to use 2 decimal points for the tax class sums when adding them together for calculating the cart total sum?


Setup:

  • we use the plugin "woocommerce germanized" version 1.9.5. Problem exist with and without it enabled.
  • we use a shipping calculator plugin, and the problem exist with and without it.
  • disabled all plugins to no effect.
  • tested with twentyseventeen theme, with same result.
  • the shop is in Germany, and sells to companies and to private customers, hence the prices are entered without tax.
  • products are associated with either the 19% or 7% tax class.
  • currency is EUR using 2 decimals.
  • "display tax totals" setting is set to "itemized".
  • prices are entered without tax.
  • prices are shown without tax.

I understand the reasoning behind using 4dp precision in the calculations, but it is not needed in our use case.

I added some debug output in the WC code, and saw that the individual tax class sums in the above example are stored with 4 decimals:
MwSt. 19% 30,6432
MwSt. 7% 1,9425

The tax subtotal here is 32,5857 which is rounded up to 32,59 € during cart sum total calculation, as opposed to 32,58 €, causing the 0,01 difference.

In my search for a solution to this issue, I found a lot of different tax calculation issues, but no exactly similar use case.

I have attempted to modify the WooCommerce code, but I have been unsuccessful in finding the right spot in WooCommerce where I can set / hard code the precision-calculation to use 2dp rather than 4dp, but that might not have been the most ideal solution anyway.

Note: If I change the "display tax total" setting to "Total" instead of "Itemized", then the displayed tax subtotal is 32,59 €.

In this setup the total cart sum 221,62 € equals the sum of the listed subtotals, but the customer requires the taxes to be shown itemized.

Sorry for the long description. In my recent experience, it appears to be necessary in order to properly explain tax calculation related issues.

Does anyone have a suggestion to resolve this issue?

Many thanks for your advice and time!

Muskat

1

1 Answers

3
votes

First you have to search how the tax are calculated in Woocommerce… If you go in WooCommerce WC_Cart class code, you will see that WC_Tax class is responsible for this…

In the source code WC_Tax the methods that make calculations are (with the corresponding available filter hooks to alter that calculations):

  • calc_tax() with available filter hook woocommerce_calc_tax.
  • calc_shipping_tax() with available filter hook woocommerce_calc_shipping_tax.
  • round() with available filter hook woocommerce_tax_round.
  • calc_inclusive_tax() with available filter hook woocommerce_price_inc_tax_amount.
  • calc_exclusive_tax() with available filter hook woocommerce_price_ex_tax_amount.
  • and may be some others…

Here is an example to change the round() behavior to return rounding to .5 cents:

add_filter( 'woocommerce_tax_round', 'euro_5cent_rounding' );
function euro_5cent_rounding( $in ) {
    return round( $in / 5, 2 ) * 5;
}

Code goes in function.php file of your active child theme or active theme (or also in any plugin file).

As your problem is very specific and difficult to reproduce, you will have to find which hook is going to make the trick to solve your issue…