From 0cde25498772443b2a246dc1b66a08c72e24692c Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Mon, 13 Feb 2023 15:43:58 +0000 Subject: [PATCH] [FIX] mrp_subcontrating: fix batch validation 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” - Update the qty to 100 - Create a Transfer: - product: P1 - type: Delivery order - qty: 1 unit - Mark as to do - Reserve the Qty - Create a seconde transfer: - product: P1 - type: Delivery order - qty: 5 unit - Mark as to do - Reserve the Qty - qty done: 2 unit - Create a batch picking with the 2 transfer - Try to validate the batch Problem: A traceback is triggered: “ValueError: min() arg is an empty sequence”: https://github.com/odoo/odoo/blob/829369d3ca0530f1aad0599fbb1598810a928cc3/addons/mrp_subcontracting/models/stock_picking.py#L73 Because when validating the first picking, the `_action_done` function is triggered, so moves that do not have qty done will be cancelled https://github.com/odoo/odoo/blob/3073779762a106b4022bfb0a350758445d28ea15/addons/stock/models/stock_move.py#L1524-L1529 Therefore, the reserved qty will be unreserved, and the `stock.move.line` will be unlinked https://github.com/odoo/odoo/blob/3073779762a106b4022bfb0a350758445d28ea15/addons/stock/models/stock_move.py#L1442 https://github.com/odoo/odoo/blob/3073779762a106b4022bfb0a350758445d28ea15/addons/stock/models/stock_move.py#L724 Solution: We get the `date` from the `stock.move.line` to use it only when we have subcontracted production, we can therefore add a check before accessing them opw-3159876 closes odoo/odoo#113136 X-original-commit: e996a45be6326cf76cf96ee76eb97abc86017458 Signed-off-by: William Henrotin (whe) Signed-off-by: Djamel Touati (otd) --- .../tests/test_batch_picking.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/addons/stock_picking_batch/tests/test_batch_picking.py b/addons/stock_picking_batch/tests/test_batch_picking.py index fdff1b30136..b419ca568d8 100644 --- a/addons/stock_picking_batch/tests/test_batch_picking.py +++ b/addons/stock_picking_batch/tests/test_batch_picking.py @@ -587,6 +587,11 @@ class TestBatchPicking02(TransactionCase): 'type': 'product', 'categ_id': self.env.ref('product.product_category_all').id, }) + self.productB = self.env['product.product'].create({ + 'name': 'Product B', + 'type': 'product', + 'categ_id': self.env.ref('product.product_category_all').id, + }) def test_same_package_several_pickings(self): """ @@ -634,3 +639,53 @@ class TestBatchPicking02(TransactionCase): {'state': 'done', 'quantity_done': 7}, ]) self.assertEqual(pickings.move_line_ids.result_package_id, package) + + + def test_batch_validation_without_backorder(self): + loc1, loc2 = self.stock_location.child_ids + self.env['stock.quant']._update_available_quantity(self.productA, loc1, 10) + self.env['stock.quant']._update_available_quantity(self.productB, loc1, 10) + picking_1 = self.env['stock.picking'].create({ + 'location_id': loc1.id, + 'location_dest_id': loc2.id, + 'picking_type_id': self.picking_type_internal.id, + 'company_id': self.env.company.id, + }) + self.env['stock.move'].create({ + 'name': self.productA.name, + 'product_id': self.productA.id, + 'product_uom_qty': 1, + 'product_uom': self.productA.uom_id.id, + 'picking_id': picking_1.id, + 'location_id': loc1.id, + 'location_dest_id': loc2.id, + }) + + picking_2 = self.env['stock.picking'].create({ + 'location_id': loc1.id, + 'location_dest_id': loc2.id, + 'picking_type_id': self.picking_type_internal.id, + 'company_id': self.env.company.id, + }) + self.env['stock.move'].create({ + 'name': self.productB.name, + 'product_id': self.productB.id, + 'product_uom_qty': 5, + 'product_uom': self.productB.uom_id.id, + 'picking_id': picking_2.id, + 'location_id': loc1.id, + 'location_dest_id': loc2.id, + }) + (picking_1 | picking_2).action_confirm() + (picking_1 | picking_2).action_assign() + picking_2.move_ids.move_line_ids.write({'qty_done': 1}) + + batch = self.env['stock.picking.batch'].create({ + 'name': 'Batch 1', + 'company_id': self.env.company.id, + 'picking_ids': [(4, picking_1.id), (4, picking_2.id)] + }) + batch.action_confirm() + action = batch.action_done() + Form(self.env[action['res_model']].with_context(action['context'])).save().process_cancel_backorder() + self.assertEqual(batch.state, 'done')