feat(jobs): button_start auto-routes contract_review steps to QA-005
User feedback on WH/JOB/00341 (S00279 retest): clicking Start on
the Contract Review step changed state to in_progress but didn't
take them to QA-005. They had to then click Finish & Next twice
to land on the form — confusing flow.
Better UX: when an operator clicks Start on a step where
recipe_node.default_kind='contract_review', the step starts AND
the QA-005 form opens immediately. Operator signs/dismisses,
navigates back, hits Finish & Next once → step finishes + advances.
Implementation:
fp.job.step.button_start, after super() returns and the
receiving check runs, calls _fp_contract_review_redirect()
(existing helper). If it returns an action, return that
instead of the parent's result. Single-record only — bulk
button_start (job-level start-all) shouldn't navigate.
Helper logic unchanged — same gate matrix:
* recipe_node.default_kind == 'contract_review'
* job has part_catalog_id
* review state NOT in (complete, dismissed)
When review is already complete, the gate clears: button_start
returns the normal True so the operator can advance the step
without bouncing through QA-005 again.
Tests:
test_button_start_routes_cr_step_to_qa005 — start opens QA-005
test_button_start_does_not_route_when_review_complete — start
does NOT redirect once review is signed off
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -827,6 +827,47 @@ class TestContractReviewStepRouting(TransactionCase):
|
||||
% action,
|
||||
)
|
||||
|
||||
def test_button_start_routes_cr_step_to_qa005(self):
|
||||
"""Sub 12e v4 UX — clicking Start on a contract_review step
|
||||
should set state=in_progress AND immediately return the QA-005
|
||||
action so the operator lands on the form without needing to
|
||||
click Finish & Next."""
|
||||
# Use the setUp's CR step but reset state to 'ready' so we
|
||||
# can call button_start. Skip the predecessor gate since
|
||||
# there are no other steps in this minimal test job.
|
||||
self.step.state = 'ready'
|
||||
action = self.step.with_context(
|
||||
fp_skip_predecessor_check=True,
|
||||
).button_start()
|
||||
# State must transition
|
||||
self.assertEqual(self.step.state, 'in_progress')
|
||||
# And the action returned must be the QA-005 form
|
||||
self.assertTrue(
|
||||
self._is_contract_review_action(action),
|
||||
'button_start on a contract_review step must return the '
|
||||
'QA-005 action, got: %r' % action,
|
||||
)
|
||||
|
||||
def test_button_start_does_not_route_when_review_complete(self):
|
||||
"""If the QA-005 review is already complete, button_start
|
||||
on the CR step should NOT redirect — operator just starts
|
||||
the step normally and clicks Finish & Next when ready."""
|
||||
review = self.env['fp.contract.review'].create({
|
||||
'part_id': self.part.id,
|
||||
'state': 'complete',
|
||||
})
|
||||
self.part.x_fc_contract_review_id = review.id
|
||||
self.step.state = 'ready'
|
||||
action = self.step.with_context(
|
||||
fp_skip_predecessor_check=True,
|
||||
).button_start()
|
||||
self.assertEqual(self.step.state, 'in_progress')
|
||||
self.assertFalse(
|
||||
self._is_contract_review_action(action),
|
||||
'When review is complete, button_start must NOT redirect '
|
||||
'(the gate is closed). Got: %r' % action,
|
||||
)
|
||||
|
||||
|
||||
class TestSequentialEnforcement(TransactionCase):
|
||||
"""Sub 13 — recipe-level + per-step sequential enforcement.
|
||||
|
||||
Reference in New Issue
Block a user