diff --git a/fusion_plating/fusion_plating_jobs/__manifest__.py b/fusion_plating/fusion_plating_jobs/__manifest__.py index a415b7b1..f6e6bba1 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.17.0', + 'version': '19.0.8.17.1', '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 5a4ccbe1..e700757c 100644 --- a/fusion_plating/fusion_plating_jobs/models/fp_job_step.py +++ b/fusion_plating/fusion_plating_jobs/models/fp_job_step.py @@ -148,6 +148,20 @@ class FpJobStep(models.Model): 'so': so.name or '', 'status': recv or 'unknown', }) + + # Sub 12e v4 — when an operator starts a contract_review step, + # immediately route to the QA-005 form. The step stays + # in_progress in the background; the operator signs (or + # dismisses) the review on QA-005, navigates back to the job, + # then clicks Finish & Next to advance. This removes the + # earlier "click Start, then click Finish & Next, then maybe + # click Finish & Next again" friction. + # Single-record only — multi-record button_start (e.g. job + # bulk-start) shouldn't navigate. + if len(self) == 1: + cr_action = self._fp_contract_review_redirect() + if cr_action: + return cr_action return result def button_pause(self): diff --git a/fusion_plating/fusion_plating_jobs/tests/test_fp_job_extensions.py b/fusion_plating/fusion_plating_jobs/tests/test_fp_job_extensions.py index 1b5831e4..99e02ce7 100644 --- a/fusion_plating/fusion_plating_jobs/tests/test_fp_job_extensions.py +++ b/fusion_plating/fusion_plating_jobs/tests/test_fp_job_extensions.py @@ -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.