From b7c40e24b1815dde870da023eaccfcfb7b33df8d Mon Sep 17 00:00:00 2001 From: "Adrien Widart (awt)" Date: Fri, 26 May 2023 13:23:18 +0000 Subject: [PATCH] [FIX] stock: clean quants after moving package When moving a package, the quant at source location is not automatically removed To reproduce the issue: 1. In Settings, enable - Packages - Storage Locations 2. Create a storable product P 3. Update the on hand quantity - 1 x P at WH/Stock in package PK 4. Create a planned delivery D with 1 x P 5. Confirm and reserve D - PK should be reserved 6. Validate 7. Open the package - Its location is "Partner Locations/Customers", which make sense 8. Inventory > Configuration > ... > Locations, open WH/Stock 9. Current Stock Error: There is a line with PK. The quantity is 0 but still, it create some confusion for the user who could believe that the package is still in WH/Stock This issue does not occur if the user goes through the product form and click on the on hand quantity. The "incorrect" quant will not be there. This is because, when loading the action, we call `_quant_tasks`: https://github.com/odoo/odoo/blob/05a7f5c04804423cfc3a833a1b3f0b5eec3fc147/addons/stock/models/stock_quant.py#L296-L300 This method will clean the quants (merge & unlink) However, in the above case (step 9), the action is defined on XML side: https://github.com/odoo/odoo/blob/7d4dfeb0e26b387dee312897264a68963f90267f/addons/stock/views/stock_location_views.xml#L24-L26 https://github.com/odoo/odoo/blob/d956e719d43c68abe6210e3136db576aaa6f60b8/addons/stock/views/stock_quant_views.xml#L190-L196 So, we can't make it behave as it does from the product form, unfortunatly. As alternative, we can try to call `_unlink_zero_quants` when we are moving a package (and not `_quant_tasks` for perf matters as, so far, we will not have any quant to merge) OPW-3292238 closes odoo/odoo#123071 X-original-commit: 30cbfdc79e54a7e7a260051da321837cd224792c Signed-off-by: William Henrotin (whe) Signed-off-by: Adrien Widart (awt) --- addons/stock/models/stock_move.py | 2 ++ addons/stock/tests/test_quant.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index ebeb00c7f28..98a6a1c11d6 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -1861,6 +1861,8 @@ Please change the quantity done or the rounding precision of your unit of measur .filtered(lambda p: p.quant_ids and len(p.quant_ids) > 1): if len(result_package.quant_ids.filtered(lambda q: not float_is_zero(abs(q.quantity) + abs(q.reserved_quantity), precision_rounding=q.product_uom_id.rounding)).mapped('location_id')) > 1: raise UserError(_('You cannot move the same package content more than once in the same transfer or split the same package into two location.')) + if any(ml.package_id and ml.package_id == ml.result_package_id for ml in moves_todo.move_line_ids): + self.env['stock.quant']._unlink_zero_quants() picking = moves_todo.mapped('picking_id') moves_todo.write({'state': 'done', 'date': fields.Datetime.now()}) diff --git a/addons/stock/tests/test_quant.py b/addons/stock/tests/test_quant.py index f9ef1430d67..16778a0488b 100644 --- a/addons/stock/tests/test_quant.py +++ b/addons/stock/tests/test_quant.py @@ -974,3 +974,33 @@ class StockQuantRemovalStrategy(TransactionCase): [{'reserved_qty': 10}] * 5 + [{'reserved_qty': 5}] * 2 ) + + def test_clean_quant_after_package_move(self): + """ + A product is at WH/Stock in a package PK. We deliver PK. The user should + not find any quant at WH/Stock with PK anymore. + """ + package = self.env['stock.quant.package'].create({}) + self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0, package_id=package) + + move = self.env['stock.move'].create({ + 'name': 'OUT 1 product', + 'product_id': self.product.id, + 'product_uom_qty': 1, + 'product_uom': self.product.uom_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.ref('stock.stock_location_customers'), + }) + move._action_confirm() + move._action_assign() + move.move_line_ids.write({ + 'result_package_id': package.id, + 'qty_done': 1, + }) + move._action_done() + + self.assertFalse(self.env['stock.quant'].search_count([ + ('product_id', '=', self.product.id), + ('package_id', '=', package.id), + ('location_id', '=', self.stock_location.id), + ]))