[IMP] stock_picking_volume: Speedup installation

Init computed fields from plain sql queries to speedup install on large database
This commit is contained in:
Laurent Mignon (ACSONE)
2023-03-29 17:04:45 +02:00
committed by Sébastien Alix
parent 0c150e2713
commit dc8c5a478a
3 changed files with 52 additions and 18 deletions

View File

@@ -1,2 +1,2 @@
from . import models
from .hooks import post_init_hook, pre_init_hook
from .hooks import pre_init_hook

View File

@@ -20,7 +20,6 @@
"views/stock_move.xml",
],
"demo": [],
"post_init_hook": "post_init_hook",
"pre_init_hook": "pre_init_hook",
"development_status": "Beta",
}

View File

@@ -3,30 +3,65 @@
import logging
from odoo import SUPERUSER_ID, api
from odoo.tools.sql import column_exists, create_column
_logger = logging.getLogger(__name__)
def post_init_hook(cr, registry):
"""Post init hook to set compute the volume on pending move and pickings."""
env = api.Environment(cr, SUPERUSER_ID, {})
pickings = env["stock.picking"].search([("state", "not in", ["done", "cancel"])])
moves = env["stock.move"].search(
[
"|",
("state", "not in", ["done", "cancel"]),
("picking_id", "in", pickings.ids),
]
)
_logger.info("Compute volumes for %d moves", len(moves))
moves._compute_volume()
def pre_init_hook(cr):
"""Pre init create volume column on stock.picking and stock.move"""
if not column_exists(cr, "stock_move", "volume"):
create_column(cr, "stock_move", "volume", "numeric")
# First we compute the reserved qty by move_id
# the reserved qty is the sum of the reserved qty of the move lines
# linked to the move
# Then we update the volume of the moves not in state done or cancel
# If the move is in state partially available, or assigned, the volume
# is the reserved qty * the product volume
# else the volume is the move quantity * the product volume
cr.execute(
"""
with reserved_qty_by_move as (
select
move_id,
product_id,
sum(product_qty) as product_qty
from stock_move_line
group by move_id, product_id
)
update stock_move
set volume =
CASE
WHEN state in ('partially_available', 'assigned') THEN
product_qty * pp.volume
ELSE
product_uom_qty * pp.volume
END
from reserved_qty_by_move
join product_product pp on pp.id = product_id
where
stock_move.id = reserved_qty_by_move.move_id
and state not in ('done', 'cancel')
"""
)
_logger.info(f"{cr.rowcount} rows updated in stock_move")
if not column_exists(cr, "stock_picking", "volume"):
create_column(cr, "stock_picking", "volume", "numeric")
# we recompute the volume of the pickings not in state done or cancel
# the volume is the sum of the volume of the moves linked to the picking
# that are not in state done or cancel
cr.execute(
"""
update stock_picking
set volume = (
select sum(volume)
from stock_move
where
stock_move.picking_id = stock_picking.id
and state not in ('done', 'cancel')
)
where state not in ('done', 'cancel')
"""
)
_logger.info(f"{cr.rowcount} rows updated in stock_picking")