From 17f723a7d4c5bc48922c3c8bd02cf14019df36a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Voet=20=28ryv=29?= Date: Mon, 28 Dec 2020 12:50:06 +0000 Subject: [PATCH] [IMP] stock: improve scalability of `_action_assign` Replace union of RecordSet by union of OrderedSet to reduce the complexity and improve the scalability. It can be a bottleneck to huge number of move to assign. task-2390516 X-original-commit: e89105144a34ee73981db383ac0625dcaf63b27b --- addons/stock/models/stock_move.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 1708ffa3b6d..e454a733d0c 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -1272,8 +1272,9 @@ class StockMove(models.Model): equal to its `product_qty`. If it is less, the stock move is considered partially available. """ - assigned_moves = self.env['stock.move'] - partially_available_moves = self.env['stock.move'] + StockMove = self.env['stock.move'] + assigned_moves_ids = OrderedSet() + partially_available_moves_ids = OrderedSet() # Read the `reserved_availability` field of the moves out of the loop to prevent unwanted # cache invalidation when actually reserving the move. reserved_availability = {move: move.reserved_availability for move in self} @@ -1300,17 +1301,17 @@ class StockMove(models.Model): to_update[0].product_uom_qty += missing_reserved_uom_quantity else: move_line_vals_list.append(move._prepare_move_line_vals(quantity=missing_reserved_quantity)) - assigned_moves |= move + assigned_moves_ids.add(move.id) else: if float_is_zero(move.product_uom_qty, precision_rounding=move.product_uom.rounding): - assigned_moves |= move + assigned_moves_ids.add(move.id) elif not move.move_orig_ids: if move.procure_method == 'make_to_order': continue # If we don't need any quantity, consider the move assigned. need = missing_reserved_quantity if float_is_zero(need, precision_rounding=rounding): - assigned_moves |= move + assigned_moves_ids.add(move.id) continue # Reserve new quants and create move lines accordingly. forced_package_id = move.package_level_id.package_id or None @@ -1321,9 +1322,9 @@ class StockMove(models.Model): if float_is_zero(taken_quantity, precision_rounding=rounding): continue if float_compare(need, taken_quantity, precision_rounding=rounding) == 0: - assigned_moves |= move + assigned_moves_ids.add(move.id) else: - partially_available_moves |= move + partially_available_moves_ids.add(move.id) else: # Check what our parents brought and what our siblings took in order to # determine what we can distribute. @@ -1348,7 +1349,7 @@ class StockMove(models.Model): # As we defer the write on the stock.move's state at the end of the loop, there # could be moves to consider in what our siblings already took. moves_out_siblings = move.move_orig_ids.mapped('move_dest_ids') - move - moves_out_siblings_to_consider = moves_out_siblings & (assigned_moves + partially_available_moves) + moves_out_siblings_to_consider = moves_out_siblings & (StockMove.browse(assigned_moves_ids) + StockMove.browse(partially_available_moves_ids)) reserved_moves_out_siblings = moves_out_siblings.filtered(lambda m: m.state in ['partially_available', 'assigned']) move_lines_out_reserved = (reserved_moves_out_siblings | moves_out_siblings_to_consider).mapped('move_line_ids') keys_out_groupby = ['location_id', 'lot_id', 'package_id', 'owner_id'] @@ -1388,15 +1389,15 @@ class StockMove(models.Model): if float_is_zero(taken_quantity, precision_rounding=rounding): continue if float_is_zero(need - taken_quantity, precision_rounding=rounding): - assigned_moves |= move + assigned_moves_ids.add(move.id) break - partially_available_moves |= move + partially_available_moves_ids.add(move.id) if move.product_id.tracking == 'serial': move.next_serial_count = move.product_uom_qty self.env['stock.move.line'].create(move_line_vals_list) - partially_available_moves.write({'state': 'partially_available'}) - assigned_moves.write({'state': 'assigned'}) + StockMove.browse(partially_available_moves_ids).write({'state': 'partially_available'}) + StockMove.browse(assigned_moves_ids).write({'state': 'assigned'}) if self.env.context.get('bypass_entire_pack'): return self.mapped('picking_id')._check_entire_pack()