This commit is contained in:
gsinghpal
2026-05-04 02:14:34 -04:00
parent 3cc393454d
commit 586f05d567
43 changed files with 3656 additions and 112 deletions

View File

@@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
"""19.0.18.13.0 — Backfill kind_id from legacy default_kind text values.
Sub 14b — `default_kind` was a Selection on fp.step.template and
fusion.plating.process.node. It is now a stored related Char that
reads from kind_id.code on a new fp.step.kind catalog.
When a Selection field is converted into a Many2one in code, Odoo's
ORM does NOT auto-migrate the data — the new column starts empty. This
script reads the (still-present) text values out of the OLD `default_kind`
column and points kind_id at the seeded fp.step.kind record whose code
matches.
Idempotent — running it twice is a no-op.
"""
import logging
_logger = logging.getLogger(__name__)
def migrate(cr, version):
"""Run by the Odoo migration framework on -u to 19.0.18.13.0."""
# ---- Build code → kind_id map from seeded data --------------------
cr.execute("SELECT id, code FROM fp_step_kind")
code_to_id = {code: kid for kid, code in cr.fetchall()}
if not code_to_id:
_logger.warning(
'19.0.18.13.0: fp_step_kind is empty — seed data did not '
'load before post-migrate. Skipping backfill.',
)
return
# ---- 1. fp.step.template.kind_id ----------------------------------
_backfill(
cr,
table='fp_step_template',
text_col='x_default_kind_legacy',
m2o_col='kind_id',
code_to_id=code_to_id,
)
# ---- 2. fusion.plating.process.node.kind_id -----------------------
_backfill(
cr,
table='fusion_plating_process_node',
text_col='x_default_kind_legacy',
m2o_col='kind_id',
code_to_id=code_to_id,
)
# ---- 3. Force recompute of stored related default_kind --------------
# Now that kind_id is populated, the related Char will read the right
# value on next access. Trigger an explicit recompute via SQL so the
# column reflects current state immediately (faster than waiting for
# ORM to do it lazily on each row).
for table in ('fp_step_template', 'fusion_plating_process_node'):
cr.execute(f"""
UPDATE {table} t
SET default_kind = k.code
FROM fp_step_kind k
WHERE t.kind_id = k.id
""")
_logger.info(
'19.0.18.13.0: synced default_kind from kind_id.code on '
'%s rows of %s', cr.rowcount, table,
)
def _backfill(cr, table, text_col, m2o_col, code_to_id):
"""Generic backfill helper. Reads `text_col` text values, updates
`m2o_col` per row using the supplied code→id lookup table.
"""
# Defensive — if either column is missing (fresh install, never had
# default_kind data) skip silently.
cr.execute("""
SELECT column_name FROM information_schema.columns
WHERE table_name = %s AND column_name IN (%s, %s)
""", (table, text_col, m2o_col))
cols = {row[0] for row in cr.fetchall()}
if text_col not in cols or m2o_col not in cols:
_logger.info(
'19.0.18.13.0: %s missing %s or %s, skipping backfill',
table, text_col, m2o_col,
)
return
# Pull every row with a non-null default_kind that doesn't yet have
# a kind_id — leaves manually-edited rows alone if migration is
# rerun.
cr.execute(f"""
SELECT id, {text_col} FROM {table}
WHERE {text_col} IS NOT NULL AND {m2o_col} IS NULL
""")
rows = cr.fetchall()
if not rows:
_logger.info(
'19.0.18.13.0: %s has no rows needing backfill', table,
)
return
updated = 0
skipped = 0
by_kind = {}
for rec_id, code in rows:
kid = code_to_id.get(code)
if not kid:
skipped += 1
continue
by_kind.setdefault(kid, []).append(rec_id)
for kid, ids in by_kind.items():
cr.execute(
f"UPDATE {table} SET {m2o_col} = %s WHERE id = ANY(%s)",
(kid, ids),
)
updated += len(ids)
_logger.info(
'19.0.18.13.0: backfilled %s.%s on %s rows (%s skipped — code '
'not found in fp_step_kind seed data)',
table, m2o_col, updated, skipped,
)

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
"""19.0.18.13.0 — Snapshot legacy default_kind values BEFORE the field
type change wipes them.
Sub 14b — `default_kind` was a Selection on fp.step.template and
fusion.plating.process.node. The new model code defines it as a
stored related Char (`related='kind_id.code', store=True`). On first
ORM access after upgrade, Odoo recomputes the stored related from
kind_id (which is NULL → wipes the column). We must snapshot the
original text values now, so post-migrate can read them and resolve
kind_id.
Idempotent — running it twice is a no-op (snapshot column gets
re-written with the same data).
"""
import logging
_logger = logging.getLogger(__name__)
def migrate(cr, version):
for table in ('fp_step_template', 'fusion_plating_process_node'):
_snapshot(cr, table)
def _snapshot(cr, table):
cr.execute("""
SELECT column_name FROM information_schema.columns
WHERE table_name = %s AND column_name = 'default_kind'
""", (table,))
if not cr.fetchone():
_logger.info(
'19.0.18.13.0/pre: %s has no default_kind column, skip',
table,
)
return
# Add the snapshot column if missing.
cr.execute(f"""
ALTER TABLE {table}
ADD COLUMN IF NOT EXISTS x_default_kind_legacy VARCHAR
""")
# Copy the live data.
cr.execute(f"""
UPDATE {table}
SET x_default_kind_legacy = default_kind
WHERE default_kind IS NOT NULL
""")
_logger.info(
'19.0.18.13.0/pre: snapshotted %s rows from %s.default_kind '
'to x_default_kind_legacy',
cr.rowcount, table,
)