From a95cb2eb2d39913440a7f29f445187f2d5ad5a80 Mon Sep 17 00:00:00 2001 From: Yolann Sabaux Date: Thu, 9 Jun 2022 11:28:00 +0000 Subject: [PATCH] [FIX] stock_account: fix rounding error Steps to reproduce: - Define the decimal accuracy for the "Product Price" to 5 - Create a product with "cost = 0.00875" - On-hand product = 10'000 - Change the cost to "0.00975" Issue: In Inventory valuation, for the product you will have two layers valued at: - 87.5 - 12.5 Instead of: - 87.5 - 10 Cause: We round with currency precision Solution: Use the "Product Price" decimal precision as it is the case when we define a "standard_price" https://github.com/odoo/odoo/blob/4c7ef5673b8fc28bf7fe2bc36fe2450987f15a28/addons/product/models/product.py#L110-L112 opw-2724975 closes odoo/odoo#93257 X-original-commit: deb26bb1182682a5071287ae313064801d080607 Signed-off-by: William Henrotin (whe) Signed-off-by: Yolann Sabaux (yosa) --- addons/stock_account/models/product.py | 5 +-- .../test_stock_valuation_layer_revaluation.py | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index e853d20e549..75cf6a79964 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import float_is_zero, float_repr, float_compare +from odoo.tools import float_is_zero, float_repr, float_round, float_compare from odoo.exceptions import ValidationError from collections import defaultdict @@ -227,7 +227,8 @@ class ProductProduct(models.Model): quantity_svl = product.sudo().quantity_svl if float_compare(quantity_svl, 0.0, precision_rounding=product.uom_id.rounding) <= 0: continue - rounded_new_price = company_id.currency_id.round(new_price) + digits = self.env['decimal.precision'].precision_get('Product Price') + rounded_new_price = float_round(new_price, precision_digits=digits) diff = rounded_new_price - product.standard_price value = company_id.currency_id.round(quantity_svl * diff) if company_id.currency_id.is_zero(value): diff --git a/addons/stock_account/tests/test_stock_valuation_layer_revaluation.py b/addons/stock_account/tests/test_stock_valuation_layer_revaluation.py index f53e7f08fbf..7ae51f263db 100644 --- a/addons/stock_account/tests/test_stock_valuation_layer_revaluation.py +++ b/addons/stock_account/tests/test_stock_valuation_layer_revaluation.py @@ -158,6 +158,38 @@ class TestStockValuationLayerRevaluation(TestStockValuationCommon): self.assertEqual(layers[0].value, 200) self.assertEqual(layers[1].value, 300) + def test_stock_valuation_layer_revaluation_avco_rounding_5_digits(self): + """ + Check that the rounding of the new price (cost) is equivalent to the rounding of the standard price (cost) + The check is done indirectly via the layers valuations. + If correct => rounding method is correct too + """ + self.product1.categ_id.property_cost_method = 'average' + + self.env['decimal.precision'].search([ + ('name', '=', 'Product Price'), + ]).digits = 5 + + # First Move + self.product1.write({'standard_price': 0.00875}) + self._make_in_move(self.product1, 10000) + + self.assertEqual(self.product1.standard_price, 0.00875) + self.assertEqual(self.product1.quantity_svl, 10000) + + layer = self.product1.stock_valuation_layer_ids + self.assertEqual(layer.value, 87.5) + + # Second Move + self.product1.write({'standard_price': 0.00975}) + + self.assertEqual(self.product1.standard_price, 0.00975) + self.assertEqual(self.product1.quantity_svl, 10000) + + layers = self.product1.stock_valuation_layer_ids + self.assertEqual(layers[0].value, 87.5) + self.assertEqual(layers[1].value, 10) + def test_stock_valuation_layer_revaluation_fifo(self): self.product1.categ_id.property_cost_method = 'fifo' context = {