From 55f461060ecb1439c1000cd5f01ce181f764a316 Mon Sep 17 00:00:00 2001 From: "Adrien Widart (awt)" Date: Tue, 10 Oct 2023 13:29:04 +0000 Subject: [PATCH] [FIX] stock: display backorder wizard To reproduce the issue: 1. Create a planned receipt with two lines: - 10 x P - 10 x P 2. Confirm and set the done quantities: - 12 x P - 8 x P 3. Validate Error: The receipt is directly processed and a backorder is created. In case a backorder could be created, we should first display the wizard that asks for a user's confirmation When checking for the backorder wizard, we compare, for each **product**, the sum of the demands with the sum of the done quantities. In the above use case, we will have `10 + 10 == 12 + 8`, so we don't display the wizard. However, while processing the SMs, this is different. For the second SM, we will set its demand to 8, create a third SM with a demand equal to 2 and create a new picking (the backorder) for this new SM. This behaviour is legit, the backorder creation makes sense. This is why this commit fixes the wizard display conditions. OPW-3373255 closes odoo/odoo#138863 X-original-commit: 5affa219d8add6f256030b699f61ddf77a928c82 Signed-off-by: William Henrotin (whe) Signed-off-by: Adrien Widart (awt) --- addons/stock/models/stock_picking.py | 12 +++------- addons/stock/tests/test_stock_flow.py | 33 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 557f544cf38..a8083451bca 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -1245,16 +1245,10 @@ class Picking(models.Model): for picking in self: if picking.picking_type_id.create_backorder != 'ask': continue - quantity_todo = {} - quantity_done = {} - for move in picking.move_ids.filtered(lambda m: m.state != "cancel"): - quantity_todo.setdefault(move.product_id.id, 0) - quantity_done.setdefault(move.product_id.id, 0) - quantity_todo[move.product_id.id] += move.product_uom._compute_quantity(move.product_uom_qty, move.product_id.uom_id, rounding_method='HALF-UP') - quantity_done[move.product_id.id] += move.product_uom._compute_quantity(move.quantity_done, move.product_id.uom_id, rounding_method='HALF-UP') if any( - float_compare(quantity_done[x], quantity_todo.get(x, 0), precision_digits=prec,) == -1 - for x in quantity_done + float_compare(move.quantity_done, move.product_uom_qty, precision_digits=prec) < 0 + for move in picking.move_ids + if move.state != 'cancel' ): backorder_pickings |= picking return backorder_pickings diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index cc6ab052f1d..53f941a280b 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -2643,3 +2643,36 @@ class TestStockFlowPostInstall(TestStockCommon): delivery.button_validate() self.assertEqual(sn.last_delivery_partner_id, partner) + + def test_several_sm_with_same_product_and_backorders(self): + picking = self.env['stock.picking'].create({ + 'picking_type_id': self.picking_type_in, + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + }) + move01, move02 = self.env['stock.move'].create([{ + 'name': self.productA.name, + 'product_id': self.productA.id, + 'product_uom_qty': 10, + 'product_uom': self.productA.uom_id.id, + 'description_picking': desc, + 'picking_id': picking.id, + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + } for desc in ['Lorem', 'Ipsum']]) + + picking.action_confirm() + + move01.quantity_done = 12 + move02.quantity_done = 8 + + res = picking.button_validate() + self.assertIsInstance(res, dict) + self.assertEqual(res.get('res_model'), 'stock.backorder.confirmation') + + wizard = Form(self.env[res['res_model']].with_context(res['context'])).save() + wizard.process() + + backorder = picking.backorder_ids + self.assertEqual(backorder.move_ids.product_uom_qty, 2) + self.assertEqual(backorder.move_ids.description_picking, 'Ipsum')