odoo / odoo

Odoo. Open Source Apps To Grow Your Business.
https://www.odoo.com
Other
38.76k stars 25.11k forks source link

Product cost price computation badly rounded #74106

Open jbaudoux opened 3 years ago

jbaudoux commented 3 years ago

Impacted versions: 11.0, 12.0, 13.0, ...

The fix for the issue https://github.com/odoo/odoo/issues/30602 where the rounding is changed to use the currency rounding breaks the computation of the product cost. https://github.com/odoo/odoo/commit/eec0b80756557ecd543a50f25b8f63f94e23de7c

The product cost precision can be bigger than the currency precision. For instance 5 digits vs 2 digits. When a move is created at PO confirmation, the unit price is computed and stored on the move. In this case, round=False is given in the context to prevent any rounding.

This was managed by compute_all on account.tax as mentioned in the comment:

# In some cases, it is necessary to force/prevent the rounding of the tax and the total
# amounts. For example, in SO/PO line, we don't want to round the price unit at the
# precision of the currency.
# The context key 'round' allows to force the standard behavior.

However, this feature has been removed and replaced by a currency rounding in the above mentioned commit. For product having a small price and always purchased by big quantities, a bigger precision for the product cost price is mandatory.

Related: https://github.com/odoo/odoo/pull/40847 https://github.com/odoo/odoo/pull/44280 https://github.com/odoo/odoo/pull/44288 https://github.com/odoo/odoo/pull/44312

cc @smetl @qdp-odoo

Failed use case: Change product precision to 5 digits. Have company currency in EUR. USD-EUR currency rate = 1.071582 Make a PO in USD for a product with a unit price of 0.09031. The move unit price is wrongly computed as 0.08427726482901 (0.09 / 1.071582) instead of 0.09031 / 1.071582 = 0.083987972922278

smetl commented 3 years ago

@jbaudoux unit_price = 0.09031, quantity = 1, currency rate = 1.071582

price_subtotal is computed as ROUND(0.09031 * 1) = 0.09 accounting balance is computed as ROUND(0.09 / 1.071582) = 0.08

This is correct if the quantity is 1...

jbaudoux commented 3 years ago

@smetl The issue is not with the amounts on the PO. The issue is with the valuation of the product.

I forgot to mention that the PO line needs a tax (excl) to face the issue. If you do not provide a tax on the PO line, then the costing is correctly computed. 2021-07-27_13-23

So, on the PO, all is fine. If you purchase 1 PCE, price_subtotal is 0.09. If you purchase 100, price_subtotal is 9.031. In both cases, the product/move valuation is computed for a quantity of 1 in the currency of the company. If you have a tax on the PO line, the move unit price is wrongly computed as 0.08427726482901 (0.09 / 1.071582) instead of 0.09031 / 1.071582 = 0.083987972922278

jbaudoux commented 1 year ago

@smetl @jco-odoo @qdp-odoo My dears. This bug is still there in odoo (i.e. in master). The product cost computation is wrong when the product cost precision is bigger than the currency precision. Since Jan 2020. Any chance you fix this :)

jco-odoo commented 1 year ago

@jbaudoux So we would just need a round totally False in the compute_all? I can not find back the compute_all computation in master immediately...

jbaudoux commented 1 year ago

@jco-odoo It is here in master https://github.com/odoo/odoo/blob/master/addons/account/models/account_tax.py#L493 Issue has been introduced by removing the check on round in this commit https://github.com/odoo/odoo/commit/eec0b80756557ecd543a50f25b8f63f94e23de7c while it is still relying on it here https://github.com/odoo/odoo/blob/master/addons/purchase_stock/models/stock_move.py#L65

smetl commented 1 year ago

@jbaudoux We are going to improve the taxes computation in 17.0 (it's not yet merged) and, from my understanding, it will fix such issue. I can keep you up to date. However, for stable versions, it's too risky to change anything about the way the taxes are computed.