diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index c9ae09db69a..4021e1d701f 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -272,6 +272,7 @@ class StockMove(models.Model): qty_to_take_on_candidates = quantity or valued_quantity candidates = move.product_id._get_fifo_candidates_in_move_with_company(move.company_id.id) new_standard_price = 0 + tmp_qty = 0 tmp_value = 0 # to accumulate the value taken on the candidates for candidate in candidates: new_standard_price = candidate.price_unit @@ -292,6 +293,7 @@ class StockMove(models.Model): candidate.write(candidate_vals) qty_to_take_on_candidates -= qty_taken_on_candidate + tmp_qty += qty_taken_on_candidate tmp_value += value_taken_on_candidate if qty_to_take_on_candidates == 0: break @@ -305,9 +307,18 @@ class StockMove(models.Model): # negative stock use case. We chose to value the out move at the price of the # last out and a correction entry will be made once `_fifo_vacuum` is called. if qty_to_take_on_candidates == 0: + # If the move is not valued yet we compute the price_unit based on the value taken on + # the candidates. + # If the move has already been valued, it means that we editing the qty_done on the + # move. In this case, the price_unit computation should take into account the quantity + # already valued and the new quantity taken. + if not move.value: + price_unit = -tmp_value / (move.product_qty or quantity) + else: + price_unit = (-(tmp_value) + move.value) / (tmp_qty + move.product_qty) move.write({ 'value': -tmp_value if not quantity else move.value or -tmp_value, # outgoing move are valued negatively - 'price_unit': -tmp_value / (move.product_qty or quantity), + 'price_unit': price_unit, }) elif qty_to_take_on_candidates > 0: last_fifo_price = new_standard_price or move.product_id.standard_price diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index d7097fe10d7..829b975b662 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -2152,6 +2152,7 @@ class TestStockValuation(TransactionCase): # stock values for move3 self.assertEqual(move3.value, -80.0) + self.assertAlmostEqual(move3.price_unit, -10.0) self.assertEqual(move3.remaining_qty, 0.0) self.assertEqual(move3.remaining_value, 0.0) @@ -2183,6 +2184,7 @@ class TestStockValuation(TransactionCase): # old value: -80 -(8@10) # new value: -148 => -(10@10 + 4@12) self.assertEqual(move3.value, -148) + self.assertAlmostEqual(move3.price_unit, -148.0/14.0) # older move self.assertEqual(move1.remaining_value, 0) # before, 20 @@ -2271,6 +2273,7 @@ class TestStockValuation(TransactionCase): # stock values for move2 self.assertEqual(move2.value, -100.0) + self.assertAlmostEqual(move2.price_unit, -10.0) self.assertEqual(move2.remaining_qty, 0.0) self.assertEqual(move2.remaining_value, 0.0) @@ -2280,6 +2283,7 @@ class TestStockValuation(TransactionCase): move2.quantity_done = 8 self.assertEqual(move2.value, -80.0) # the move actually sent 8@10 + self.assertAlmostEqual(move2.price_unit, -10.0) self.assertEqual(move2.remaining_qty, 0.0) self.assertEqual(move2.remaining_value, 0.0)