Removes the `description` field from `fp.sale.description.template` now that all readers (reports, wizard, sale line) consume the new `internal_description` + `customer_facing_description` pair. - Model: drop `description = fields.Text(...)` declaration - Migration 19.0.9.0.0 Step 6: `ALTER TABLE ... DROP COLUMN IF EXISTS description` - Template form/search views: swap `description` for the two new fields - Seed data: write new fields instead of legacy column (dupes old text into both) - Direct-order wizard: remove `tpl.description` fallback in both onchange handlers Entech column dropped via Odoo's auto-schema-sync during module upgrade (migration step is for fresh installs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1
|
|
# Sub 2 — Part Data Model Overhaul. Runs on upgrade from < 19.0.9.0.0.
|
|
# Idempotent (NULL / empty guards). Safe to re-run.
|
|
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
def migrate(cr, version):
|
|
if not version:
|
|
return # Fresh install — nothing to migrate
|
|
|
|
_logger.info("Sub 2: starting part-data-model migration to %s", version)
|
|
|
|
# Step 1: Backfill part_number from name where empty
|
|
cr.execute("""
|
|
UPDATE fp_part_catalog
|
|
SET part_number = name
|
|
WHERE part_number IS NULL OR part_number = ''
|
|
""")
|
|
_logger.info("Sub 2: backfilled part_number on %d records", cr.rowcount)
|
|
|
|
# Step 2: Backfill revision with 'A' where empty
|
|
cr.execute("""
|
|
UPDATE fp_part_catalog
|
|
SET revision = 'A'
|
|
WHERE revision IS NULL OR revision = ''
|
|
""")
|
|
_logger.info("Sub 2: backfilled revision on %d records", cr.rowcount)
|
|
|
|
# Step 3: Split fp_sale_description_template.description into two columns
|
|
# Copy existing description into BOTH internal_description and
|
|
# customer_facing_description. Estimators split them later.
|
|
cr.execute("""
|
|
UPDATE fp_sale_description_template
|
|
SET internal_description = description,
|
|
customer_facing_description = description
|
|
WHERE description IS NOT NULL
|
|
AND description <> ''
|
|
AND (internal_description IS NULL OR internal_description = '')
|
|
""")
|
|
_logger.info(
|
|
"Sub 2: duplicated description into new columns on %d template rows",
|
|
cr.rowcount,
|
|
)
|
|
|
|
# Step 4: Backfill x_fc_internal_description on sale.order.line
|
|
# Copy the existing `name` (Odoo's line description) into internal so
|
|
# historical lines satisfy the required-field check when it flips.
|
|
cr.execute("""
|
|
UPDATE sale_order_line
|
|
SET x_fc_internal_description = name
|
|
WHERE x_fc_internal_description IS NULL OR x_fc_internal_description = ''
|
|
""")
|
|
_logger.info(
|
|
"Sub 2: backfilled x_fc_internal_description on %d SO lines",
|
|
cr.rowcount,
|
|
)
|
|
|
|
# Step 5: Default certificate_requirement to 'inherit' on any rows
|
|
# where it's NULL (shouldn't happen given Odoo default=, but defensive).
|
|
cr.execute("""
|
|
UPDATE fp_part_catalog
|
|
SET certificate_requirement = 'inherit'
|
|
WHERE certificate_requirement IS NULL
|
|
""")
|
|
_logger.info(
|
|
"Sub 2: defaulted certificate_requirement to 'inherit' on %d parts",
|
|
cr.rowcount,
|
|
)
|
|
|
|
# Step 6: Drop legacy description column (all reads migrated to new fields).
|
|
# Runs after Steps 3 duplicated data into internal_description +
|
|
# customer_facing_description. Idempotent via IF EXISTS.
|
|
cr.execute("""
|
|
ALTER TABLE fp_sale_description_template
|
|
DROP COLUMN IF EXISTS description
|
|
""")
|
|
_logger.info("Sub 2: dropped legacy description column")
|
|
|
|
_logger.info("Sub 2: migration complete")
|