From 537e82d78d5dce64c5e28ea072fb771457f9cf6f Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Tue, 10 May 2022 17:20:04 +0000 Subject: [PATCH] [FIX] purchase_stock: update the move price after changing the PO line price MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce the bug: - Create a storable product “P1”: - Standard price: 20$ - Add vendor in the Purchase tab: - name: Azure Interior - min qty: 10 - price: $15 - Create a PO: - Vendor: "Azure Interior" - Product line: “P1” Automatically, the Quantity field will automatically get populated as 10 Units and price:$15 as per the pricelist - Confirm the PO A picking will be created containing a stock_move with a price of $15 and a QTY of 10 - Edit the Quantity to 9 Units and save the PO The price will be updated to $20 on the PO line, but not in the `stock.move` Problem: When we update the qty in the PO line, a new move with a quantity of “-1” and a price of “$20” will be created. Then, it will be merged with the initial move, but since they are not identical in the price, we can't merge them, so a new picking is created: https://github.com/odoo/odoo/blob/dda9700d8236091626cbd78efc0ca4116e1e1acd/addons/stock/models/stock_move.py#L869-L881 Solution: when the price is updated in a PO line, the price of its linked `stock.move` must also be updated opw-2825160 closes odoo/odoo#92208 X-original-commit: c8d74a1cb4bfed8226e52e0bc6f243b4e483fc98 Signed-off-by: Djamel Touati (otd) Signed-off-by: William Henrotin (whe) --- addons/purchase_stock/models/purchase.py | 2 + .../tests/test_create_picking.py | 41 +++++++++++++++++++ .../tests/test_stockvaluation.py | 2 - 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index 6575c51e218..454053441b1 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -366,6 +366,8 @@ class PurchaseOrderLine(models.Model): lines = self.filtered(lambda l: l.order_id.state == 'purchase') previous_product_qty = {line.id: line.product_uom_qty for line in lines} result = super(PurchaseOrderLine, self).write(values) + if 'price_unit' in values: + self.move_ids.price_unit = self.price_unit if 'product_qty' in values: lines.with_context(previous_product_qty=previous_product_qty)._create_or_update_picking() return result diff --git a/addons/purchase_stock/tests/test_create_picking.py b/addons/purchase_stock/tests/test_create_picking.py index cb5b76d13f5..6d267c5a284 100644 --- a/addons/purchase_stock/tests/test_create_picking.py +++ b/addons/purchase_stock/tests/test_create_picking.py @@ -600,3 +600,44 @@ class TestCreatePicking(common.TestProductCommon): self.assertEqual(purchase_order_line.product_qty, 45, 'The demand on the Purchase Order should not have been increased since it is has been confirmed.') purchase_orders = self.env['purchase.order'].search([('partner_id', '=', partner.id)]) self.assertEqual(len(purchase_orders), 2, 'A new RFQ should have been created for missing demand.') + + def test_update_qty_purchased(self): + """ + Test that the price unit in the purchase order line and the move is updated + according to the pricelist defined in the product, and that the "stock.moves" + are merged correctly when changing the qty purchased. + """ + # add vendor to the product + self.product_id_1.seller_ids = [(0, 0, { + 'partner_id': self.partner_id.id, + 'min_qty': 10, + 'price': 15, + })] + + # Create PO + po_form = Form(self.env['purchase.order']) + po_form.partner_id = self.partner_id + with po_form.order_line.new() as po_line: + po_line.product_id = self.product_id_1 + po_line.product_qty = 10 + purchase_order = po_form.save() + + # Confirm Purchase order + purchase_order.button_confirm() + # Check purchase order state, it should be "purchase". + self.assertEqual(purchase_order.state, 'purchase', 'Purchase order should be in purchase state.') + # Make sure that picking has been created + self.assertEqual(len(purchase_order.picking_ids), 1) + # check that the price list has been applied + self.assertEqual(purchase_order.order_line.price_unit, 15) + self.assertEqual(purchase_order.picking_ids.move_ids.price_unit, 15) + # update the product qty purchased + with po_form.order_line.edit(0) as po_line: + po_line.product_qty = 9 + purchase_order = po_form.save() + # verify that the move for the decreased qty has been merged with the initial move + self.assertEqual(len(purchase_order.picking_ids), 1) + self.assertEqual(len(purchase_order.picking_ids.move_ids), 1) + # check that the price has been updated in the purchase order line and in the stock.move + self.assertEqual(purchase_order.order_line.price_unit, 0) + self.assertEqual(purchase_order.picking_ids.move_ids.price_unit, 0) diff --git a/addons/purchase_stock/tests/test_stockvaluation.py b/addons/purchase_stock/tests/test_stockvaluation.py index 92de86ffb1c..799ab741855 100644 --- a/addons/purchase_stock/tests/test_stockvaluation.py +++ b/addons/purchase_stock/tests/test_stockvaluation.py @@ -88,8 +88,6 @@ class TestStockValuation(TransactionCase): # update the unit price on the purchase order line po1.order_line.price_unit = 200 - # the unit price on the stock move is not directly updated - self.assertEqual(move1.price_unit, 100) # validate the receipt res_dict = picking1.button_validate()