fix(operator-wizard): surface office-authored instructions to operators
Critical UX gap discovered in production-environment battle test: when operator hits "Mark Done" and the input wizard fires, they only saw the measurement prompts list. The rich-text instructions written by the office (recipe_node.description) never reached the operator at the exact moment they need them. Fixed: wizard model gains instructions (Html, computed from step.recipe_node_id.description) + has_instructions flag. Form view renders the instructions in a prominent blue alert at the top of the wizard, above the Measurements list. Hidden when blank so operators on instruction-less steps don't see noise. Also: extend default_kind Selection on fusion.plating.process.node to match fp.step.template — both models now have the same 24 kinds. Without this, recipe authors could pick a kind in the library template form that the recipe-node Selection rejected with a ValueError. Battle test artifact: - Recipe "Hard Anodize Type III + Dye + Seal" (id=1863) — 23 steps, 105 measurement prompts, rich-text operator instructions per step - SO S00278 for ABC Manufactoring confirmed → fp.job 1236 / WH/JOB/00337 with all 23 steps materialized, 105 prompts visible to operators - Wizard test: step "11. Hard Anodize Type III" → 516 chars of instructions render + 7 input prompts in the form Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
{
|
||||
'name': 'Fusion Plating — Native Jobs',
|
||||
'version': '19.0.8.12.0',
|
||||
'version': '19.0.8.13.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
||||
'author': 'Nexa Systems Inc.',
|
||||
|
||||
@@ -59,11 +59,31 @@ class FpJobStepInputWizard(models.TransientModel):
|
||||
job_id = fields.Many2one(
|
||||
related='step_id.job_id', string='Job', store=False, readonly=True,
|
||||
)
|
||||
# Sub 12d — surface the office-authored instructions to the operator
|
||||
# at the exact moment they're recording values. Sourced from the
|
||||
# recipe node's description (rich-text); empty when the recipe
|
||||
# author left it blank.
|
||||
instructions = fields.Html(
|
||||
string='Operator Instructions',
|
||||
compute='_compute_instructions',
|
||||
readonly=True,
|
||||
)
|
||||
has_instructions = fields.Boolean(
|
||||
compute='_compute_instructions',
|
||||
)
|
||||
line_ids = fields.One2many(
|
||||
'fp.job.step.input.wizard.line', 'wizard_id',
|
||||
string='Inputs',
|
||||
)
|
||||
|
||||
@api.depends('step_id', 'step_id.recipe_node_id', 'step_id.recipe_node_id.description')
|
||||
def _compute_instructions(self):
|
||||
for rec in self:
|
||||
node = rec.step_id.recipe_node_id if rec.step_id else False
|
||||
html = (node and node.description) or ''
|
||||
rec.instructions = html
|
||||
rec.has_instructions = bool(html and html.strip())
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
defaults = super().default_get(fields_list)
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
<field name="step_id" readonly="1"/>
|
||||
<field name="job_id" readonly="1"/>
|
||||
</group>
|
||||
<field name="has_instructions" invisible="1"/>
|
||||
<div class="alert alert-info"
|
||||
role="alert"
|
||||
invisible="not has_instructions"
|
||||
style="margin-bottom: 12px;">
|
||||
<h4 style="margin-top: 0;">
|
||||
<i class="fa fa-info-circle"/>
|
||||
Instructions for this step
|
||||
</h4>
|
||||
<field name="instructions" nolabel="1" readonly="1"/>
|
||||
</div>
|
||||
<separator string="Measurements"/>
|
||||
<p class="text-muted" invisible="line_ids">
|
||||
Click <strong>Add a line</strong> to record one or
|
||||
|
||||
Reference in New Issue
Block a user