chnages
This commit is contained in:
@@ -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,
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
Reference in New Issue
Block a user