[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) <whe@odoo.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user