From 38eb5346c75fb97f215d59d208978cbc27a82b6e Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Fri, 28 Jun 2019 11:55:50 +0000 Subject: [PATCH] [FIX] purchase_stock: average cost - Create 2 rates: 2019-05-01: 1.0 2019-06-01: 0.5 - Set-up a product A in AVCO - Create a PO for A on 2019-05-15 - Receive the product after 2019-06-01 The AML are created with a rate of 0.5, but the product cost is updated with the rate of 1.0. This is because the stock move date is used when it is still assigned, and not done yet. As described in: https://github.com/odoo/odoo/blob/2f789b6863407e63f90b3a2d4cc3be09815f7002/addons/stock/models/stock_move.py#L36 The date is the scheduled date until the move is done, then it is the date of the actual move processing. We change the date to today's date, since it is the value used to update the move date: https://github.com/odoo/odoo/blob/2f789b6863407e63f90b3a2d4cc3be09815f7002/addons/stock/models/stock_move.py#L1143 opw-2006368 Note: the test has been slightly refactored to avoid an inconsistency between `fields.Date.context_today` and `fields.Datetime.now`. Now, they both return the same day. Moreover, the date is updated before each action. closes odoo/odoo#34444 Signed-off-by: Nicolas Martinelli (nim) --- addons/purchase_stock/models/stock.py | 6 +++- .../tests/test_stockvaluation.py | 32 ++++++++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/addons/purchase_stock/models/stock.py b/addons/purchase_stock/models/stock.py index ec645364e50..15f2ecee538 100644 --- a/addons/purchase_stock/models/stock.py +++ b/addons/purchase_stock/models/stock.py @@ -46,8 +46,12 @@ class StockMove(models.Model): if line.product_uom.id != line.product_id.uom_id.id: price_unit *= line.product_uom.factor / line.product_id.uom_id.factor if order.currency_id != order.company_id.currency_id: + # The date must be today, and not the date of the move since the move move is still + # in assigned state. However, the move date is the scheduled date until move is + # done, then date of actual move processing. See: + # https://github.com/odoo/odoo/blob/2f789b6863407e63f90b3a2d4cc3be09815f7002/addons/stock/models/stock_move.py#L36 price_unit = order.currency_id._convert( - price_unit, order.company_id.currency_id, order.company_id, self.date, round=False) + price_unit, order.company_id.currency_id, order.company_id, fields.Date.context_today(self), round=False) return price_unit return super(StockMove, self)._get_price_unit() diff --git a/addons/purchase_stock/tests/test_stockvaluation.py b/addons/purchase_stock/tests/test_stockvaluation.py index 46cb357ed50..0b2701c5dae 100644 --- a/addons/purchase_stock/tests/test_stockvaluation.py +++ b/addons/purchase_stock/tests/test_stockvaluation.py @@ -776,12 +776,12 @@ class TestStockValuationWithCOA(AccountingTestCase): 'company_id': company.id, }) - # To allow testing validation of PO + # To allow testing validation of PO and Delivery + today = date_po def _today(*args, **kwargs): - return date_po - # To allow testing validation of Delivery + return today def _now(*args, **kwargs): - return date_delivery + ' 01:00:00' + return today + ' 01:00:00' patchers = [ patch('odoo.fields.Date.context_today', _today), @@ -810,13 +810,17 @@ class TestStockValuationWithCOA(AccountingTestCase): line_product_avg = po.order_line.filtered(lambda l: l.product_id == product_avg) + today = date_delivery picking = po.picking_ids (picking.move_lines .filtered(lambda l: l.purchase_line_id == line_product_avg) .write({'quantity_done': 1.0})) picking.button_validate() + # 5 Units received at rate 0.7 = 42.86 + self.assertAlmostEqual(product_avg.standard_price, 42.86) + today = date_invoice inv = self.env['account.invoice'].create({ 'type': 'in_invoice', 'date_invoice': date_invoice, @@ -899,7 +903,7 @@ class TestStockValuationWithCOA(AccountingTestCase): 'purchase_method': 'purchase', 'cost_method': 'average', 'name': 'AVG', - 'standard_price': 60, + 'standard_price': 0, 'property_account_creditor_price_difference': self.price_diff_account.id }).product_variant_id product_avg.invoice_policy = 'order' @@ -946,13 +950,12 @@ class TestStockValuationWithCOA(AccountingTestCase): 'company_id': company.id, }) - # To allow testing validation of PO + # To allow testing validation of PO and Delivery + today = date_po def _today(*args, **kwargs): - return date_po - # To allow testing validation of Delivery - delivery_now = date_delivery + return today def _now(*args, **kwargs): - return delivery_now + ' 01:00:00' + return today + ' 01:00:00' patchers = [ patch('odoo.fields.Date.context_today', _today), @@ -981,6 +984,7 @@ class TestStockValuationWithCOA(AccountingTestCase): line_product_avg = po.order_line.filtered(lambda l: l.product_id == product_avg) + today = date_delivery picking = po.picking_ids (picking.move_lines .filtered(lambda l: l.purchase_line_id == line_product_avg) @@ -988,7 +992,10 @@ class TestStockValuationWithCOA(AccountingTestCase): picking.button_validate() picking.action_done() # Create Backorder + # 5 Units received at rate 0.7 = 42.86 + self.assertAlmostEqual(product_avg.standard_price, 42.86) + today = date_invoice inv = self.env['account.invoice'].create({ 'type': 'in_invoice', 'date_invoice': date_invoice, @@ -1011,13 +1018,16 @@ class TestStockValuationWithCOA(AccountingTestCase): inv.action_invoice_open() + today = date_delivery1 backorder_picking = self.env['stock.picking'].search([('backorder_id', '=', picking.id)]) - delivery_now = date_delivery1 (backorder_picking.move_lines .filtered(lambda l: l.purchase_line_id == line_product_avg) .write({'quantity_done': 5.0})) backorder_picking.button_validate() + # 5 Units received at rate 0.7 (42.86) + 5 Units received at rate 0.8 (37.50) = 40.18 + self.assertAlmostEqual(product_avg.standard_price, 40.18) + today = date_invoice1 inv1 = self.env['account.invoice'].create({ 'type': 'in_invoice', 'date_invoice': date_invoice1,