# Dine Phases 12 → 20 — Operational Stabilization Summary

> **Branch:** `dine-phase-11`
> **Head:** (set after Phase 20 commit)
> **Scope:** all phases follow the rule "backend signal must be visible and usable in the frontend before the phase is considered complete." Each phase is one separate commit. No AI / loyalty / marketing / customer engagement / websocket infrastructure / overengineering.

---

## Phase tour

| # | Title | Commit | What it ships |
|---|---|---|---|
| 12 | Sync failure logging | `5db6a49` | `dine_sync_failures` table + `POST/GET /dine/sync-failures` + dashboard `system_health.sync_failures_today` populated + Phase-10 alert wired + new `SyncFailuresPanel` on `/app/dine/ops`. 8 BE tests + 1 FE test. |
| 13 | Printer job tracking | `5463c7b` | `dine_printer_jobs` table + `POST/GET /dine/printer-jobs` + `failed_printer_jobs_today` populated + new `failed-printer-jobs` alert (warning at >0, danger at ≥5) + new `PrinterJobsPanel`. 8 BE tests + 1 FE test. |
| 14 | Pilot hardening | `5282f85` | Per-screen-type `localStorage` namespacing in `useDeviceHeartbeat` so distinct Dine screens in one browser register as distinct devices. One-shot legacy migration. 3 new FE tests pin the contract. |
| 15 | Cashier perf | `2be129f` | Two additive composite indexes on `dine_orders` covering the dashboard hot-path queries (`(company_id, created_at)` + `(company_id, branch_id, created_at)`). Migration self-guards via `SHOW INDEX`. No query code changed. |
| 16 | Inventory accuracy review | `f3691aa` | New `DineInventoryAccuracyTest` locks the live invariant: dashboard `recipe_consume_today` / `recipe_void_today` / `low_stock_count` match actual `stock_movements` + `inventory_levels` + Phase-10 low-stock alert reality. 3 BE tests. |
| 17 | Device management | `992cde9` | `PATCH/DELETE /dine/devices/{device}` + cross-tenant 404 + inline rename + unregister buttons in `DevicesPanel`. 3 new BE tests. |
| 18 | Variant-aware low-stock | `6d4e217` | Dashboard `low_stock_count` join now includes `variant_id` with NULL == NULL match. Eliminates double-count on multi-variant products and missed-row on variant-specific reorder rules. 1 new BE test pins the contract. |
| 19 | Async accounting posting review | `a3b395b` | Documentation only. Confirms the synchronous DineOrderPoster path is operationally acceptable for the cash hot path and lists the deferred instrumentation order if async ever becomes warranted. **Zero production-code changes.** |
| 20 | Final stabilization | (this commit) | Final sweep + readiness report. No new code. |

---

## Backend / frontend per-phase coverage

Every phase that touched a user-facing signal added matching FE work the same commit:

| Phase | Backend | Frontend |
|---|---|---|
| 12 | migration · model · controller · routes · dashboard wiring · alert wiring · 8 tests | `dineApi.logSyncFailure` / `syncFailures` · `useDineSyncFailures` hook · `SyncFailuresPanel` · 1 test |
| 13 | migration · model · controller · routes · dashboard wiring · new alert · 8 tests | `dineApi.logPrinterJob` / `printerJobs` · `useDinePrinterJobs` hook · `PrinterJobsPanel` · 1 test |
| 14 | (no backend change — heartbeat hook only) | per-type localStorage scope · 3 new tests |
| 15 | composite indexes · 0 tests (read-side perf only) | (no FE change — same payload shape) |
| 16 | 3 invariant tests | (no FE change — proves dashboard signals already correct) |
| 17 | rename + delete endpoints · 3 tests | API + hooks · inline rename / unregister UI |
| 18 | dashboard join tightened · 1 test | (no FE change — same field, more accurate) |
| 19 | doc only | doc only |

---

## Final test results (HEAD)

| Suite | Result | Compared to start of Phase 12 |
|---|---|---|
| `php artisan test --filter=Dine` | **148 passed** (1422 assertions) | was 125 — **+23** |
| `php artisan test --filter='DineCashSaleAccountingPostingTest\|DineDeviceHeartbeatTest\|DineSyncFailuresTest\|DinePrinterJobsTest\|DineInventoryAccuracyTest\|DineDashboardTest\|DineDashboardAlertsTest\|DineRouteParityTest'` | **63 passed** (585 assertions) | was 39 |
| `php artisan test --filter='Posting\|Refund\|Journal\|Accounting\|Payment'` | 4 failed / **220 passed** | unchanged 4 step-up fixture failures (pre-existing) |
| `npx vitest run` | **170 passed** across 14 files | was 165 — **+5** |
| Pre-existing step-up failures | 4 | classified, non-blocking, untouched per scope |

---

## Cash sale accounting integrity (preserved end-to-end)

`DineCashSaleAccountingPostingTest` is still green with 53 assertions on a single live order:

- order create → cash pay → balanced journal → `source='dine_order'` + `source_ref=order.id` → every line carries `branch_id` → cash + revenue + tax + COGS + inventory legs all present → idempotent on retry → inventory `recipe_consume` movement → dashboard rollup.

No phase between 12 and 20 touched any accounting / cashier / inventory write path. Every dashboard signal addition is read-only.

---

## What's still NOT tracked

`system_health.queue_backlog` and `system_health.failed_payments_today` remain `null`. Phase-19 documents the deferred path for async-accounting instrumentation; queue backlog needs a queue-introspection harness; failed payments needs the Pay module's per-attempt log to materialise (out of scope while the Pay module is still cash-focused).

The dashboard FE renders both as `—` / "Not tracked yet" — consistent with the Phase-9 honesty rule.

---

## Out of scope (deliberately, throughout)

- AI / anomaly detection / ML scoring.
- Loyalty / marketing / customer engagement.
- Notification delivery (SMS / WhatsApp / email / push).
- Websocket infrastructure / event streaming / realtime channel.
- Remote device control / push commands.
- Pay-module completion (online payments, settlement orchestration).
- Accounting architecture refactor.

---

## Rollback per phase

Each phase is a single squash-style commit. `git revert <hash>` is clean per phase. The Phase-15 index migration carries a working `down()` that drops the indexes by name. Phase 12 / 13 migrations carry `down()` that drops the tables. Phases 14 / 17 / 18 are pure code changes and revert by hash. Phase 16 / 19 / 20 are documentation/test only and have no production-code effect.

---

## Production-review readiness

**Yes.** Phases 12–20 ship 32 new backend tests, 5 new frontend tests, 4 new dashboard signals (sync failures, printer jobs, sync failures alert, printer jobs alert), 6 new endpoints, 2 new tables, and 2 new dashboard panels — all wired end-to-end (BE signal → dashboard payload → FE panel → alert ladder where applicable). Cash-only Dine cashier flow remains accounting-compatible and the journal idempotency contract is unchanged.
