# 21 — Phase 5 Checklist & Status

Working tracker for [13 — Implementation Plan, Phase 5](13-implementation-plan.md) —
accounts, credit & funding at the counter. Status date: **2026-08-05**.

---

## Exit criteria (doc 13)

| Criterion | Status | Evidence |
|---|---|---|
| An employee exhausts a cap mid-order and the excess settles **personally on one order** with correct slips | ✅ Automated | PWA drill: Ahmed, 5,000 cap, 12,000 order → `chargePlan` computes covered 5,000 + personal 7,000 (never asks); one order, `settlement_type: mixed`, company leg + cash leg; split slip carries covered/personal, **remaining cap 0** and balance-after (doc 04 §7) |
| An over-limit charge **blocks** and an override is **audited** | ✅ Automated | `balanceCheck.ok = false` with the excess shown; supervisor PIN → `credit_check: override`, `over_limit: 1`, `sale.credit_override` audit with the approver; lands on `/admin/reports/credit` |
| All of it works **offline as provisional** | ✅ Automated | D24: balance = pulled snapshot + local deltas (outbox-pending docs + docs newer than the snapshot); caps derive from local charges (exact at the single home terminal, doc 10 §9); `provisional` label on roaming accounts; the centre accepts, reconciles and flags — `SyncPipelineTest` proves charges/payments apply, re-log the account, and the next pull carries the refreshed snapshot |

Suites: **160 → 161 PHPUnit** (both dialects; +13-assertion accounts-pipeline test) and
**289 PWA assertions** including the drills above, policy walls (BLOCK /
ALLOW_WITH_APPROVAL / NOT_COVERED / on-hold / IMMEDIATE / wrong-branch / daily limit),
POS payment, credit-note refund, and the Z/blind-close reconciliation with account legs.

## Delivered

- **Master data** (migration 0005): `accounts` (doc 03 §3 — type, home branch,
  cross-branch flag, office_ref, parent link, funding policy, restricted flag, credit
  limit, full four-mode billing terms, hold states), `account_contacts`,
  `authorized_persons` (§6.2 — overrides, caps, periods, `on_cap_exceeded`,
  per-order/daily guards, signature flag), plus the AR ledger: `order_charges`
  (signed) and `account_payments`. Balances/caps **derived, never stored** (§3/§6.3).
- **Back office** `/admin/accounts`: create/edit with terms validation, funding policy,
  restricted/cross-branch flags; credit limit + hold/release gated by
  `account.set_credit_limit` (D27), audited; authorized-person management with live
  cap-consumed display; charge and payment history; live derived balance.
  `/admin/reports/credit`: over-limit accounts + provisional/override charges.
- **Sync** (contract [1.4.0](15-sync-contract.md)): pull entities `account`
  (+balance snapshot, D24) and `authorized_person`; `order.confirmed` charge legs
  extracted into `order_charges` (unknown account → quarantined `unknown_reference`);
  `payment.received` applied into `account_payments`; both re-log the account so
  devices refresh; rollups gain `on_account_iqd` / `account_payments_iqd`.
- **PWA counter flows**: Arabic-normalized account search (code / name / **office
  number** / person / phone — `ArabicText` + JS mirror, D26, vector-pinned);
  buyer chip with cap-remaining warning at selection (doc 03 §6.4 "warn before
  blocking"); the **computed split** settle flow (covered charged, only the personal
  remainder tendered; fully-covered orders confirm with zero extra taps); supervisor-PIN
  overrides for cap overage (ALLOW_WITH_APPROVAL) and over-limit, audited; charge/split
  slips with remaining-cap + balance-after + signature line; **repeat last order** at
  today's prices; **receive account payment** at the POS with sequential receipts
  (D28) — the cash enters the shift's expected count via an `account_payment`
  movement (doc 05 §5 rule 4, D25); refunds of charged orders become **credit
  notes** restoring balance and cap (doc 04 §6); Z-report carries on-account and
  payments-received lines.
- **Kernel/domain shared math**: `ArabicText` (D26) and `BillingPeriod` (D29 — the
  four billing modes' period grids, reused by Phase 6) with JS mirrors under D20
  parity vectors.

## Deferred, with reasons

| Item | Where it lands |
|---|---|
| Overdue-past-grace credit check (`has_invoice_overdue_beyond_grace`) | Phase 6 — invoices don't exist yet; the hold/auto-hold machinery is ready for it |
| Central payment entry, reversals, allocations, unapplied credit | Phase 6 payments/collections (doc 05 §5 rules 2–3, §6) |
| Statements, parent-account rollup billing | Phase 6 invoicing |
| `price_list_id` / standing `discount_pct` on accounts | Phase 10 corporate pricing (doc 02 §4) — columns not yet created, deliberately |
| Cap-warning threshold as config | Constant behaviour (remaining cap always shown at selection); config knob when a tenant asks |
| Digital signature capture | Printed slip carries the signature line (doc 03 §6.5); digital capture only if a tenant demands proof archival |
| Cashier charge-history lookup screen | Balance + last order already visible at selection; a full history screen with doc 03 §8 read-only scoping when requested |

## Notes for Phase 6

`BillingPeriod` (D29) is the cycle-grid authority — the billing run iterates accounts
by mode over these exact windows, so caps and invoices agree by construction.
`order_charges` (signed) + `account_payments` are the invoice inputs; `balance()` =
unbilled + invoiced − credits once invoices exist. `auto_hold_when_overdue`,
`due_days`, `grace_days` are already on every account. Billing must run **two full
cycles reconciled line-by-line against a manual spreadsheet** before being trusted
(doc 13's explicit instruction — the schedule risk of the whole project).
