From e1316a425cd1a42bbb3c1d6f8cc8526d559eacb8 Mon Sep 17 00:00:00 2001 From: Walid Date: Thu, 25 Jan 2024 10:46:38 +0100 Subject: [PATCH] [FIX] stock: update SO line (reserved package) Steps to Reproduce: - Activate packaging - Create a storable product update on hand qty 1 package: "PACK6" - Create a sale order with the product qty 1 - Confirm the order, picking will have a package already assigned - Edit the sale order and set the product quantity to 0 Bug: a new move will be created with negtaive quantity and merged with original (correct behaviour) but when the picking is confirmed an extra move will be created due to the picking still having a package level set Fix: unlink the package level when its last linked SML is unlinked opw-3597188 closes odoo/odoo#150939 X-original-commit: 4983923973bacbff84d67cdd442d4b6985f33577 Signed-off-by: William Henrotin (whe) Signed-off-by: Walid Hanniche (waha) --- addons/sale_stock/tests/test_sale_stock.py | 23 ++++++++++++++++++++++ addons/stock/models/stock_move_line.py | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index 0fab4e26da5..cc367019650 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -1183,6 +1183,29 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon): self.assertEqual(len(sale_order.picking_ids), 2) + def test_update_so_line_qty_with_package(self): + """ + Creates a sale order, then validates the delivery + modifying the sale order lines qty to 0 + move line should be deleted. + """ + self.product_a.type = 'product' + self.env['stock.quant']._update_available_quantity( + self.product_a, self.company_data['default_warehouse'].lot_stock_id, 10, + package_id=self.env['stock.quant.package'].create({'name': 'PacMan'})) + + # Create sale order + sale_order = self._get_new_sale_order(product=self.product_a) + sale_order.action_confirm() + + # Update the SO line + with Form(sale_order.with_context(import_file=True)) as so_form: + with so_form.order_line.edit(0) as line: + line.product_uom_qty = 0 + + self.assertFalse(sale_order.picking_ids.package_level_ids) + self.assertFalse(sale_order.picking_ids.move_line_ids) + def test_multiple_returns(self): # Creates a sale order for 10 products. sale_order = self._get_new_sale_order() diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index 45011c3daae..ff281966ef6 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -488,7 +488,11 @@ class StockMoveLine(models.Model): quants = quants_by_product[ml.product_id.id] quants._update_reserved_quantity(ml.product_id, ml.location_id, -ml.quantity_product_uom, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True) moves = self.mapped('move_id') + package_levels = self.package_level_id res = super().unlink() + package_levels = package_levels.filtered(lambda pl: not (pl.move_line_ids or pl.move_ids)) + if package_levels: + package_levels.unlink() if moves: # Add with_prefetch() to set the _prefecht_ids = _ids # because _prefecht_ids generator look lazily on the cache of move_id