From e324243e5f425e748ba5553a28440f32aa5747b2 Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Wed, 22 Mar 2023 12:41:29 +0000 Subject: [PATCH] [FIX] stock: validate an immediate transfer without a backorder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce the bug: - Create a Storable product “C1” tracked by Lot: - Update the Qty to 10 - Create a Storable product “P1”: - Add a BoM: - add 1 unit of “C1” as component - Enable 3 steps for the manufacturing operation in warehouse settings - Create a Mo to produce 1 unit of “P1”: - Confirm the MO - Click on related transfer: - Select the “Pick component” - check that the qty is reserved correctly - Try to validate it without setting Qty done - The immediate transfer is triggered, validate it Problem: The backorder's wizard triggers when it shouldn't To know if we should create a backorder, we check if the qty reserved is equal to the qty done, and as the qty done was not set correctly during the validation of the immediate transfer, the two quantities are not identical, therefore the widget is trigger: https://github.com/odoo/odoo/blob/15.0/addons/stock/models/stock_picking.py#L1128-L1132 opw-3240264 closes odoo/odoo#117706 X-original-commit: dd44e1f69dfd217fafa9c2ec5da8b211b2ff3513 Signed-off-by: Steve Van Essche Signed-off-by: Djamel Touati (otd) --- addons/stock/models/stock_move.py | 10 +++++----- addons/stock/tests/test_move.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 335db29f46f..30844ab6da9 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -2027,11 +2027,11 @@ Please change the quantity done or the rounding precision of your unit of measur if move.state not in ('partially_available', 'assigned'): continue for move_line in move.move_line_ids: - if move.has_tracking != 'none' and ( - (move.picking_type_id.use_existing_lots and not move_line.lot_id) or - (move.picking_type_id.use_create_lots and not move_line.lot_name)): - continue - move_line.qty_done = move_line.reserved_uom_qty + if move.has_tracking == 'none' or\ + (move.picking_type_id.use_existing_lots and move_line.lot_id) or\ + (move.picking_type_id.use_create_lots and move_line.lot_name) or\ + (not move.picking_type_id.use_existing_lots and not move.picking_type_id.use_create_lots): + move_line.qty_done = move_line.reserved_uom_qty def _clear_quantities_to_zero(self): self.filtered(lambda m: m.state in ('partially_available', 'assigned')).move_line_ids.qty_done = 0 diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index 682619157a4..f45ac2cea10 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -4602,6 +4602,36 @@ class StockMove(TransactionCase): immediate_wizard_form.process() self.assertEqual(receipt.state, 'done') + def test_immediate_validate_10_tracked_move_without_backorder(self): + """ + Create a picking for a tracked product, validate it as an + immediate transfer, and ensure that the backorder wizard is + not triggered when the qty is reserved. + """ + picking_type_internal = self.env.ref('stock.picking_type_internal') + picking_type_internal.use_create_lots = True + picking_type_internal.use_existing_lots = True + lot = self.env['stock.lot'].create({ + 'name': 'Lot 1', + 'product_id': self.product_lot.id, + 'company_id': self.env.company.id, + }) + self.env['stock.quant']._update_available_quantity(self.product_lot, self.stock_location, 10, lot_id=lot) + picking_form = Form(self.env['stock.picking']) + picking_form.picking_type_id = picking_type_internal + with picking_form.move_ids_without_package.new() as move: + move.product_id = self.product_lot + move.product_uom_qty = 4 + internal_transfer = picking_form.save() + internal_transfer.action_confirm() + + immediate_wizard = internal_transfer.button_validate() + immediate_wizard_form = Form( + self.env[immediate_wizard['res_model']].with_context(immediate_wizard['context']) + ).save() + immediate_wizard_form.process() + self.assertEqual(internal_transfer.state, 'done') + def test_set_quantity_done_1(self): move1 = self.env['stock.move'].create({ 'name': 'test_set_quantity_done_1',