From 8d082cd9cc41048d23fcae904ce8836622fa4896 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 12 May 2026 00:27:05 -0400 Subject: [PATCH] fix(jobs): make "In Progress" workflow milestone fire reliably MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../fusion_plating_jobs/__manifest__.py | 2 +- .../fusion_plating_jobs/models/fp_job_step.py | 12 ++++++++ .../models/fp_job_workflow_state.py | 30 ++++++++++++------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/fusion_plating/fusion_plating_jobs/__manifest__.py b/fusion_plating/fusion_plating_jobs/__manifest__.py index 1600cdd0..1c0fb325 100644 --- a/fusion_plating/fusion_plating_jobs/__manifest__.py +++ b/fusion_plating/fusion_plating_jobs/__manifest__.py @@ -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.', diff --git a/fusion_plating/fusion_plating_jobs/models/fp_job_step.py b/fusion_plating/fusion_plating_jobs/models/fp_job_step.py index 5eee6827..e5b212f3 100644 --- a/fusion_plating/fusion_plating_jobs/models/fp_job_step.py +++ b/fusion_plating/fusion_plating_jobs/models/fp_job_step.py @@ -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 diff --git a/fusion_plating/fusion_plating_jobs/models/fp_job_workflow_state.py b/fusion_plating/fusion_plating_jobs/models/fp_job_workflow_state.py index e00d0a86..e9e73133 100644 --- a/fusion_plating/fusion_plating_jobs/models/fp_job_workflow_state.py +++ b/fusion_plating/fusion_plating_jobs/models/fp_job_workflow_state.py @@ -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