fix(jobs): make "In Progress" workflow milestone fire reliably
Two coupled fixes so the workflow bar shows "In Progress" when work
is actually underway, even on recipes without kind tagging:
B. Auto-promote fp.job.state on first step start.
fp.job.step.write hook detects step transitions to in_progress
and promotes parent job state from 'confirmed' → 'in_progress'.
Without this, fp.job.state never reached 'in_progress' anywhere
in the codebase, so the trigger_on_job_state='in_progress'
path was dead code.
C. Smarter trigger_first_step_started for untagged recipes.
For tagged recipes (any step has kind in wet/bake/mask/rack),
keep the strict kind-based check. For untagged recipes (all
steps kind='other' or similar), fall back to "any step in
in_progress/paused/done" so the milestone fires regardless of
recipe authoring quality.
Verified end-to-end on entech with untagged steps:
- confirmed → in_progress when first step starts
- workflow bar tracks at in_progress through the work
- workflow bar advances to done when all steps done/skipped
Recipe authoring still encouraged for full Received / Inspected
intermediate states (those keep their default_kind triggers).
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.20.3',
|
||||
'version': '19.0.8.20.4',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
||||
'author': 'Nexa Systems Inc.',
|
||||
|
||||
@@ -174,6 +174,18 @@ class FpJobStep(models.Model):
|
||||
'(state=%s) by %s.'
|
||||
)) % (step.name, old_name, new_name, step.state,
|
||||
self.env.user.name))
|
||||
|
||||
# Auto-promote parent job: confirmed → in_progress on first
|
||||
# step start. Without this, fp.job.state never reaches
|
||||
# 'in_progress' anywhere in the codebase, so the In Progress
|
||||
# workflow milestone (trigger_on_job_state='in_progress')
|
||||
# never fires.
|
||||
if vals.get('state') == 'in_progress':
|
||||
jobs_to_promote = self.mapped('job_id').filtered(
|
||||
lambda j: j.state == 'confirmed'
|
||||
)
|
||||
if jobs_to_promote:
|
||||
jobs_to_promote.write({'state': 'in_progress'})
|
||||
return result
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -227,18 +227,28 @@ class FpJobWorkflowState(models.Model):
|
||||
actual = order.get(job.state, -1)
|
||||
return required >= 0 and actual >= required
|
||||
|
||||
# Special trigger: first wet step started
|
||||
# Special trigger: first wet step started.
|
||||
# For tagged recipes (any step has kind in wet/bake/mask/rack),
|
||||
# use strict kind-based check. For untagged recipes (all steps
|
||||
# are kind='other'), fall back to "any step started" so the
|
||||
# milestone fires regardless of recipe authoring quality.
|
||||
if self.trigger_first_step_started:
|
||||
wet_kinds = ('wet', 'bake', 'mask', 'rack')
|
||||
production_started = any(
|
||||
s.state in ('in_progress', 'paused', 'done')
|
||||
and (s.kind in wet_kinds)
|
||||
for s in steps
|
||||
)
|
||||
if not production_started:
|
||||
return False
|
||||
# Production milestone — not blocked by quality hold here
|
||||
return True
|
||||
has_kind_tagging = any(s.kind in wet_kinds for s in steps)
|
||||
if has_kind_tagging:
|
||||
production_started = any(
|
||||
s.state in ('in_progress', 'paused', 'done')
|
||||
and (s.kind in wet_kinds)
|
||||
for s in steps
|
||||
)
|
||||
else:
|
||||
# Untagged recipe — any started step counts as
|
||||
# "production has started".
|
||||
production_started = any(
|
||||
s.state in ('in_progress', 'paused', 'done')
|
||||
for s in steps
|
||||
)
|
||||
return production_started
|
||||
|
||||
# Standard trigger: ALL recipe steps matching the trigger
|
||||
# (default_kind in our list OR per-node override pointing at
|
||||
|
||||
Reference in New Issue
Block a user