fix(contract-review): WO step routes to QA-005 + auto-stage on part create

Two bugs fixed in one drop, both targeting the contract review (QA-005)
enforcement gap reported on entech.

## Bug 1 — WO step routed to wrong wizard

Symptom: clicking Finish & Next or Record on a Contract Review step in
WH/JOB/00339 opened the generic measurement wizard with three fake
prompts (Reviewer Initials / Date Reviewed / QA-005 Approved). No path
to the actual QA-005 form from the work order.

Root cause: action_finish_and_advance + action_open_input_wizard had no
branch for recipe_node.default_kind == 'contract_review'. The step.kind
mapping collapses contract_review -> 'other' so kind-based detection
wouldn't have worked either; gate has to live at the recipe-node layer.

Fix in fusion_plating_jobs/models/fp_job_step.py (v19.0.8.14.6):
- action_finish_and_advance:329 calls _fp_contract_review_redirect
  before the input-wizard branch
- action_open_input_wizard:844 same gate, keeps Record button consistent
- _fp_contract_review_redirect:866 (new) returns the part's
  action_start_contract_review() unless review.state in
  (complete, dismissed) — gate clears so the step can finish after
  the operator signs QA-005.

## Bug 2 — Part create did not enforce contract review

Symptom: spec called for a banner-only UX. User wanted true automatic
enforcement on first part creation under an enforced customer.

Fix in fusion_plating_quality/models/fp_part_catalog.py (v19.0.4.10.0):
- @api.model_create_multi def create() override
- _fp_enforce_contract_review_on_create() helper auto-stages the
  fp.contract.review record AND surfaces three prominent reminders:
    1. Sticky bus.bus warning toast (top-right, doesn't auto-dismiss)
    2. mail.activity (To Do) on the part for the current user
    3. Smart button on the part form lights up (review now exists)
- Idempotent: skips parts that already carry a review id
- Soft-fails: bus or activity outage doesn't block part creation
- create()-only — write/update flows never re-trigger

Sub 4's existing info banner stays as a fourth surface.

## Tests

- fusion_plating_jobs/tests/test_fp_job_extensions.py:
  +TestContractReviewStepRouting (5 tests covering both routing methods,
  the complete/dismissed gate-clear, and non-CR step regression)
- fusion_plating_quality/tests/test_part_catalog_contract_review_enforcement.py
  (NEW): 9 tests covering auto-create, batch create, idempotency,
  activity surface, bus surface, write-must-not-retrigger, soft-fail.
- docs/superpowers/tests/2026-04-22-sub4-smoke.py: flipped the
  "no review yet" assertion to "review auto-created" to match new
  behavior. Sign-flow assertions unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-03 20:02:52 -04:00
parent 1da27ed6bf
commit ee80673579
8 changed files with 584 additions and 9 deletions

View File

@@ -40,19 +40,23 @@ part = Part.create({
})
part.invalidate_recordset()
assert part.x_fc_customer_requires_contract_review
assert part.x_fc_contract_review_banner_visible, 'banner should be visible'
assert not part.x_fc_contract_review_id
print('[OK] Banner visible on fresh part')
# v19.0.4.10.0 — create() now auto-stages the review when the customer
# has enforcement enabled, so the review record exists immediately and
# the banner correspondingly hides (banner = "no review yet"). The
# action_start_contract_review path remains valid for parts created
# before enforcement was enabled or via flows that bypass create().
assert part.x_fc_contract_review_id, 'review should be auto-created on create()'
print('[OK] Review auto-created on part create')
# ---- Start contract review → record created + state = assistant_review
# ---- Start contract review → opens the existing record ---------------
action = part.action_start_contract_review()
part.invalidate_recordset()
review = part.x_fc_contract_review_id
assert review, 'review should be created'
assert review, 'review should exist'
assert review.state == 'assistant_review'
assert review.customer_id == cust
assert review.part_number == 'SUB4-SMOKE-001'
print('[OK] Review created by action_start_contract_review')
print('[OK] action_start_contract_review opens the auto-created review')
# ---- Sign section 2.0 as admin (roster ok) -----------------------------
review.with_user(admin).action_sign_section_20()