From 26c29efca6696ae1783d2b5fae37994811277a19 Mon Sep 17 00:00:00 2001 From: Jacques-Etienne Baudoux Date: Fri, 3 Jan 2025 12:58:45 +0100 Subject: [PATCH] [PERF] stock_release_channel: kanban Load picking counters for all channels at once --- .../models/stock_release_channel.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/stock_release_channel/models/stock_release_channel.py b/stock_release_channel/models/stock_release_channel.py index dfeebd1229..704332b29a 100644 --- a/stock_release_channel/models/stock_release_channel.py +++ b/stock_release_channel/models/stock_release_channel.py @@ -6,11 +6,13 @@ import logging from collections import defaultdict from copy import deepcopy +from operator import itemgetter from pytz import timezone from odoo import _, api, exceptions, fields, models from odoo.osv.expression import NEGATIVE_TERM_OPERATORS +from odoo.tools import groupby from odoo.tools.safe_eval import ( datetime as safe_datetime, dateutil as safe_dateutil, @@ -460,15 +462,18 @@ def _query_get_chain(self, pickings): WITH RECURSIVE pickings AS ( SELECT move.picking_id, + stock_picking.release_channel_id, true as outgoing, ''::varchar as state, -- no need it, we exclude outgoing move.id as move_orig_id FROM stock_move move + INNER JOIN stock_picking ON move.picking_id = stock_picking.id WHERE move.picking_id in %s UNION SELECT move.picking_id, + pickings.release_channel_id, false as outgoing, picking.state, rel.move_orig_id @@ -480,7 +485,7 @@ def _query_get_chain(self, pickings): INNER JOIN stock_picking picking ON picking.id = move.picking_id ) - SELECT DISTINCT picking_id, state FROM pickings + SELECT DISTINCT release_channel_id, picking_id, state FROM pickings WHERE outgoing is false; """ return (query, (tuple(pickings.ids),)) @@ -490,20 +495,24 @@ def _compute_picking_chain(self): ["move_dest_ids", "move_orig_ids", "picking_id"] ) self.env["stock.picking"].flush_model(["state"]) - for channel in self: - domain = self._field_picking_domains()["released"] - domain += [("release_channel_id", "=", channel.id)] - released = self.env["stock.picking"].search(domain) - if not released: + domain = self._field_picking_domains()["released"] + domain += [("release_channel_id", "in", self.ids)] + released = self.env["stock.picking"].search(domain) + + if not released: + for channel in self: channel.picking_chain_ids = False channel.count_picking_chain = 0 channel.count_picking_chain_in_progress = 0 channel.count_picking_chain_done = 0 - continue + return - self.env.cr.execute(*self._query_get_chain(released)) - rows = self.env.cr.dictfetchall() + self.env.cr.execute(*self._query_get_chain(released)) + rows = self.env.cr.dictfetchall() + rows_by_channel = dict(groupby(rows, key=itemgetter("release_channel_id"))) + for channel in self: + rows = rows_by_channel.get(channel.id, []) channel.picking_chain_ids = [row["picking_id"] for row in rows] channel.count_picking_chain_in_progress = sum( [1 for row in rows if row["state"] not in ("cancel", "done")]