diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index f13559a9337..5dc72f5c146 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -235,7 +235,7 @@ class StockMove(models.Model): break # Update the standard price with the price of the last used candidate, if any. - if new_standard_price: + if new_standard_price and move.product_id.cost_method == 'fifo': move.product_id.standard_price = new_standard_price # If there's still quantity to value but we're out of candidates, we fall in the @@ -264,29 +264,30 @@ class StockMove(models.Model): valued_move_lines = self.move_line_ids.filtered(lambda ml: not ml.location_id._should_be_valued() and ml.location_dest_id._should_be_valued()) valued_quantity = sum(valued_move_lines.mapped('qty_done')) - if self.product_id.cost_method in ['fifo', 'average']: - price_unit = self._get_price_unit() - value = price_unit * (quantity or valued_quantity) - vals = { - 'price_unit': price_unit, - 'value': value if quantity is None or not self.value else self.value, - 'remaining_value': value if quantity is None else self.remaining_value + value, - } - if self.product_id.cost_method == 'fifo': - vals['remaining_qty'] = valued_quantity if quantity is None else self.remaining_qty + quantity - self.write(vals) - else: # standard + # Note: we always compute the fifo `remaining_value` and `remaining_qty` fields no + # matter which cost method is set, to ease the switching of cost method. + vals = {} + price_unit = self._get_price_unit() + value = price_unit * (quantity or valued_quantity) + vals = { + 'price_unit': price_unit, + 'value': value if quantity is None or not self.value else self.value, + 'remaining_value': value if quantity is None else self.remaining_value + value, + } + vals['remaining_qty'] = valued_quantity if quantity is None else self.remaining_qty + quantity + + if self.product_id.cost_method == 'standard': value = self.product_id.standard_price * (quantity or valued_quantity) - self.write({ + vals.update({ 'price_unit': self.product_id.standard_price, 'value': value if quantity is None or not self.value else self.value, }) + self.write(vals) elif self._is_out(): valued_move_lines = self.move_line_ids.filtered(lambda ml: ml.location_id._should_be_valued() and not ml.location_dest_id._should_be_valued()) valued_quantity = sum(valued_move_lines.mapped('qty_done')) - if self.product_id.cost_method == 'fifo': - self.env['stock.move']._run_fifo(self, quantity=quantity) - elif self.product_id.cost_method in ['standard', 'average']: + self.env['stock.move']._run_fifo(self, quantity=quantity) + if self.product_id.cost_method in ['standard', 'average']: curr_rounding = self.company_id.currency_id.rounding value = -float_round(self.product_id.standard_price * (valued_quantity if quantity is None else quantity), precision_rounding=curr_rounding) self.write({ diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index 33aee80a1ca..f7e63cc9f15 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -2140,7 +2140,6 @@ class TestStockValuation(TransactionCase): move1._action_done() self.assertEqual(move1.value, 900.0) - self.assertEqual(move1.remaining_qty, 0.0) # unusedin average move # Purchase 140 units @ 15.50 per unit move2 = self.env['stock.move'].create({ @@ -2407,7 +2406,6 @@ class TestStockValuation(TransactionCase): move1.quantity_done = 10.0 move1._action_done() self.assertEqual(move1.value, -990.0) # as no move out were done for this product, fallback on the standard price - self.assertEqual(move1.remaining_qty, 0.0) # unused in average move def test_average_negative_3(self): """ Send goods that you don't have in stock but received and send some units before. @@ -2433,7 +2431,6 @@ class TestStockValuation(TransactionCase): move1._action_done() self.assertEqual(move1.value, 100.0) - self.assertEqual(move1.remaining_qty, 0.0) # unused in average move # send 10 products move2 = self.env['stock.move'].create({ @@ -2467,7 +2464,6 @@ class TestStockValuation(TransactionCase): move3._action_done() self.assertEqual(move3.value, -100.0) # as no move out were done for this product, fallback on latest cost - self.assertEqual(move3.remaining_qty, 0.0) # unused in average move def test_average_negative_4(self): self.product1.product_tmpl_id.cost_method = 'average' @@ -2491,7 +2487,6 @@ class TestStockValuation(TransactionCase): move1._action_done() self.assertEqual(move1.value, 100.0) - self.assertEqual(move1.remaining_qty, 0.0) # unused in average move def test_average_negative_5(self): self.product1.product_tmpl_id.cost_method = 'average' @@ -2678,7 +2673,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Change the production valuation to AVCO # --------------------------------------------------------------------- - self.product1.with_context(debug=True).product_tmpl_id.cost_method = 'average' + self.product1.product_tmpl_id.cost_method = 'average' # valuation should stay to ~240 self.assertAlmostEqual(self.product1.stock_value, 240, delta=0.03)