From 6981ae67af650e65208073d29f72db55db902376 Mon Sep 17 00:00:00 2001 From: Adrien Widart Date: Fri, 18 Feb 2022 12:52:05 +0000 Subject: [PATCH] [FIX] mrp, sale_stock: deliver more than expected ISSUE 01 When adding a product to a sale delivery, another picking is generated to return the additional product To reproduce the issue: 1. Create two consumable products P01 and P02 2. Create and confirm a SO with 1 x P01 3. Add 1 x P02 to the delivery and validate it 4. Go back to the SO Error: Another picking has been generated, it's a return for P02. This picking should not exist. When validating the picking, because of the new line, a sale order line is created with a quantity equal to 0. During the SOL creation, `_action_launch_stock_rule` is called and checks if a procurement must be created and processed. To do so, it checks if the SOL quantity (0 in our case) is the same than the procurement quantity (1 in our case): https://github.com/odoo/odoo/blob/6a0cbff92141961655a5f3e33abc23a2c5b1045d/addons/sale_stock/models/sale_order.py#L543-L549 Since the values are not the same, a procurement is created and processed. The feature that updates the SO when adding some products to the picking has been introduced by 1f0835a9d01b46b5cc617756f854c25541b644a7 and is correctly working in 14.0 because the condition (in `_action_launch_stock_rule`) is not the same: https://github.com/odoo/odoo/blob/ec5475ee881c5ca2bcc992592bfa4edf12f492df/addons/sale_stock/models/sale_order.py#L572-L574 In 14.0, we check if the SOL quantity is greater than the procurement quantity. The condition has changed in 15.0 due to a new feature (bda3225c6cc27bb2c2933eda3cc68c6f9708daf3). ISSUE 02 When delivering more than sold, a useless SM is generated. To reproduce the issue: 1. Create a consumable product P 2. Create and Confirm a SO with 3 x P 3. Deliver 5 x P Error: A new line appears (Demand: 2, Done: 0) Because the delivered quantity is more than expected, an extra move is created. Then, the extra_move is merged into the initial one a condition is respected: https://github.com/odoo/odoo/blob/6f2ba1e1b40a458e23c8ed712927c44d75d86614/addons/stock/models/stock_move.py#L1603-L1610 Here is the issue: the field `date_dealine` is not copied anymore (see [1]). Therefore, the condition will never be respected [1] fb781dcf57fdf03fcb7b41f7a7003e99e2889ee3 OPW-2716309 closes odoo/odoo#85649 X-original-commit: fabc32c4733bb404e74dc111d80aa1fe1edd4bfb Signed-off-by: Arnold Moyaux Signed-off-by: Adrien Widart --- addons/mrp/models/stock_move.py | 5 ----- addons/sale_stock/models/sale_order_line.py | 2 ++ addons/sale_stock/models/stock.py | 2 +- addons/sale_stock/tests/test_sale_stock.py | 7 +++++++ addons/stock/models/stock_move.py | 1 + 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index cc1ac61738e..d4e0ca36d5b 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -520,8 +520,3 @@ class StockMove(models.Model): self.move_line_ids = self._set_quantity_done_prepare_vals(quantity_done) else: super()._multi_line_quantity_done_set(quantity_done) - - def _prepare_extra_move_vals(self, qty): - vals = super()._prepare_extra_move_vals(qty) - vals['date_deadline'] = self.date_deadline - return vals diff --git a/addons/sale_stock/models/sale_order_line.py b/addons/sale_stock/models/sale_order_line.py index 3ac1fab0e6f..2c63eb0d008 100644 --- a/addons/sale_stock/models/sale_order_line.py +++ b/addons/sale_stock/models/sale_order_line.py @@ -295,6 +295,8 @@ class SaleOrderLine(models.Model): sale order line. procurement group will launch '_run_pull', '_run_buy' or '_run_manufacture' depending on the sale order line product rule. """ + if self._context.get("skip_procurement"): + return True precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') procurements = [] for line in self: diff --git a/addons/sale_stock/models/stock.py b/addons/sale_stock/models/stock.py index 65ce97dc2d2..8660d7b6134 100644 --- a/addons/sale_stock/models/stock.py +++ b/addons/sale_stock/models/stock.py @@ -110,7 +110,7 @@ class StockPicking(models.Model): sale_order_lines_vals.append(so_line_vals) if sale_order_lines_vals: - self.env['sale.order.line'].create(sale_order_lines_vals) + self.env['sale.order.line'].with_context(skip_procurement=True).create(sale_order_lines_vals) return res def _log_less_quantities_than_expected(self, moves): diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index 0bf7bd64bee..0be8b7d80f0 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -794,6 +794,7 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): self.assertEqual(len(sale_order.order_line), 1) self.assertEqual(sale_order.order_line.qty_delivered, 0) picking = sale_order.picking_ids + initial_product = sale_order.order_line.product_id picking_form = Form(picking) with picking_form.move_line_ids_without_package.edit(0) as move: @@ -819,6 +820,12 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): so_line_2.price_unit, 0, "Shouldn't get the product price as the invoice policy is on qty. ordered") + # Check the picking didn't change + self.assertRecordValues(sale_order.picking_ids.move_ids, [ + {'product_id': initial_product.id, 'quantity_done': 5}, + {'product_id': product_inv_on_order.id, 'quantity_done': 5}, + ]) + # Creates a second sale order for 3 product invoiced on qty. ordered. sale_order = self._get_new_sale_order(product=product_inv_on_order, amount=3) # Confirms the sale order, then increases the delivered qty., adds a new diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index bba0daa8d2d..f99178db75b 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -1580,6 +1580,7 @@ class StockMove(models.Model): 'product_uom_qty': qty, 'picking_id': self.picking_id.id, 'price_unit': self.price_unit, + 'date_deadline': self.date_deadline, } return vals