woocommerce / woocommerce

A customizable, open-source ecommerce platform built on WordPress. Build any commerce solution you can imagine.
https://woocommerce.com
9.42k stars 10.77k forks source link

0.01 inconsistencies between price and subtotal #27026

Closed kingplugins closed 3 years ago

kingplugins commented 4 years ago

Prerequisites (mark completed items with an [x]):

The issue has been discussed: https://wordpress.org/support/topic/rpoblem-rounding-taxes-woocommerce/ https://wordpress.org/support/topic/wrong-round-in-cart-and-checkout/ But as far as I can see, no solution has been offered.

Describe the bug The issue is: subtotals differ from price by 0.01 sometimes, because of rounding. See screenshot: https://prnt.sc/tgpfca You can get into the technical reasons for this, but put very simply, of course this is a bug. From the user's point of view, you are displaying a price of 3.65 per item, but for 2 items you are charging them 7.31 . This creates accounting issues, about displaying a price per item and billing a different price per multiple items.

Related issues: You could use a workaround (which is not a fix) of changing price display settings. However, there are situations when this is not possible. If I have both B2C users, and B2B users that I exempt from tax programatically (via WC()->customer->set_is_vat_exempt(true) ), one of these groups will always see prices off by 0.01 under various circumstances.

Possible solution?: I think the problem is: WooCommerce calculates subtotals based on prices entered, but this is incorrect. It should calculate based on prices displayed per item (rounded based on decimals setting), as that is the final price given to the buyer. The buyer does not see or care about the prices entered in the backend.

Expected behavior I would expect that if 1 item costs 3.65, 2 items cost 7.30.

Actual behavior 2 items actually cost 7.31

Steps to reproduce the bug (We need to be able to reproduce the bug in order to fix it.) Steps to reproduce the bug:

  1. Set prices entered to "excluding tax" but price displayed to "including tax". Set tax rate to 16%
  2. Create a product with price 3.15
  3. Add 2 items to cart
  4. See error: https://prnt.sc/tgpfca

This issue happens when prices are entered including tax but displayed excluding tax ,or the other way around. Prices are calculated at 4 decimals (I think?), but in most situations, based on shop settings, they are displayed at 2 decimals.

Isolating the problem (mark completed items with an [x]):

WordPress Environment We use the WooCommerce System Status Report to help us evaluate the issue. Without this report we won't be able to fully evaluate this issue.

` ### WordPress Environment ### WordPress address (URL): http://localhost:10093 Site address (URL): http://localhost:10093 WC Version: 4.3.0 REST API Version: ✔ 1.0.10 WC Blocks Version: ✔ 2.7.1 Action Scheduler Version: ✔ 3.1.6 WC Admin Version: ✔ 1.3.0 Log Directory Writable: ✔ WP Version: 5.4.2 WP Multisite: – WP Memory Limit: 256 MB WP Debug Mode: – WP Cron: ✔ Language: en_US External object cache: – ### Server Environment ### Server Info: nginx/1.16.0 PHP Version: 7.3.5 PHP Post Max Size: 1,000 MB PHP Time Limit: 1200 PHP Max Input Vars: 4000 cURL Version: 7.64.0 OpenSSL/1.1.1b SUHOSIN Installed: – MySQL Version: 8.0.16 Max Upload Size: 300 MB Default Timezone is UTC: ✔ fsockopen/cURL: ✔ SoapClient: ✔ DOMDocument: ✔ GZip: ✔ Multibyte String: ✔ Remote Post: ✔ Remote Get: ✔ ### Database ### WC Database Version: 4.3.0 WC Database Prefix: wp_ Total Database Size: 4.27MB Database Data Size: 2.87MB Database Index Size: 1.40MB wp_woocommerce_sessions: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_api_keys: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_attribute_taxonomies: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_downloadable_product_permissions: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_woocommerce_order_items: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_order_itemmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_tax_rates: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_woocommerce_tax_rate_locations: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_shipping_zones: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_woocommerce_shipping_zone_locations: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_shipping_zone_methods: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_woocommerce_payment_tokens: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_payment_tokenmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_log: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_actions: Data: 0.02MB + Index: 0.11MB + Engine InnoDB wp_actionscheduler_claims: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_groups: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_logs: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_commentmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_comments: Data: 0.02MB + Index: 0.08MB + Engine InnoDB wp_links: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_options: Data: 2.03MB + Index: 0.06MB + Engine InnoDB wp_postmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_posts: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_term_relationships: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_term_taxonomy: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_termmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_terms: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_usermeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_users: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wc_admin_note_actions: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wc_admin_notes: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_category_lookup: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_customer_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_download_log: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_order_coupon_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_order_product_lookup: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_wc_order_stats: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wc_order_tax_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_product_meta_lookup: Data: 0.02MB + Index: 0.09MB + Engine InnoDB wp_wc_reserved_stock: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_tax_rate_classes: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wc_webhooks: Data: 0.02MB + Index: 0.02MB + Engine InnoDB ### Post Type Counts ### attachment: 1 b2bking_custom_field: 9 b2bking_custom_role: 2 b2bking_rule: 4 page: 6 post: 2 product: 2 ### Security ### Secure connection (HTTPS): ❌ Your store is not using HTTPS. Learn more about HTTPS and SSL Certificates. Hide errors from visitors: ✔ ### Active Plugins (1) ### WooCommerce: by Automattic – 4.3.0 ### Inactive Plugins (1) ### B2BKing: by WebWizards – 1.8.5 ### Settings ### API Enabled: – Force SSL: – Currency: EUR (€) Currency Position: left Thousand Separator: . Decimal Separator: , Number of Decimals: 2 Taxonomies: Product Types: external (external) grouped (grouped) simple (simple) variable (variable) Taxonomies: Product Visibility: exclude-from-catalog (exclude-from-catalog) exclude-from-search (exclude-from-search) featured (featured) outofstock (outofstock) rated-1 (rated-1) rated-2 (rated-2) rated-3 (rated-3) rated-4 (rated-4) rated-5 (rated-5) Connected to WooCommerce.com: – ### WC Pages ### Shop base: #19 - /shop/ Cart: #20 - /cart/ Checkout: #21 - /checkout/ My account: #22 - /my-account/ Terms and conditions: ❌ Page not set ### Theme ### Name: Storefront Version: 2.5.8 Author URL: https://woocommerce.com/ Child Theme: ❌ – If you are modifying WooCommerce on a parent theme that you did not build personally we recommend using a child theme. See: How to create a child theme WooCommerce Support: ✔ ### Templates ### Overrides: – ### Action Scheduler ### Complete: 8 Oldest: 2020-07-10 12:49:11 +0000 Newest: 2020-07-13 04:27:06 +0000 Pending: 2 Oldest: 2020-07-13 07:33:27 +0000 Newest: 2020-07-13 13:34:05 +0000 `
juliaamosova commented 4 years ago

Hi @stefanstatescu1,

Thank you for taking the time to report this bug, we really appreciate your help. I can reproduce it on my end following the steps you provided:

tax_issue

We’re going to look into solving this bug as soon as possible. 

kingplugins commented 4 years ago

Thanks @juliaamosova . If you have time to take a look at issue #27012 as well, at least just to confirm it on your end, I'd appreciate it.

typeofweb commented 4 years ago

I also have the same problem, but the other way round 🙃 I enter prices tax exclusive and display them tax inclusive. My product net price is 85.70, tax is 5% so the gross price is 89.99. Now, when user adds, for instance, six products to the cart, the total is miscalculated as 539.91 instead of 539.94. This error occurs because the quantity is multiplied by the net price and then tax is added: total net price = 6 85.70 = 514.20 total gross price = 514.20 1.05 = 539.91

What I believe should be happening instead is that tax should be applied per item and then multiplied by the quantity: total net price = 6 85.70 = 514.20 total gross price = 6 89.99 = 539.94

Correct me if I'm wrong.

GeoJunkie commented 4 years ago

Encountered in 12342636-hc

Image Link: https://d.pr/i/0EkQxw

I checked and confirmed that this was caused by a rounding error in the taxes:

Image Link: https://d.pr/i/AJOAU5

tobias992 commented 4 years ago

Over one Month and no Fix - nice job Dev-Team!!!

This is a critical bug for EVERY WooCommerce Shop - please fix ASAP

typeofweb commented 4 years ago

@tobias992 you could fix it yourself and create a Pull Request. This is how Open Source works :)

tobias992 commented 4 years ago
  1. I am not a Developer and
  2. I pay so much Money to WooCommerce for premium extensions.... thats not my job to fix this. Thats the job from WooCommerce Team to fix this ASAP.
wzpsolutions commented 4 years ago

We became aware of the problem through a new customer and have created a support ticket at https://wordpress.org/support/topic/urgent-wrong-calculation-of-tax/. The customer is using version 3.7.0. An update to the latest version did not change anything. The problem certainly affects all WooCommerce installations worldwide. We hope you fix this really soon. Thanks!

GlueDigiStu commented 4 years ago

I've recently had the same issue with a store I'm working on, I managed to temporarily resolve by forcing the wc_get_rounding_precision() function to return 2 by editing the core code, but obviously this is not a fix - I was just exploring solutions. Is there a reason why we're not allowed to set a rounding precision of 2 decimal places and it has to be at least 2dp beyond what the currency is set to?

tobias992 commented 4 years ago

HELLO DEV-TEAM!!!!!

vedanshujain commented 4 years ago

Apologies, this will take longer than expected, perhaps in November release. We are looking to address this and other rounding issues as well (and possibly do an overhaul if needed). We are already discussing approaches internally, and have figured out some low effort fixes we can do, but please expect it to take more time as its still ongoing research and discussion.

bartekmiturafrontkom commented 3 years ago

Hello @vedanshujain @juliaamosova

An update on the status will be greatly appreciated - I think it's safe to say that thousands of people are experiencing this bug and it affects the critical functionality, big time - including me and the client with whom I work.

Looking forward to hearing from you.

bartekmiturafrontkom commented 3 years ago

Hello @vedanshujain @juliaamosova - any news?

vedanshujain commented 3 years ago

@bartekmiturafrontkom It's being actively worked upon, but I don't have any expected fix date yet.

ad-on-is commented 3 years ago

I'm having a similar issue 1 item costs 1.01

Expected behavior: 8 items costing 8.08

Actual behavior: 8 items cost 8.07

vedanshujain commented 3 years ago

So I did took a look at this over this and last week, and unfortunately it does not looks like we can support rounding at unit level as requested in the original comment anytime soon. This is mostly because its not compatible with few other features that WooCommerce support out of the box without adding whole bunch of settings.

As already stated in the above comments, maths behind the scenes are correct and they do follow upon whether rounding per line or subtotal is selected. It only appear that there is a rounding problem because rounded unit level price may not add up to rounded subtotal price.

Coming back to unit level rounding, it does not look like it can be supported yet because:

  1. WooCommerce allows functionality such as multiple tax rates (cumulative and additive), product level coupons, fractional quantities (via external plugins), etc which are incompatible with allowing unit level rounding. For example, with multiple tax rates, its messy to figure out whether they should be rounded after combining or before. There does not seem be a standard way, and allowing for customization there means lots more settings and controls, which you can argue that there is already a lot of.

  2. Rounding at the unit level seems to be rarely used and supported. Many WooCommerce shops (and some payment gateways) also use separate accounting software to consolidate tax reports that may not support unit rounding. Allowing it could mean a discrepancy in totals computed by those software and by WooCommerce. It seems unreasonable to add support for unit level rounding just because of this issue.

  3. There are workarounds in settings with how prices are displayed to prevent these inconsistencies being displayed to the user (mentioned below):

Recommended settings

All this said, this does not mean that there is no way of showing correct prices everytime. Basically, if I set the settings to display the prices as they are entered, I was not able to reproduce any of the rounding issue mentioned here (and in some other issues as well).

This means that when prices are including taxes, we should be displaying them in cart and checkout including as well:

Screenshot 2020-12-03 at 7 10 04 PM

Prices including tax means that for customers who are not in the tax zone (or are in a tax zone with different tax rates), the gross amount (price including tax) will always be the same. The net (price excluding tax) will be adjusted based on the tax rates applicable to make sure that the gross rate is same for everyone (except customers manually exempted from tax using set_is_vat_exempt method).

Incase prices are entered exclusive of taxes, then looks like we should be displaying them without taxes in cart and checkout as well. This mode also displayed all taxes as a separate tax total, so taxes are displayed, just not included in the price. I would also recommend this mode to be used when you have many customers who are manually exempted from using set_is_vat_exempt method.

Screenshot 2020-12-03 at 1 22 45 PM

I am also writing a support article including all these settings and reasoning behind not supporting unit level rounding as suggested in this comment for now.

I also checked out other similar eCommerce systems, and they seem to work around the problem by restricting how prices will be displayed, i.e. prices will strictly be displayed based on how they are entered without any setting to configure it, or in case where there was an option, I was able to reproduce this error.

I also looked into another algorithm, which a popular spreadsheet program uses to make sure that all percentages in pie chart or bar chart etc sums up to 100. Unfortunately, that causes the displayed taxes or totals to go incorrect, and then external tallying system would also show a mismatch.

For now, I am marking this issue as won't fix, since rounding discrepancy does not look reason enough to support and maintain a complex setting like unit rounding, when workaround exists that will prevent this rounding discrepancy for most.

All this said, as always, its entirely possible that I might be missing something, in which case I am curious to hear what y'all think and if there are indeed approaches that we can take. Or perhaps we can make smaller improvements somewhere to further help with these discrepancies? Lets continue the discussion here if some has more/better approaches in mind.

vedanshujain commented 3 years ago

I am closing this issue since there has not been any feedback. But feel free to comment if there any questions/suggestions/improvements that we can do but I have missed.

rigaleb commented 2 years ago

Hello! @GlueDigiStu How exactly did you use that function, can you show me an example snippet? Thank you!

lixicus commented 2 years ago

August 2022 and still no fix for this.

nalognl commented 2 years ago

You closed as not important but in tax menu beside option Round on total leve mentioned that this setting is EU is not allowed, we should use rounding on per line level.

kingplugins commented 1 year ago

@vedanshujain

I believe there are still significant issues, even with the recommended settings below:

Screenshot 2023-05-08 at 16 19 18

Example (1):

We configure a tax rate of 24%, a product that costs $100.28, and a flat rate shipping method that costs 10.48

Screenshot 2023-05-08 at 16 37 01

The tax should be 110.76*24% = 26.5824 = 26.58

Results are 26.59 (incorrect):

Screenshot 2023-05-08 at 16 38 54

I think it may be because each line's tax is calculated and rounded separately, which obviously is not correct. This creates problems for accounting.

Example (2)

We configure a tax rate of 24%, a product that costs $10 and a flat rate shipping method that costs 10.4789:

Screenshot 2023-05-08 at 16 21 04

Tax should be 20.48*24% = 4.9152 = 4.92

Results are incorrect (4.91):

Screenshot 2023-05-08 at 16 22 07

If we change the shipping cost from 10.4789 to 10.48, the results of the same calculation are now different (4.92):

Screenshot 2023-05-08 at 17 07 04

So the exact same frontend calculation has different results depending on internal settings. Not good.

Example (3)

Simplest example, without any shipping.

Tax rate = 24%, Product price = 100.4789

Screenshot 2023-05-08 at 17 16 48

Results are incorrect: 24.11 instead of 24.12:

Screenshot 2023-05-08 at 17 17 35

Similarly, if you change the price of the product to 100.48, instead of 100.4789, the problem is fixed:

Screenshot 2023-05-08 at 17 19 32

(again, we have different results for the same calculation, based on invisible internal numbers)

All of this is quite a disaster. WooCommerce now displays the "Inconsistent Tax Settings" warning message in the backend as a response to this issue when incl/excl tax settings are chosen. But it does not address the fundamental problem in my opinion: totals and taxes should be calculated based on displayed numbers, not based on internal numbers.

You cannot say "1+1 = 3", because internally it is actually 1.51 and 1.49.

Totals should be calculated in 2 steps:

(1) Calculate the displayed numbers (2) Calculate tax and totals based on the displayed numbers, not the internal numbers

Doing this would fix this mess and also allow choosing mixed incl/excl tax settings without needing the "inconsistent tax settings" warning.