From 6c853953eb626993bc6280a5d146edf7a1fdeb3d Mon Sep 17 00:00:00 2001 From: MerlinGuillaume Date: Wed, 13 Jul 2022 15:10:32 +0000 Subject: [PATCH] [FIX] stock: don't create empty move lines for receipts When creating a receipt with products tracked by lot or serial number, empty move lines are automatically created when the receipt is validated Steps to reproduce: 1. Install Inventory 2. Go to Inventory > Configuration > Warehouse Management > Operations Types 3. Open Receipts and enable 'Show Detailed Operations' and 'Pre-fill Detailed Operations' 4. Go to Overview > Receipts and create a new receipt, in Detailed Operations add product 'Cable Management Box' with any serial number and a quantity of 1 5. Validate the receipt, a new line is added in Detailed Operations with quantity 0 Solution: When we create a stock move line and we need to create a lot, we create the lot with the context key `do_not_unreserve` Problem: When we create and write the lot on stock move lines, we detect that the `product_uom_qty` is not set. Because we are in an immediate transfer, we will try and assign it the `quantity_done`. https://github.com/odoo/odoo/blob/7fec535f3d84d15899aea5e61b51947f260d9697/addons/stock/models/stock_move_line.py#L467-L469 By writing the `product_uom_qty` on the stock move, we will try to unreserve and reserve again the stock move (if `do_not_unreserve` is not in the context) https://github.com/odoo/odoo/blob/ba3bb9b701a382c4052ddb57392baeee32625937/addons/stock/models/stock_move.py#L569-L576 This will then create the undesired empty move lines (that are supposed to be the 'Pre-filled Detailed Operations') in _action_assign https://github.com/odoo/odoo/blob/3e8a45fce0af0aa5792f0aea978d4ab78ab50a40/addons/stock/models/stock_move.py#L1586 opw-2897875 closes odoo/odoo#95983 Signed-off-by: Tiffany Chang --- addons/stock/models/stock_move_line.py | 2 +- addons/stock/tests/test_move2.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index fbee3631893..4b58ef07e6d 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -566,7 +566,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._create_and_assign_production_lot() + ml_to_create_lot.with_context(do_not_unreserve=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_move2.py b/addons/stock/tests/test_move2.py index f5286a57f3b..b6c18882045 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -2232,6 +2232,26 @@ class TestSinglePicking(TestStockCommon): self.assertEqual(picking.move_ids.state, 'cancel', "Stock move should be in a cancel state.") self.assertEqual(picking.state, 'cancel', "Picking should be in a cancel state.") + def test_immediate_picking_with_lot(self): + self.productA.tracking = 'serial' + picking = self.env['stock.picking'].create({ + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + 'picking_type_id': self.picking_type_in, + 'immediate_transfer': True, + 'move_line_ids': [(0, 0, { + 'product_id': self.productA.id, + 'product_uom_id': self.productA.uom_id.id, + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + 'qty_done': 1, + 'lot_name': '12345', + })] + }) + + self.assertEqual(len(picking.move_line_ids), 1, "Picking should have a single move line") + picking.button_validate() + self.assertEqual(len(picking.move_line_ids), 1, "Picking should have a single move line") class TestStockUOM(TestStockCommon): @classmethod