The shop I am dealing with had a product which is sold at EUR 5,80 (gross). German VAT on wine is 19%. Therefore, the exact net price would be EUR 4,87394958. By default, OpenCart only allows to specify the product net price with a precision of 4 decimals which would be EUR 4,8739 in this case. It's quite obvious that this will lead to issues if customers put large quantities (e.g. 100 or 1000 items of this product) into their shopping cart. Neither the subtotal nor the tax nor the total would be correctly calculated.
Hence, I did some research in the OpenCart code (based on version 3.0.3.8 that I use). To my understanding, the actual problem has more than one root cause, I think:
- The field "price" in table "oc_product" has too few decimal places (set to "decimal(15,4)").
- The controller (catalog/controller/checkout/cart.php) reduces the precision of the value for "unit_price" by rounding it to two decimal places and then setting "price" based on $this-currency->format($unit_price, ...) and "total" using $this->currency->format($unit_price * product['quantity']), ...) which produce incorrect results as the precision of "unit_price" has already been reduced by rounding it before.
- Increase the precision of the "price" field in table "oc_product" to at least "decimal(15,8)".
- Avoid reducing precision of "unit_price", "price" and "total" in catalog/controller/checkout/cart.php. Instead keep the values with their default precision and store additional array fields (e.g. "$data['products']['formattedPrice']", "$data['products']['formattedTotal']", "$data['formattedTotals']['title']" and "$data['formattedTotals']['text']") to pass properly rounded and formatted values to the template (catalog/view/theme/default/template/checkout/cart.twig).