feat(workspace): per-kind step action buttons in Job Workspace

Fix: in the Job Workspace tablet view, the Start button was buried
inside a parent t-if that required the step to already be in_progress
or blocked. So ready/paused steps showed no buttons at all -
operators couldn't advance the WO from this screen (the reason the
user couldn't complete anything on WO-30057).

Template restructure (job_workspace.xml):
- Always-visible line 1 (icon + step# + name + ACTIVE/PAUSED badge + meta)
- Non-terminal detail panel (chips + instructions + opt-out + GateViz)
  visible on every non-done step so operator reads ahead
- Action row dispatched per-kind via getStepActions() helper

Per-kind action dispatcher (job_workspace.js):
- in_progress -> Record Inputs, Pause, Finish (or Finish & Sign Off)
- paused      -> Resume, Record Inputs, Finish
- contract_review (ready) -> Open QA-005 Form
- gating (ready)          -> Mark Passed (1-click start+finish)
- requires_rack_assignment -> Start (Assign Rack) - opens FpRackPartsDialog
- else (ready)            -> Start

5 new handlers: onPauseStep / onResumeStep / onMarkPassed /
onOpenContractReview / onStartWithRack. Pause and Resume use ORM RPC
(button_pause/button_resume) since no HTTP endpoint exists.

New model method (fp.job.step.action_mark_gating_passed):
- 1-click pass for gating steps - does button_start + button_finish
  in one transaction, posts chatter "Gate X marked passed by Y"
- Raises UserError if called on a non-gating step (defensive)
- Bypasses S21 required-inputs gate (gating steps have no inputs)

Controller: workspace_controller.py adds requires_rack_assignment to
the step payload so the JS dispatcher can route correctly.

Spec: docs/superpowers/specs/2026-05-24-workspace-step-actions-design.md
Sub-B (Record Inputs tablet polish: inputmode/prefill/date pickers/
signature pad/camera) is brainstormed but deferred.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-24 18:38:22 -04:00
parent d4e95dcd47
commit 170398ab6f
7 changed files with 644 additions and 33 deletions

View File

@@ -1397,6 +1397,50 @@ class FpJobStep(models.Model):
},
}
def action_mark_gating_passed(self):
"""1-click pass for gating steps (kind=='gating').
Performs button_start (or button_resume if paused) followed by
button_finish in the same transaction. Posts a chatter audit on
the parent job naming the user.
Only valid for kind='gating' steps in state in (ready, pending,
paused). NOOPs on already-terminal steps for idempotency. Raises
UserError if called on a non-gating step (defensive — UI dispatcher
only renders Mark Passed for gating kinds).
Bypasses the S21 required-inputs gate (gating steps have no
required inputs by design — they're admin gates).
Spec: 2026-05-24-workspace-step-actions-design.md Change 5.
"""
for step in self:
if step.state in ('done', 'skipped', 'cancelled'):
continue
kind_code = (
step.recipe_node_id.kind_id.code
if step.recipe_node_id and step.recipe_node_id.kind_id
else None
)
if kind_code != 'gating':
raise UserError(_(
"Mark Passed is only valid for gating steps. "
"This step's kind is %s."
) % (kind_code or 'unknown'))
if step.state not in ('ready', 'pending', 'paused'):
continue
if step.state == 'paused':
step.button_resume()
if step.state != 'in_progress':
step.button_start()
step.with_context(
fp_skip_required_inputs_gate=True,
).button_finish()
step.job_id.message_post(body=_(
'Gate "%(name)s" marked passed by %(user)s.'
) % {'name': step.name, 'user': self.env.user.name})
return True
def _fp_contract_review_redirect(self):
"""Return an ir.actions.act_window opening the part's QA-005
Contract Review form, or False to indicate "no redirect needed".