feat(configurator): direct-order line shows effective Process alongside Treatment
User asked why the direct-order wizard only showed "Primary
Treatment" and not Process — aren't they the same? They're not,
but the distinction was invisible on the order line until now.
Mental model (preserved here to keep future decisions aligned with
the user's question):
* Primary Treatment (fp.coating.config) = "WHAT coating" (process
type, thickness range, spec reference — the contractual
deliverable).
* Process (fusion.plating.process.node tree) = "HOW we make it"
(the floor-level sequence of operations and steps that WO
generation turns into work).
Each coating carries a default process (recipe_id). Parts can
override that via the Process Composer, storing a part-scoped
clone (default_process_id on fp.part.catalog). Resolution:
part's composed process wins; coating default is the fallback.
Added a computed read-only `effective_process_id` field on
fp.direct.order.line that displays exactly what process will drive
WO generation for the line, plus a one-line `effective_process_source`
showing whether it came from the part ("customised") or the
coating ("default"). Both surfaced on the wizard list and form so
the estimator can verify before confirming the order.
No behaviour change — this is pure visibility. WO generation still
uses the same resolution chain it did before.
fusion_plating_configurator → 19.0.13.2.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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': """
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -106,6 +106,14 @@
|
||||
<field name="internal_description"
|
||||
optional="hide"/>
|
||||
<field name="coating_config_id"/>
|
||||
<field name="effective_process_id"
|
||||
string="Process"
|
||||
readonly="1"
|
||||
optional="show"/>
|
||||
<field name="effective_process_source"
|
||||
string="Process Source"
|
||||
readonly="1"
|
||||
optional="hide"/>
|
||||
<field name="thickness_id"
|
||||
options="{'no_create': True}"
|
||||
invisible="not coating_config_id"
|
||||
@@ -143,6 +151,13 @@
|
||||
<field name="coating_config_id"/>
|
||||
<field name="treatment_ids"
|
||||
widget="many2many_tags"/>
|
||||
<field name="effective_process_id"
|
||||
string="Effective Process"
|
||||
readonly="1"/>
|
||||
<field name="effective_process_source"
|
||||
string="Source"
|
||||
readonly="1"
|
||||
invisible="not effective_process_id"/>
|
||||
</group>
|
||||
<group string="Qty & Price">
|
||||
<field name="quote_id"
|
||||
|
||||
Reference in New Issue
Block a user