feat(reports): occupancy curve, hour×dow heatmap, stay histogram, fraud KPIs
The dashboard had generic BI views but nothing parking-shaped. Added: - Occupancy step-area over the range with the configured capacity as a red reference line. occupancyStart folds the ENTIRE prior ledger (voided entries excluded, clamped ≥0); each series point carries occupancyEnd. Answers "when are we near full". - Entries heatmap hour × day-of-week (7×24, row 0 = Monday, site tz) as a pure CSS-grid intensity map — weekday-vs-weekend at a glance, the direct evidence for tariff windows. Replaces the flat hour histogram (strictly contains it). - Stay-duration histogram at tariff-shaped edges (30m/1h/2h/4h/8h/24h/ tail): where ladder/up-to breakpoints should sit. - Voids + anomalies KPIs (accented when >0) — the look-closer counters the signed chain exists for; peak-occupancy KPI (peak / capacity). - Revenue bars stacked cash vs card (the drawer's money vs the bank's); CSV export gains cash, card, occupancy_end columns. Internals: localParts caches its Intl formatter per tz (was one new formatter per ledger row); @parking/db re-exports lt/gt. 5 new tests. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
type: concept
|
||||
tags: [parking, domain, business, reporting]
|
||||
sources: []
|
||||
updated: 2026-06-22
|
||||
updated: 2026-07-05
|
||||
status: open
|
||||
---
|
||||
|
||||
@@ -73,6 +73,30 @@ disputes ("I was charged for a car that left earlier"), lost-ticket lookup, and
|
||||
- **Export** for [[reconciliation]] / accounting (CSV/PDF) — the periodic external-authority path
|
||||
([[open-questions]] #4).
|
||||
|
||||
## As-built additions (2026-07-05) — the parking-shaped graphics
|
||||
|
||||
Operator ask: "check /reports for improvements and meaningful graphics." The dashboard (Recharts,
|
||||
ledger-first aggregation in `apps/server/src/reports.ts`) gained the three views that are
|
||||
parking-specific rather than generic BI, plus fraud counters:
|
||||
|
||||
- **Occupancy curve** — cars-inside step-area over the range with the configured capacity as a
|
||||
red reference line. `occupancyStart` folds the ENTIRE prior ledger (voided entries excluded,
|
||||
clamped ≥0); each series point carries `occupancyEnd`. The at-a-glance answer to "when are we
|
||||
near full" — the input for capacity and dynamic-window decisions.
|
||||
- **Entries heatmap (hour × day-of-week)** — 7×24 matrix (`entriesByDowHour`, row 0 = Monday,
|
||||
site-tz), rendered as a pure CSS-grid amber-intensity map. Shows weekday-vs-weekend and
|
||||
morning/evening patterns — the direct evidence for tariff windows (night rates, weekend cards,
|
||||
early-bird — see [[tariff-industry-survey]]). Replaces the flat entries-by-hour bar (strictly
|
||||
contains it).
|
||||
- **Stay-duration histogram** — closed sessions bucketed at 30m/1h/2h/4h/8h/24h/tail
|
||||
(`stayHistogram`): where the ladder/up-to breakpoints should sit.
|
||||
- **Look-closer counters** — voids + anomalies in range as KPI cards (accented when >0): a spike
|
||||
is exactly what the signed chain exists to surface (the operator is the threat model).
|
||||
- Revenue bars now **stack cash vs card** per bucket (`cashMinor`/`cardMinor` on each point —
|
||||
the drawer's money vs the bank's); peak-occupancy KPI (`peak / capacity`); CSV export gained
|
||||
cash, card, occupancy_end columns. `localParts` now caches its Intl formatter per tz (was one
|
||||
`new Intl.DateTimeFormat` per ledger row).
|
||||
|
||||
## Open
|
||||
|
||||
- Which reports matter at launch vs. later; the export format/cadence.
|
||||
|
||||
Reference in New Issue
Block a user