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:
@@ -483,7 +483,11 @@ export interface ReportSeriesPoint {
|
||||
entries: number;
|
||||
exits: number;
|
||||
revenueMinor: number;
|
||||
cashMinor: number;
|
||||
cardMinor: number;
|
||||
payments: number;
|
||||
/** Cars inside at the END of the bucket. */
|
||||
occupancyEnd: number;
|
||||
}
|
||||
|
||||
export interface ReportTotals {
|
||||
@@ -500,6 +504,8 @@ export interface ReportTotals {
|
||||
totalParkedMinutes: number;
|
||||
avgParkedMinutes: number;
|
||||
medianParkedMinutes: number;
|
||||
voids: number;
|
||||
anomalies: number;
|
||||
}
|
||||
|
||||
export interface ReportSubscriptionStats {
|
||||
@@ -519,6 +525,12 @@ export interface ReportSummary {
|
||||
totals: ReportTotals;
|
||||
series: ReportSeriesPoint[];
|
||||
entriesByHour: number[];
|
||||
/** 7×24, row 0 = Monday — entries heatmap (weekday-vs-weekend patterns). */
|
||||
entriesByDowHour: number[][];
|
||||
/** Stay-duration histogram; last bucket has uptoMin null (>24h tail). */
|
||||
stayHistogram: { uptoMin: number | null; count: number }[];
|
||||
occupancyStart: number;
|
||||
capacity: number | null;
|
||||
subscriptions: ReportSubscriptionStats;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user