# 23 — Phase 7 Checklist & Status

Working tracker for [13 — Implementation Plan, Phase 7](13-implementation-plan.md) —
multi-branch rollout & owner visibility. Status date: **2026-08-05**. Under
[D17](14-conventions.md) the rollout has no hardware leg: onboarding a branch is
registering a device, loading its master data, and installing the PWA.

---

## Exit criteria (doc 13)

| Criterion | Status | Evidence |
|---|---|---|
| The owner answers "how did Karbala do yesterday and why is it different from Basrah" **from the digest and dashboard alone** | ✅ Engineering | `digest:send` pushes the doc 09 §1 message every morning (Telegram first-class, webhook for WhatsApp gateways, always logged); `/admin/reports/branches` is the doc 09 §2 ranked five-branch table. `DigestTest`: comparisons step over declared closures and state the day used; closure-day digests still send with the reason; a silent branch is flagged in the message |
| Every branch has passed a **recovery drill** | 🔲 **External, per branch** | Drill per doc 10 §9.1 / doc 20: revoke device → register new → install PWA → token → pull → resume. Run at each branch **before its go-live** |
| Staggered rollout branch-by-branch | 🔲 **External** | Protocol below |

## Delivered

- **Owner daily digest** (doc 13: "best value-to-effort item — ship first"): per-branch
  + consolidated sections — sales split paid/on-account, orders and average ticket,
  variance vs branch tolerance, voids/discounts, receivables + overdue, caps ≥90%;
  **trading-day-aware comparison** ("▲6% مقابل الثلاثاء 21-07") that skips declared
  closures and names the day used (doc 10 §3.1); **closure days still send** with the
  closure reason — silence is never ambiguous; **stale-branch flag** when a device has
  been silent (doc 09 §8); waste + low-stock lines light up automatically with the
  Phase 8 tables. Channels: Telegram (`DIGEST_TELEGRAM_*`), generic webhook
  (`DIGEST_WEBHOOK_URL` — a WhatsApp gateway plugs in here), and the `digests` log
  table; idempotent per (date, channel); re-send a specific day with
  `php cron/run.php digest:send YYYY-MM-DD`.
- **Branch comparison** `/admin/reports/branches` (doc 09 §2): ranked, best/worst
  highlighted — net + trend vs the previous equal period, orders, average ticket,
  void %, discount %, variance (total and per shift), on-account share, receivables +
  overdue % — margin/waste columns arrive with Phase 8, labour/rent with Phase 9.
- **Anti-fraud exception suite** `/admin/reports/fraud` (docs 06 §6, 09 §7), ranked
  across branches: variance by cashier with the zero-variance-always flag, voids /
  discounts / refunds / no-sale opens per cashier with % of own sales, **voids after
  READY**, **cash refunds against non-cash sales**, pay-outs with no document, and
  stale devices.
- **Cross-branch collection guard** (doc 05 §5 rule 1): the POS refuses payment for a
  home-only account at another branch and records roaming collections against the
  collecting branch's shift. Cross-branch charging, provisional credit labels, credit-
  exception reporting and stale-device alerting were already live (Phases 4–6).

## Rollout protocol (external, per branch — staggered, never all four at once)

1. Create the branch + building + calendar defaults; load its menu and prices.
2. Onboard tenants: accounts, terms, authorized persons and caps (doc 03).
3. Register the branch device in `/admin/devices`; install the PWA on the branch's
   machine; token → pull → verify the menu and accounts appear.
4. Train staff on the counter flows (PIN, split settlement, blind close, day close).
5. **Recovery drill before go-live** (doc 10 §9.1) — target under one hour.
6. Go live; watch `/admin/sync` and the digest for the first week; declare success
   when a full week reconciles (the doc 20 pilot protocol, per branch).

## Deferred, with reasons

| Item | Where it lands |
|---|---|
| Reminder/alert auto-push into the digest channels | The transports now exist; wiring reminders as individual pushes is a small follow-up once the owner confirms the channel (doc 05 reminders stay listed in `/admin/invoices` meanwhile) |
| Margin/waste columns in the comparison | Phase 8 (this session) |
| Labour %, rent %, branch net profit column | Phase 9 |
| Off-hours-activity exception | Needs `opening_hours` to be operated; add when branches maintain hours |
| Weekly/monthly digest variants | Doc 09 §8 lists them; the daily one is the doc 13 deliverable — variants when asked |

## Notes

Sync hardening under real five-branch load is observational: the pipeline is idempotent
and chunked by construction (Phase 4) and `/admin/sync` + stale alerts are the watch
instruments during the staggered go-lives.
