P-06 · Internal review & override approvals
SOP:
Payroll_Processing.md§6 / Step 4.0 (S7 → S8)Actors: Payroll Executive (PE) for review; Payroll Operations Lead (POL) for overrides. SoD control: PE must not self-approve overrides. Pre-state: Cycle inREADY_FOR_INTERNAL_REVIEW. Post-state: All mandatory gate conditions are either green or have a recorded override; cycle ready for export.
This step is mostly procedural — most of its enforcement is automatic via the validation pipeline. The user-facing surface is the cycle detail page's review checklist plus the issue-resolution dialogs.
0. Prerequisites
- Validation has cleared blocking rules (P-04).
- Cycle in
READY_FOR_INTERNAL_REVIEW.
1. Steps
1.1 Walk the readiness checklist (PE)
On /dashboard/cycles/<id>, the Readiness tab shows:
| Gate | What PE checks |
|---|---|
| Blocking errors resolved | Issues tab is empty (status = OPEN filter returns 0 rows) |
| Medium-confidence extractions confirmed | Each ExtractedField with 0.80 ≤ confidence < 0.95 shows confirmed_at set on the form |
| Major variance flags identified | Compare current submission totals to the seeded prior-cycle baseline; flag any > X% delta (configurable per client) |
| IR21 tasks created where required | For every foreign leaver, an IR21-kind file or override is present |
| CPF ceiling risk flags reviewed | The validation result for CPF_CEILING_RISK is acknowledged (warning-only by default) |
1.2 Resolve issues if needed
If a WorkflowIssue is still open (e.g. you intentionally left a duplicate-receipt warning), click Resolve on the row. The dialog asks for a reason; the underlying call is:
POST /ops/cycles/<id>/issues/<issueId>/resolve
Authorization: Bearer <staff-jwt>
{ "override": false, "reason": "Duplicate is the same purchase split across two receipts." }For an override (e.g. proceed without IR21 because the client confirmed in writing the IR21 was already filed externally), POL must do it:
POST /ops/cycles/<id>/issues/<issueId>/resolve
Authorization: Bearer <pol-jwt>
{ "override": true, "reason": "IR21 filed externally by client tax agent — confirmed via email 2026-04-23." }The handler enforces Action.OVERRIDE_ISSUE (only PAYROLL_LEAD or PLATFORM_ADMIN).
1.3 Mark Ready for Export
Once everything is clean, clicking Mark Ready for Export on the cycle header transitions the cycle READY_FOR_INTERNAL_REVIEW → READY_FOR_EXPORT.
Note: under the canonical path you can skip this manual click — Generate Export (P-07) will do it implicitly when validation passes.
2. Verification
Database
SELECT issue_id, resolution_kind, reason, resolved_by, resolved_at
FROM workflow_issue_resolutions WHERE cycle_id = '<cycleId>';
-- expect resolution_kind ∈ ('RESOLVED', 'OVERRIDDEN')
SELECT status FROM payroll_cycles WHERE id = '<cycleId>';
-- READY_FOR_EXPORTAudit log
| Event | Notes |
|---|---|
issue.resolved | per resolve click |
issue.overridden | per override click; carries actor (must be POL) and reason |
cycle.marked_ready_for_export | implicit transition |
3. Negative & edge cases
- PE attempts an override → 403
"OVERRIDE_ISSUE requires PAYROLL_LEAD or PLATFORM_ADMIN."SoD enforcement. - Resolve without a reason → 400
"Reason is required." - Cycle already past
READY_FOR_EXPORT→ 409"Issue cannot be resolved on a cycle past export."Open a revision round instead (P-10 revision branch). - Attempt to mark ready while issues remain → 400 with the open issue ids. The button is hidden in the UI when issues are open.
Next
Proceed to P-07 · Generate Infotech export.