[REF] mrp: action_explode and unlink

`action_explode` is called when confirming the moves of a picking.  It
calls unlink() when the move contains a kit.  As this method is not
multi, when confirming 50 kit moves, unlink is called 50 times resulting in
a lot of cache invalidation, prefetching and so on.

We make `action_explode` multi in order to call one time `unlink` per
kit levels.

X-original-commit: 096c682e748f7e581e48f0070ec8a3284d8a2fe7
This commit is contained in:
William Henrotin
2020-02-13 16:02:29 +00:00
parent 84723d4278
commit 7d1e78db92
+31 -32
View File
@@ -169,9 +169,7 @@ class StockMove(models.Model):
return res
def _action_confirm(self, merge=True, merge_into=False):
moves = self.env['stock.move']
for move in self:
moves |= move.action_explode()
moves = self.action_explode()
# we go further with the list of ids potentially changed by action_explode
return super(StockMove, moves)._action_confirm(merge=merge, merge_into=merge_into)
@@ -180,37 +178,38 @@ class StockMove(models.Model):
# in order to explode a move, we must have a picking_type_id on that move because otherwise the move
# won't be assigned to a picking and it would be weird to explode a move into several if they aren't
# all grouped in the same picking.
if not self.picking_type_id:
return self
bom = self.env['mrp.bom'].sudo()._bom_find(product=self.product_id, company_id=self.company_id.id, bom_type='phantom')
if not bom:
return self
phantom_moves = self.env['stock.move']
processed_moves = self.env['stock.move']
if self.picking_id.immediate_transfer:
factor = self.product_uom._compute_quantity(self.quantity_done, bom.product_uom_id) / bom.product_qty
else:
factor = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.sudo().explode(self.product_id, factor, picking_type=bom.picking_type_id)
for bom_line, line_data in lines:
if self.picking_id.immediate_transfer:
phantom_moves += self._generate_move_phantom(bom_line, 0, line_data['qty'])
moves_to_return = self.env['stock.move']
moves_to_unlink = self.env['stock.move']
for move in self:
if not move.picking_type_id:
moves_to_return |= move
continue
bom = self.env['mrp.bom'].sudo()._bom_find(product=move.product_id, company_id=move.company_id.id, bom_type='phantom')
if not bom:
moves_to_return |= move
continue
phantom_moves = self.env['stock.move']
processed_moves = self.env['stock.move']
if move.picking_id.immediate_transfer:
factor = move.product_uom._compute_quantity(move.quantity_done, bom.product_uom_id) / bom.product_qty
else:
phantom_moves += self._generate_move_phantom(bom_line, line_data['qty'], 0)
factor = move.product_uom._compute_quantity(move.product_uom_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.sudo().explode(move.product_id, factor, picking_type=bom.picking_type_id)
for bom_line, line_data in lines:
if move.picking_id.immediate_transfer:
phantom_moves += move._generate_move_phantom(bom_line, 0, line_data['qty'])
else:
phantom_moves += move._generate_move_phantom(bom_line, line_data['qty'], 0)
for new_move in phantom_moves:
processed_moves |= new_move.action_explode()
# if not self.split_from and self.procurement_id:
# # Check if procurements have been made to wait for
# moves = self.procurement_id.move_ids
# if len(moves) == 1:
# self.procurement_id.write({'state': 'done'})
if processed_moves and self.state == 'assigned':
# Set the state of resulting moves according to 'assigned' as the original move is assigned
processed_moves.write({'state': 'assigned'})
# delete the move with original product which is not relevant anymore
self.sudo().unlink()
return processed_moves
processed_moves |= phantom_moves.action_explode()
if processed_moves and move.state == 'assigned':
# Set the state of resulting moves according to 'assigned' as the original move is assigned
processed_moves.write({'state': 'assigned'})
# delete the move with original product which is not relevant anymore
moves_to_return |= processed_moves
moves_to_unlink |= move
moves_to_unlink.sudo().unlink()
return moves_to_return
def _action_cancel(self):
res = super(StockMove, self)._action_cancel()