From 7d5c826f3e9688cee46815c84a926cd448ab4b56 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 22 Apr 2026 08:52:10 -0400 Subject: [PATCH] fix(plating): Sub 3 \u2014 move part_catalog_id/cloned_from_id/treatment_uom to configurator inherit (core can't reference fp.part.catalog) --- .../fusion_plating/models/fp_process_node.py | 35 +++---------------- .../models/fp_process_node.py | 34 ++++++++++++++++-- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/fusion_plating/fusion_plating/models/fp_process_node.py b/fusion_plating/fusion_plating/models/fp_process_node.py index d51d745c..52a8ee7f 100644 --- a/fusion_plating/fusion_plating/models/fp_process_node.py +++ b/fusion_plating/fusion_plating/models/fp_process_node.py @@ -201,36 +201,11 @@ class FpProcessNode(models.Model): # ---- Part ownership & provenance (Sub 3) -------------------------------- - # Sub 3 — part ownership. NULL on shared templates (admin-managed); - # populated on every node in a part's cloned tree. - part_catalog_id = fields.Many2one( - 'fp.part.catalog', - string='Part', - ondelete='cascade', - index=True, - help='Populated on nodes that belong to a specific part\'s ' - 'composed process tree. NULL on shared templates.', - ) - # Sub 3 — source-template reference on cloned nodes. Enables - # future "template drifted" indicators. Optional, not load-bearing. - cloned_from_id = fields.Many2one( - 'fusion.plating.process.node', - string='Cloned From', - ondelete='set null', - help='On a part-cloned node, points back at the source template ' - 'node it was copied from.', - ) - # Sub 3 — per-node treatment UoM for pricing / cost tracking. - treatment_uom = fields.Selection( - [ - ('lbs', 'Lbs (weight-based)'), - ('sq_in', 'Sq in (area-based)'), - ], - string='Treatment UoM', - help='How this process step is measured for costing / pricing. ' - 'Picks which physical property of the part to multiply by ' - 'the per-unit rate: weight (Lbs) or surface area (Sq in).', - ) + # Sub 3 fields (part_catalog_id, cloned_from_id, treatment_uom) are + # declared as an inherit in fusion_plating_configurator — they need + # to reference fp.part.catalog, which lives in configurator (a child + # module). Adding them here would create a circular dependency. + # See fusion_plating_configurator/models/fp_process_node_inherit.py. # ---- Recipe-only fields (apply when node_type='recipe') ----------------- # These migrate Steelhead's recipe-level metadata: lead time, the diff --git a/fusion_plating/fusion_plating_configurator/models/fp_process_node.py b/fusion_plating/fusion_plating_configurator/models/fp_process_node.py index f9d6bf4c..6666969d 100644 --- a/fusion_plating/fusion_plating_configurator/models/fp_process_node.py +++ b/fusion_plating/fusion_plating_configurator/models/fp_process_node.py @@ -2,10 +2,12 @@ # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # Part of the Fusion Plating product family. -"""Add the configurator-side `pricing_rule_ids` field to process nodes. +"""Configurator-side extensions to fusion.plating.process.node. Lives here (not in core fusion_plating) so the core module doesn't have -to depend on the configurator. +to depend on the configurator. Any field that references a model defined +in configurator — like fp.pricing.rule, fp.part.catalog — must be +declared here. """ from odoo import fields, models @@ -13,6 +15,7 @@ from odoo import fields, models class FpProcessNode(models.Model): _inherit = 'fusion.plating.process.node' + # ---- Existing: pricing rule linkage (Steelhead "Use Price Builders") ---- pricing_rule_ids = fields.Many2many( 'fp.pricing.rule', relation='fp_process_node_pricing_rule_rel', @@ -22,3 +25,30 @@ class FpProcessNode(models.Model): help='Pricing rules to apply when this recipe is selected on a ' 'quotation (mirrors Steelhead "Use Price Builders").', ) + + # ---- Sub 3: part ownership + template reference + treatment UoM -------- + part_catalog_id = fields.Many2one( + 'fp.part.catalog', + string='Part', + ondelete='cascade', + index=True, + help='Populated on nodes that belong to a specific part\'s ' + 'composed process tree. NULL on shared templates.', + ) + cloned_from_id = fields.Many2one( + 'fusion.plating.process.node', + string='Cloned From', + ondelete='set null', + help='On a part-cloned node, points back at the source template ' + 'node it was copied from.', + ) + treatment_uom = fields.Selection( + [ + ('lbs', 'Lbs (weight-based)'), + ('sq_in', 'Sq in (area-based)'), + ], + string='Treatment UoM', + help='How this process step is measured for costing / pricing. ' + 'Picks which physical property of the part to multiply by ' + 'the per-unit rate: weight (Lbs) or surface area (Sq in).', + )