feat(promote-customer-spec): Phase A — recipe + spec foundation
- Add fp.recipe.thickness model (replaces fp.coating.thickness, scoped to recipe root)
- Add spec metadata + bake-relief fields to fusion.plating.process.node (recipe root):
phosphorus_level, thickness_min/max/uom, thickness_option_ids,
requires_bake_relief + bake_window_hours/temperature/duration
- Add recipe_ids M2M + print_on_cert to fusion.plating.customer.spec
- Add applicable_spec_ids reverse M2M as inherit in fusion_plating_quality
(avoids circular dep — core can't reference customer.spec which lives in quality)
- Surface new fields on recipe form ("Specification & Bake" notebook page)
- Surface recipe linkage on customer spec form
Pure additive. Foundation for Phases B-E.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -336,6 +336,68 @@ class FpProcessNode(models.Model):
|
||||
# NB. `pricing_rule_ids` lives in fusion_plating_configurator
|
||||
# (added there so this core module doesn't depend on the configurator).
|
||||
|
||||
# ---- Spec-derived metadata (recipe-root only — Promote Customer Spec) ----
|
||||
# These were on fp.coating.config (since retired). They describe the
|
||||
# PROCESS the recipe runs, not the customer-facing specification —
|
||||
# specs live on fusion.plating.customer.spec.
|
||||
phosphorus_level = fields.Selection(
|
||||
[('low_phos', 'Low Phosphorus (2-5%)'),
|
||||
('mid_phos', 'Mid Phosphorus (6-9%)'),
|
||||
('high_phos', 'High Phosphorus (10-13%)'),
|
||||
('na', 'N/A')],
|
||||
string='Phosphorus Level',
|
||||
default='na',
|
||||
help='EN-specific. Set to N/A for non-EN processes (chrome, '
|
||||
'anodize, black oxide). Drives certificate annotation and '
|
||||
'hydrogen-embrittlement risk assessment for bake-relief.',
|
||||
)
|
||||
thickness_min = fields.Float(string='Min Thickness', digits=(10, 4))
|
||||
thickness_max = fields.Float(string='Max Thickness', digits=(10, 4))
|
||||
thickness_uom = fields.Selection(
|
||||
[('mils', 'mils'), ('microns', 'microns'), ('inches', 'inches')],
|
||||
string='Thickness UoM', default='mils',
|
||||
)
|
||||
thickness_option_ids = fields.One2many(
|
||||
'fp.recipe.thickness',
|
||||
'recipe_id',
|
||||
string='Thickness Options',
|
||||
help='Discrete thickness values offered to the estimator on the '
|
||||
'order line for jobs running this recipe.',
|
||||
)
|
||||
|
||||
# ---- Bake relief — AMS 2759/9 hydrogen embrittlement (recipe root) ----
|
||||
requires_bake_relief = fields.Boolean(
|
||||
string='Requires Bake Relief',
|
||||
help='Hydrogen embrittlement relief bake required (high-strength '
|
||||
'steel ≥ HRC 31 in conjunction with this chemistry). When '
|
||||
'set, finishing the job auto-creates a bake-window record '
|
||||
'and blocks shipment until bake is complete.',
|
||||
)
|
||||
bake_window_hours = fields.Float(
|
||||
string='Bake Window (hours)', default=4.0,
|
||||
help='Maximum time between plate exit and bake start. Typical 4h '
|
||||
'per AMS 2759/9.',
|
||||
)
|
||||
bake_temperature = fields.Float(
|
||||
string='Bake Temperature', default=375.0,
|
||||
help='Relief bake temperature. Default 375 (°F per AMS 2759/9 for '
|
||||
'steel ≥ HRC 40).',
|
||||
)
|
||||
bake_temperature_uom = fields.Selection(
|
||||
[('F', '°F'), ('C', '°C')],
|
||||
string='Bake Temp Unit',
|
||||
default='F',
|
||||
)
|
||||
bake_duration_hours = fields.Float(
|
||||
string='Bake Duration (hours)', default=23.0,
|
||||
help='Minimum bake hold time at temperature. Typical 23h.',
|
||||
)
|
||||
|
||||
# NB. `applicable_spec_ids` (reverse of customer.spec.recipe_ids) is
|
||||
# defined as an inherit in fusion_plating_quality (the module that
|
||||
# owns fusion.plating.customer.spec). Core can't reference it
|
||||
# directly without a dependency inversion.
|
||||
|
||||
# ---- Computed fields -----------------------------------------------------
|
||||
|
||||
display_name = fields.Char(
|
||||
|
||||
Reference in New Issue
Block a user