Skip to content

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 in READY_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:

GateWhat PE checks
Blocking errors resolvedIssues tab is empty (status = OPEN filter returns 0 rows)
Medium-confidence extractions confirmedEach ExtractedField with 0.80 ≤ confidence < 0.95 shows confirmed_at set on the form
Major variance flags identifiedCompare current submission totals to the seeded prior-cycle baseline; flag any > X% delta (configurable per client)
IR21 tasks created where requiredFor every foreign leaver, IRAS's clearance is recorded, or their final pay stays withheld (no override exists)
CPF ceiling risk flags reviewedSG.PAY.CPF_AW_CEILING shows not checked while no year-to-date wages are on file: check it in Infotech

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:

http
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. a repeated receipt the client confirms was two separate purchases), POL must do it:

http
POST /ops/cycles/<id>/issues/<issueId>/resolve
Authorization: Bearer <pol-jwt>

{ "override": true, "reasonCode": "Two separate taxi rides the same day — confirmed by the client by email 2026-04-23." }

The handler enforces Action.OVERRIDE_ISSUE (only PAYROLL_LEAD or PLATFORM_ADMIN). The override covers that one finding only (that claim line, document or change). The IR21 pay-withheld warning cannot be overridden: IRAS's clearance letter is the only release.

1.2a Confirm review (the validation sign-off) ​

The Payroll Executive signs validation with Confirm review (a Lead may too). The signer must name every open warning and give a reason. Each named warning is closed as ACKNOWLEDGED (reason ACCEPTED_AT_SIGN_OFF) by the signer: it is not an override, and the checklist says "Accepted at the validation sign-off by <name>". The IR21 warning stays open even when named. The full checklist the signer saw (every rule, its result and reasons) is kept on the sign-off's audit record. While a month a document opened waits for this step, the console says "Waiting for Confirm review."; if the signer declines, the issue reads "Confirm review was declined by <name>: …" (or "sent back for changes by <name>").

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 ​

sql
SELECT issue_id, resolution_kind, reason, resolved_by, resolved_at
  FROM workflow_issue_resolutions WHERE cycle_id = '<cycleId>';
-- expect resolution_kind ∈ ('RESOLVED', 'OVERRIDDEN', 'ACKNOWLEDGED')

SELECT status FROM payroll_cycles WHERE id = '<cycleId>';
-- READY_FOR_EXPORT

Audit log ​

EventNotes
issue.resolvedper resolve click
issue.overriddenper override click; carries actor (must be POL) and reason
cycle.marked_ready_for_exportimplicit 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.

Internal use only — BreezyCorp