feat(configurator): drop legacy description column after dual-field migration (Sub 2 Task 27)

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>
This commit is contained in:
gsinghpal
2026-04-21 23:27:22 -04:00
parent e3dcc1c381
commit 1eac630d87
5 changed files with 45 additions and 28 deletions

View File

@@ -7,6 +7,10 @@
Eight starter description templates covering the common things
estimators write on SO lines. noupdate="1" so customers can edit
freely without upgrades clobbering their changes.
Sub 2 (Task 27): legacy `description` field dropped. Seed data now
sets `internal_description` + `customer_facing_description` with the
same text — estimators split them over time as needed.
-->
<odoo noupdate="1">
@@ -14,56 +18,64 @@
<field name="name">ENP — Standard (AMS 2404 Class I)</field>
<field name="tag">standard</field>
<field name="sequence">10</field>
<field name="description">Electroless nickel plating per AMS 2404, Class I, Type II (medium phosphorus, 69%). Plate to 0.0005" thickness, heat-treat 4 hours @ 375°F for hydrogen embrittlement relief. Parts to be cleaned, deoxidised and activated prior to plating. All threaded holes &amp; tapped features to remain unplated.</field>
<field name="internal_description">Electroless nickel plating per AMS 2404, Class I, Type II (medium phosphorus, 69%). Plate to 0.0005" thickness, heat-treat 4 hours @ 375°F for hydrogen embrittlement relief. Parts to be cleaned, deoxidised and activated prior to plating. All threaded holes &amp; tapped features to remain unplated.</field>
<field name="customer_facing_description">Electroless nickel plating per AMS 2404, Class I, Type II (medium phosphorus, 69%). Plate to 0.0005" thickness, heat-treat 4 hours @ 375°F for hydrogen embrittlement relief. Parts to be cleaned, deoxidised and activated prior to plating. All threaded holes &amp; tapped features to remain unplated.</field>
</record>
<record id="desc_tpl_enp_aerospace" model="fp.sale.description.template">
<field name="name">ENP — Aerospace (AMS 2404 w/ CoC)</field>
<field name="tag">aerospace</field>
<field name="sequence">20</field>
<field name="description">Electroless nickel plating per AMS 2404, Class I, Type II, Grade A. Plate to customer-specified thickness. Post-bake 4 hours @ 375°F min. Certificate of Conformance and thickness readings (3 points minimum per lot) required. Traceability to raw material heat lot. Nadcap-accredited process.</field>
<field name="internal_description">Electroless nickel plating per AMS 2404, Class I, Type II, Grade A. Plate to customer-specified thickness. Post-bake 4 hours @ 375°F min. Certificate of Conformance and thickness readings (3 points minimum per lot) required. Traceability to raw material heat lot. Nadcap-accredited process.</field>
<field name="customer_facing_description">Electroless nickel plating per AMS 2404, Class I, Type II, Grade A. Plate to customer-specified thickness. Post-bake 4 hours @ 375°F min. Certificate of Conformance and thickness readings (3 points minimum per lot) required. Traceability to raw material heat lot. Nadcap-accredited process.</field>
</record>
<record id="desc_tpl_enp_nuclear" model="fp.sale.description.template">
<field name="name">ENP — Nuclear (CSA N299 / 10CFR50 App B)</field>
<field name="tag">nuclear</field>
<field name="sequence">25</field>
<field name="description">Electroless nickel plating under CSA N299 / 10CFR50 Appendix B quality program. Full material traceability, dedicated tooling, independent QA inspection. Certificate package includes thickness, adhesion tape test, visual inspection sign-off, and chemistry log for the processing shift.</field>
<field name="internal_description">Electroless nickel plating under CSA N299 / 10CFR50 Appendix B quality program. Full material traceability, dedicated tooling, independent QA inspection. Certificate package includes thickness, adhesion tape test, visual inspection sign-off, and chemistry log for the processing shift.</field>
<field name="customer_facing_description">Electroless nickel plating under CSA N299 / 10CFR50 Appendix B quality program. Full material traceability, dedicated tooling, independent QA inspection. Certificate package includes thickness, adhesion tape test, visual inspection sign-off, and chemistry log for the processing shift.</field>
</record>
<record id="desc_tpl_masking_threaded" model="fp.sale.description.template">
<field name="name">Masking — Threaded &amp; Tapped Features</field>
<field name="tag">masking</field>
<field name="sequence">30</field>
<field name="description">Selective plating. Mask all threaded holes, tapped features and mating surfaces per customer drawing. Non-plated areas to be free of residue. Remove masking prior to shipment. Any masking residue is cause for rejection.</field>
<field name="internal_description">Selective plating. Mask all threaded holes, tapped features and mating surfaces per customer drawing. Non-plated areas to be free of residue. Remove masking prior to shipment. Any masking residue is cause for rejection.</field>
<field name="customer_facing_description">Selective plating. Mask all threaded holes, tapped features and mating surfaces per customer drawing. Non-plated areas to be free of residue. Remove masking prior to shipment. Any masking residue is cause for rejection.</field>
</record>
<record id="desc_tpl_masking_od" model="fp.sale.description.template">
<field name="name">Masking — Selective O.D. / Journals</field>
<field name="tag">masking</field>
<field name="sequence">35</field>
<field name="description">Plate O.D. and specified journal surfaces only. Mask all bore surfaces, end faces, and sealing surfaces. Maintain ±0.0001" on masked-feature edges. Rack holes to be plugged.</field>
<field name="internal_description">Plate O.D. and specified journal surfaces only. Mask all bore surfaces, end faces, and sealing surfaces. Maintain ±0.0001" on masked-feature edges. Rack holes to be plugged.</field>
<field name="customer_facing_description">Plate O.D. and specified journal surfaces only. Mask all bore surfaces, end faces, and sealing surfaces. Maintain ±0.0001" on masked-feature edges. Rack holes to be plugged.</field>
</record>
<record id="desc_tpl_rework_strip" model="fp.sale.description.template">
<field name="name">Rework — Strip &amp; Replate</field>
<field name="tag">rework</field>
<field name="sequence">40</field>
<field name="description">Rework of previously-plated parts. Chemically strip existing nickel deposit without attacking the base metal. Dimensional inspection after strip — any parts outside blueprint tolerance to be held for customer disposition. Replate to original spec. New Certificate of Conformance issued for the rework lot.</field>
<field name="internal_description">Rework of previously-plated parts. Chemically strip existing nickel deposit without attacking the base metal. Dimensional inspection after strip — any parts outside blueprint tolerance to be held for customer disposition. Replate to original spec. New Certificate of Conformance issued for the rework lot.</field>
<field name="customer_facing_description">Rework of previously-plated parts. Chemically strip existing nickel deposit without attacking the base metal. Dimensional inspection after strip — any parts outside blueprint tolerance to be held for customer disposition. Replate to original spec. New Certificate of Conformance issued for the rework lot.</field>
</record>
<record id="desc_tpl_packaging_individual" model="fp.sale.description.template">
<field name="name">Packaging — Individual Bag + Desiccant</field>
<field name="tag">packaging</field>
<field name="sequence">50</field>
<field name="description">Each part individually bagged in anti-static poly bag with desiccant pack. Bagged parts packed in cushioned cardboard cartons with corner protection. Outer carton labelled with part number, lot, quantity, and Entech W/O number. Do not ship open-top or mixed part-number cartons.</field>
<field name="internal_description">Each part individually bagged in anti-static poly bag with desiccant pack. Bagged parts packed in cushioned cardboard cartons with corner protection. Outer carton labelled with part number, lot, quantity, and Entech W/O number. Do not ship open-top or mixed part-number cartons.</field>
<field name="customer_facing_description">Each part individually bagged in anti-static poly bag with desiccant pack. Bagged parts packed in cushioned cardboard cartons with corner protection. Outer carton labelled with part number, lot, quantity, and Entech W/O number. Do not ship open-top or mixed part-number cartons.</field>
</record>
<record id="desc_tpl_hazmat_note" model="fp.sale.description.template">
<field name="name">Handling — Delicate / No Tumble</field>
<field name="tag">other</field>
<field name="sequence">60</field>
<field name="description">Delicate parts — rack plating only, no barrel. No tumbling or vibratory finishing before or after plating. Inspect for handling damage prior to final packaging. Any edge, surface or impact damage is cause for segregation.</field>
<field name="internal_description">Delicate parts — rack plating only, no barrel. No tumbling or vibratory finishing before or after plating. Inspect for handling damage prior to final packaging. Any edge, surface or impact damage is cause for segregation.</field>
<field name="customer_facing_description">Delicate parts — rack plating only, no barrel. No tumbling or vibratory finishing before or after plating. Inspect for handling damage prior to final packaging. Any edge, surface or impact damage is cause for segregation.</field>
</record>
</odoo>

View File

@@ -72,4 +72,13 @@ def migrate(cr, version):
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")

View File

@@ -30,14 +30,9 @@ class FpSaleDescriptionTemplate(models.Model):
string='Template Name', required=True,
help='Short name shown in the picker (e.g. "Standard masking", "With threaded holes masked").',
)
description = fields.Text(
string='Description', required=True,
help='Boilerplate text. The user can tweak this in the wizard before '
'it lands on the order line.',
)
# Sub 2 — dual descriptions. Added alongside the legacy `description`
# field; migration copies old value into both, then old column dropped
# in Phase C. Nullable during Phase A so existing records don't fail.
# Sub 2 — dual descriptions. Replaces the legacy `description` field
# (dropped in Phase C / Task 27). Migration Step 3 duplicated the old
# value into both columns; Step 6 drops the old column.
internal_description = fields.Text(
string='Internal Description',
required=True,

View File

@@ -54,8 +54,12 @@
<field name="active" widget="boolean_toggle"/>
</group>
</group>
<group string="Description">
<field name="description" nolabel="1" colspan="2"
<group string="Internal Description (Shop Floor Only)">
<field name="internal_description" nolabel="1" colspan="2"
placeholder="What the shop floor sees on the WO / traveler…"/>
</group>
<group string="Customer-Facing Description">
<field name="customer_facing_description" nolabel="1" colspan="2"
placeholder="Electroless nickel plating per AMS 2404, Class I, Type II…"/>
</group>
</sheet>
@@ -69,7 +73,8 @@
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="description"/>
<field name="internal_description"/>
<field name="customer_facing_description"/>
<field name="part_catalog_id"/>
<field name="coating_config_id"/>
<field name="partner_id"/>

View File

@@ -206,15 +206,12 @@ class FpDirectOrderLine(models.TransientModel):
Customer-facing text lands in `line_description` (ends up on the
SO line `name`, prints on customer docs). Internal text lands in
`internal_description` (ends up in x_fc_internal_description on
the SO line, prints on WO / traveler only). Falls back to the
legacy `description` field when the new dual fields are empty so
pre-Sub-2 templates keep working.
the SO line, prints on WO / traveler only).
"""
if self.description_template_id:
tpl = self.description_template_id
customer_text = tpl.customer_facing_description or tpl.description
if customer_text:
self.line_description = customer_text
if tpl.customer_facing_description:
self.line_description = tpl.customer_facing_description
if tpl.internal_description:
self.internal_description = tpl.internal_description
@@ -235,9 +232,8 @@ class FpDirectOrderLine(models.TransientModel):
def _apply(match):
self.description_template_id = match.id
customer_text = match.customer_facing_description or match.description
if customer_text:
self.line_description = customer_text
if match.customer_facing_description:
self.line_description = match.customer_facing_description
if match.internal_description:
self.internal_description = match.internal_description