From 1ff7fd2030d84abf82d5f0f30f3968e196ca2fc0 Mon Sep 17 00:00:00 2001 From: "Adrien Widart (awt)" Date: Mon, 6 Feb 2023 12:55:43 +0000 Subject: [PATCH] [FIX] stock: ensure destination location of SML To reproduce the issue: (Use demo data) 1. In Settings, enable "Multi Locations" 2. Create a storable and tracked-by-lot product P 3. Create an immediate receipt R 4. Add a line for 1 x P and save 5. Open the wizard 'Detailed Operations' and add a line: - 1 x P, lot 123, to WH/Stock/Shelf 1 6. Save 7. Open the wizard again Error: The destination location of the line is now WH/Stock When creating the SML, because we write on its done quantity, we will automatically write the same on the new done quantity of the SM on the demand of that SM. Doing so, it will trigger the assign process: https://github.com/odoo/odoo/blob/57ac92fc4c14bf305ffd9ef98212cc80013345f5/addons/stock/models/stock_move.py#L599-L602 (And it will therefore lead to the putaway rules feature) Once the above issue is fixed, there will be another one. When marking the SML as done, if it's needed, we assign it a lot. However, writing on such a field will trigger the reservation process: https://github.com/odoo/odoo/blob/c9fdd4f2ac2d8afb18cb0dd126bb0b88c54f374e/addons/stock/models/stock_move_line.py#L330-L333 And it will lead, again, to the putaway rules feature OPW-3086704 closes odoo/odoo#112322 X-original-commit: a3f6cefbbe81bafc0780a95729b8f9150afef817 Signed-off-by: Arnold Moyaux (arm) Signed-off-by: Adrien Widart --- addons/stock/models/stock_move_line.py | 4 +-- addons/stock/tests/test_stock_flow.py | 35 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index a1ccbd0af8c..abd8bc343f3 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -315,7 +315,7 @@ class StockMoveLine(models.Model): ml.move_id.picking_id.immediate_transfer and \ ml.move_id.state != 'done' and \ 'qty_done' in vals: - ml.move_id.product_uom_qty = ml.move_id.quantity_done + ml.move_id.with_context(avoid_putaway_rules=True).product_uom_qty = ml.move_id.quantity_done if ml.state == 'done': if 'qty_done' in vals: ml.move_id.product_uom_qty = ml.move_id.quantity_done @@ -567,7 +567,7 @@ class StockMoveLine(models.Model): raise UserError(_('You need to supply a Lot/Serial Number for product: \n - ') + '\n - '.join(mls_tracked_without_lot.mapped('product_id.display_name'))) ml_to_create_lot = self.env['stock.move.line'].browse(ml_ids_to_create_lot) - ml_to_create_lot.with_context(do_not_unreserve=True)._create_and_assign_production_lot() + ml_to_create_lot.with_context(bypass_reservation_update=True)._create_and_assign_production_lot() mls_to_delete = self.env['stock.move.line'].browse(ml_ids_to_delete) mls_to_delete.unlink() diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index be93963fbff..d8e295ef520 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -2408,3 +2408,38 @@ class TestStockFlow(TestStockCommon): in_stock_picking.button_validate() self.assertEqual(out_move.move_line_ids.reserved_qty, 1.0, 'The out move should be reserved') + + def test_assign_done_sml_and_validate_it(self): + """ + From the detailed operations wizard, create a SML that has a + sub-location as destination location. After its creation, the + destination location should not changed. Same when marking the picking + as done + """ + grp_multi_loc = self.env.ref('stock.group_stock_multi_locations') + self.env.user.write({'groups_id': [(4, grp_multi_loc.id, 0)]}) + + warehouse = self.env['stock.warehouse'].search([('company_id', '=', self.env.company.id)], limit=1) + stock_location = warehouse.lot_stock_id + sub_loc = stock_location.child_ids[0] + + self.productA.tracking = 'lot' + + receipt_form = Form(self.env['stock.picking'].with_context(default_immediate_transfer=True)) + receipt_form.picking_type_id = self.env.ref('stock.picking_type_in') + with receipt_form.move_ids_without_package.new() as move: + move.product_id = self.productA + receipt = receipt_form.save() + + with Form(receipt.move_ids, view='stock.view_stock_move_nosuggest_operations') as move_form: + with move_form.move_line_nosuggest_ids.new() as sml: + sml.location_dest_id = sub_loc + sml.lot_name = '123' + sml.qty_done = 10 + + done_sml = receipt.move_ids.move_line_ids.filtered(lambda sml: sml.qty_done > 0) + self.assertEqual(done_sml.location_dest_id, sub_loc) + + receipt.button_validate() + + self.assertEqual(receipt.move_ids.move_line_ids.location_dest_id, sub_loc)