diff --git a/fusion_plating/fusion_plating_configurator/__manifest__.py b/fusion_plating/fusion_plating_configurator/__manifest__.py index 71dffecc..3bb59aaf 100644 --- a/fusion_plating/fusion_plating_configurator/__manifest__.py +++ b/fusion_plating/fusion_plating_configurator/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Configurator', - 'version': '19.0.13.1.0', + 'version': '19.0.13.2.0', 'category': 'Manufacturing/Plating', 'summary': 'Quotation configurator with part catalog, coating configs, and formula-based pricing engine.', 'description': """ diff --git a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_line.py b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_line.py index 2876e019..1233e0ae 100644 --- a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_line.py +++ b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_line.py @@ -59,6 +59,47 @@ class FpDirectOrderLine(models.TransientModel): string='Additional Treatments', help='Extra pre/post treatments applied to this line.', ) + # Read-only preview of the process tree that WILL drive WO generation + # for this line. Resolution priority: + # 1. Part's composed process (fp.part.catalog.default_process_id) + # — a part-scoped customisation set via the Process Composer. + # 2. Primary Treatment's default recipe (fp.coating.config.recipe_id) + # — the shared template used if the part has no override. + # Shown so operators can see *what will run* before confirming the + # order. Treatment answers the "what coating"; process answers the + # "how" — they're distinct but coupled via the resolution chain. + effective_process_id = fields.Many2one( + 'fusion.plating.process.node', + string='Process', + compute='_compute_effective_process', + help='Process tree that will generate work orders for this line. ' + 'Uses the part-composed process if one exists, otherwise the ' + "primary treatment's default recipe.", + ) + effective_process_source = fields.Char( + compute='_compute_effective_process', + help='Tells the estimator whether the process comes from the ' + 'part (customised) or the coating (shared default).', + ) + + @api.depends('part_catalog_id.default_process_id', + 'coating_config_id.recipe_id') + def _compute_effective_process(self): + for rec in self: + part_proc = (rec.part_catalog_id.default_process_id + if rec.part_catalog_id else False) + if part_proc: + rec.effective_process_id = part_proc + rec.effective_process_source = 'Part (customised)' + continue + cc_proc = (rec.coating_config_id.recipe_id + if rec.coating_config_id else False) + if cc_proc: + rec.effective_process_id = cc_proc + rec.effective_process_source = 'Coating default' + continue + rec.effective_process_id = False + rec.effective_process_source = False # ---- Qty / price ---- quantity = fields.Integer(string='Qty', default=1, required=True) diff --git a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard_views.xml b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard_views.xml index b9884089..8b6da084 100644 --- a/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard_views.xml +++ b/fusion_plating/fusion_plating_configurator/wizard/fp_direct_order_wizard_views.xml @@ -106,6 +106,14 @@ + + + +