From 28e1fdce4e5ecd09963e69bb2956097914cd1994 Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Thu, 26 Jan 2023 12:35:35 +0000 Subject: [PATCH] [FIX] stock: auto batch of internal transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce the bug: - Enable “batch transfers” in the inventory settings - Create a new warehouse “WH2”: - Enable “Resupply From” option - Enable “3steps” - Go to the operation type “internal transfers” of WH2: - Enable “Automatic Batches” - “Destination Location” - Create two storable product “P1” and “P2”: - Route: warehouse # 2: Supply Product from YourCompany - update the Qty to 10 in wh/stock - Create a replenishment for “P1” and “p2”: - Location: WH2/stock - Preferred route: warehouse # 2: Supply Product from YourCompany - Procurement Group: select two different procurement - min qty: 1 Problem: Two internal pickings are created for “P1” and two others for “P2”, because two different procurement: - from “input” to “quality control” - from “quality control” to “wh/stock2” But as the pickings have the same location destination, two batches are supposed to be created to group the pickings. The `_find_auto_batch` function is triggered when the picking is confirmed: https://github.com/odoo/odoo/blob/16.0/addons/stock_picking_batch/models/stock_picking.py#L120 but since the pickings are not confirmed, the function is not called: opw-3076077 closes odoo/odoo#111716 X-original-commit: 324298967cb63d7de1144c8aee2039119443e60c Signed-off-by: William Henrotin (whe) --- .../stock_picking_batch/models/stock_move.py | 4 ++ .../tests/test_batch_picking.py | 65 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/addons/stock_picking_batch/models/stock_move.py b/addons/stock_picking_batch/models/stock_move.py index af4b61970f7..5e12cb0a327 100644 --- a/addons/stock_picking_batch/models/stock_move.py +++ b/addons/stock_picking_batch/models/stock_move.py @@ -21,3 +21,7 @@ class StockMove(models.Model): if picking.state == 'cancel' and picking.batch_id and any(p.state != 'cancel' for p in picking.batch_id.picking_ids): picking.batch_id = None return res + + def _assign_picking_post_process(self, new=False): + super(StockMove, self)._assign_picking_post_process(new=new) + self.picking_id.action_confirm() diff --git a/addons/stock_picking_batch/tests/test_batch_picking.py b/addons/stock_picking_batch/tests/test_batch_picking.py index 32303b1795f..1ff175cdd6f 100644 --- a/addons/stock_picking_batch/tests/test_batch_picking.py +++ b/addons/stock_picking_batch/tests/test_batch_picking.py @@ -460,6 +460,71 @@ class TestBatchPicking(TransactionCase): self.assertFalse(picking_out_1.batch_id) self.assertEqual(len(picking_out_3.batch_id.picking_ids), 1) + def test_auto_batch_02(self): + """ Test that the auto batch works correctly in internal transfers + when they are created from an order point: + * WH1: 1 steps outgoing transfers: + - Delivery orders: auto batch - source location + * WH2: 3 steps incoming transfers, ressuply from WH1 + - internal transfert/ WH2 : auto batch - destination location + * orderpoint: + - Product A - Location: WH2 - Route: WH2/supply from WH1 - procurement: P1 - min_qty: 1 + - Product B - Location: WH2 - Route: WH2/supply from >H1 - procurement: P2 - min_qty: 1 + + * Result: 6 pickings and 3 batchs + """ + warehouse_1 = self.env['stock.warehouse'].search([], limit=1) + warehouse_2 = self.env['stock.warehouse'].create({ + 'name': 'WH 2', + 'code': 'WH2', + 'company_id': warehouse_1.company_id.id, + 'resupply_wh_ids': [(6, 0, [warehouse_1.id])], + 'reception_steps': 'three_steps', + }) + warehouse_1.int_type_id.write({ + 'auto_batch': True, + 'batch_group_by_src_loc': True, + }) + warehouse_2.int_type_id.write({ + 'auto_batch': True, + 'batch_group_by_dest_loc': True, + }) + self.env['stock.quant']._update_available_quantity(self.productA, warehouse_1.lot_stock_id, 10) + self.env['stock.quant']._update_available_quantity(self.productB, warehouse_1.lot_stock_id, 10) + procurement_1 = self.env['procurement.group'].create({ + 'move_type': 'direct', + 'partner_id': self.client_1.id + }) + procurement_2 = self.env['procurement.group'].create({ + 'move_type': 'direct', + 'partner_id': self.client_1.id + }) + op1 = self.env['stock.warehouse.orderpoint'].create({ + 'name': 'Product A', + 'location_id': warehouse_2.lot_stock_id.id, + 'product_id': self.productA.id, + 'product_min_qty': 1, + 'product_max_qty': 1, + 'group_id': procurement_1.id, + 'route_id': warehouse_2.route_ids[0].id, + }) + op2 = self.env['stock.warehouse.orderpoint'].create({ + 'name': 'Product B', + 'location_id': warehouse_2.lot_stock_id.id, + 'product_id': self.productB.id, + 'product_min_qty': 1, + 'product_max_qty': 1, + 'group_id': procurement_2.id, + 'route_id': warehouse_2.route_ids[0].id, + }) + self.productA.route_ids = warehouse_2.resupply_route_ids + self.productB.route_ids = warehouse_2.resupply_route_ids + (op1 | op2)._procure_orderpoint_confirm() + self.assertEqual(len(procurement_1.stock_move_ids.picking_id.batch_id), 3) + self.assertEqual(procurement_1.stock_move_ids.picking_id[0].batch_id, procurement_2.stock_move_ids.picking_id[0].batch_id) + self.assertEqual(procurement_1.stock_move_ids.picking_id[1].batch_id, procurement_2.stock_move_ids.picking_id[1].batch_id) + self.assertEqual(procurement_1.stock_move_ids.picking_id[2].batch_id, procurement_2.stock_move_ids.picking_id[2].batch_id) + def test_remove_all_transfers_from_confirmed_batch(self): """ Check that the batch is canceled when all transfers are deleted