Files
Odoo-Modules/fusion_plating/fusion_plating_receiving/migrations/19.0.3.9.0/post-migrate.py
gsinghpal 091f98e1f9 changes
2026-05-18 22:33:23 -04:00

90 lines
3.3 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
"""Backfill missing part metadata + received_qty on fp.receiving.line.
A bug in fp.receiving auto-create (now fixed in
fusion_plating_receiving/models/sale_order.py) read
``order.x_fc_part_catalog_id`` (the rarely-populated SO header field)
instead of ``line.x_fc_part_catalog_id`` (the authoritative per-line
field), leaving every auto-generated receiving line with an empty
``part_number`` and ``part_catalog_id``. Same auto-create also forgot
to prefill ``received_qty``.
This migration walks existing receiving records and rebuilds the line
metadata from the linked SO's order lines via position-based zip — only
when the receiving line count matches the SO line count (otherwise the
mapping isn't safe and we leave the record alone for manual review).
"""
import logging
_logger = logging.getLogger(__name__)
def migrate(cr, version):
# Find candidates: receiving lines with empty part_catalog_id AND
# empty part_number, scoped to receivings with a linked SO.
cr.execute("""
SELECT r.id AS receiving_id,
r.sale_order_id AS so_id,
array_agg(rl.id ORDER BY rl.id) AS line_ids
FROM fp_receiving r
JOIN fp_receiving_line rl ON rl.receiving_id = r.id
WHERE r.sale_order_id IS NOT NULL
AND (rl.part_catalog_id IS NULL
AND (rl.part_number IS NULL OR rl.part_number = ''))
GROUP BY r.id, r.sale_order_id
""")
candidates = cr.fetchall()
if not candidates:
_logger.info('Receiving line backfill: no candidates.')
return
fixed = 0
skipped = 0
for receiving_id, so_id, recv_line_ids in candidates:
# Pull the SO's order lines in stable order.
cr.execute("""
SELECT id, x_fc_part_catalog_id, product_uom_qty, name
FROM sale_order_line
WHERE order_id = %s
ORDER BY sequence, id
""", (so_id,))
so_lines = cr.fetchall()
if len(so_lines) != len(recv_line_ids):
# Mismatch — don't risk corrupting a non-trivial mapping.
skipped += 1
continue
# Receiving lines come ordered by id ascending (the create call
# in sale_order.py emits them in order_line order, so id-order
# = sequence-order on the SO side).
for recv_line_id, (sol_id, part_id, qty, name) in zip(
recv_line_ids, so_lines,
):
part_number = ''
if part_id:
cr.execute(
"SELECT part_number FROM fp_part_catalog WHERE id = %s",
(part_id,),
)
row = cr.fetchone()
part_number = (row and row[0]) or ''
cr.execute("""
UPDATE fp_receiving_line
SET part_catalog_id = %s,
part_number = %s,
received_qty = COALESCE(NULLIF(received_qty, 0),
%s)
WHERE id = %s
""", (
part_id or None,
part_number,
int(qty or 0),
recv_line_id,
))
fixed += 1
_logger.info(
'Receiving line backfill: fixed %d lines, skipped %d receivings '
'(line-count mismatch).', fixed, skipped,
)