From 34c192761fa375b56d617fec78fb63d8008f6451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20=28avd=29?= Date: Tue, 15 Feb 2022 12:56:41 +0000 Subject: [PATCH] [FIX] mrp: speedup _post_inventory for MO batches Rewrite _post_inventory to make it work better with mo batches. This mainly improves the time it takes to mark_as_done manufacturing orders from the Workorders ListView. stock.move._action_done is faster when called outside of a for loop, i.e. directly on self. opw-2760394 closes odoo/odoo#84846 X-original-commit: 4cc6083ea1bd28be07e275322481ad11d8995d58 Signed-off-by: William Henrotin (whe) --- addons/mrp/models/mrp_production.py | 38 +++++++++++++++++------------ 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index b53517a332e..6c9451535fd 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -13,7 +13,7 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models, _, Command from odoo.exceptions import UserError, ValidationError from odoo.tools import float_compare, float_round, float_is_zero, format_datetime -from odoo.tools.misc import OrderedSet, format_date +from odoo.tools.misc import OrderedSet, format_date, groupby as tools_groupby from odoo.addons.stock.models.stock_move import PROCUREMENT_PRIORITIES @@ -1439,27 +1439,33 @@ class MrpProduction(models.Model): return True def _post_inventory(self, cancel_backorder=False): + moves_to_do, moves_not_to_do = set(), set() + for move in self.move_raw_ids: + if move.state == 'done': + moves_not_to_do.add(move.id) + elif move.state != 'cancel': + moves_to_do.add(move.id) + if move.product_qty == 0.0 and move.quantity_done > 0: + move.product_uom_qty = move.quantity_done + self.env['stock.move'].browse(moves_to_do)._action_done(cancel_backorder=cancel_backorder) + moves_to_do = self.move_raw_ids.filtered(lambda x: x.state == 'done') - self.env['stock.move'].browse(moves_not_to_do) + # Create a dict to avoid calling filtered inside for loops. + moves_to_do_by_order = defaultdict(lambda: self.env['stock.move'], [ + (key, self.env['stock.move'].concat(*values)) + for key, values in tools_groupby(moves_to_do, key=lambda m: m.raw_material_production_id.id) + ]) for order in self: - moves_not_to_do = order.move_raw_ids.filtered(lambda x: x.state == 'done') - moves_to_do = order.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel')) - for move in moves_to_do.filtered(lambda m: m.product_qty == 0.0 and m.quantity_done > 0): - move.product_uom_qty = move.quantity_done - # MRP do not merge move, catch the result of _action_done in order - # to get extra moves. - moves_to_do = moves_to_do._action_done(cancel_backorder=cancel_backorder) - moves_to_do = order.move_raw_ids.filtered(lambda x: x.state == 'done') - moves_not_to_do - finish_moves = order.move_finished_ids.filtered(lambda m: m.product_id == order.product_id and m.state not in ('done', 'cancel')) # the finish move can already be completed by the workorder. if not finish_moves.quantity_done: finish_moves.quantity_done = float_round(order.qty_producing - order.qty_produced, precision_rounding=order.product_uom_id.rounding, rounding_method='HALF-UP') finish_moves.move_line_ids.lot_id = order.lot_producing_id - order._cal_price(moves_to_do) - - moves_to_finish = order.move_finished_ids.filtered(lambda x: x.state not in ('done', 'cancel')) - moves_to_finish = moves_to_finish._action_done(cancel_backorder=cancel_backorder) - order.action_assign() - consume_move_lines = moves_to_do.mapped('move_line_ids') + order._cal_price(moves_to_do_by_order[order.id]) + moves_to_finish = self.move_finished_ids.filtered(lambda x: x.state not in ('done', 'cancel')) + moves_to_finish = moves_to_finish._action_done(cancel_backorder=cancel_backorder) + self.action_assign() + for order in self: + consume_move_lines = moves_to_do_by_order[order.id].mapped('move_line_ids') order.move_finished_ids.move_line_ids.consume_line_ids = [(6, 0, consume_move_lines.ids)] return True