feat(booth): overstay sessions, top-up pricing, and session/feed filters
Rework paid-but-grace-expired sessions and add booth filters. Overstay (was "stuck"): - Stop silently aging out a paid transient whose walk-back grace lapsed with no signed exit. Keep it listed with an OVERSTAY badge — a new parking period began (re-parked) or the car is faulty/abandoned; it is not a system fault. - No free exit: reopenBarrier refuses server-side once a transient's payment grace has expired (allow only subscription OR paid-and-within-grace); the UI hides the Open-barrier button on overstay rows and routes to the pay/exit modal. Closes a hole where a stale payment authorized a free multi-day exit (operator-as-adversary). - Price the overstay as a NEW period from grace-expiry -> now with its own daily-cap ladder, NOT "full stay minus paid" (which a daily cap collapsed to 0 — ticket 1245791632490 owed ALL 0; now owes its real overstay). quote() gains periodStart + overstay; SessionLookup/ActiveSession gain `overstay`. handlePayAndExit charges whenever the session is payable (was: only if !alreadyPaid, skipping the overstay). Filters (new ui/FilterBar): Active Sessions — search + status (unpaid/paid/exiting/overstay) + transient-vs-subscriber. Live feed — search + event (entry/exit/pay/void/anomaly) + direction + source (booth=manual vs reader). All client-side over already-fetched data; matched/total count shown. i18n parity (sq+en). Wiki: booth-exit-flow updated (overstay model, naming history, no-free-exit security fix, new-period pricing; open question on grace-renewal noted). Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -694,6 +694,9 @@ export interface SessionLookup {
|
||||
currency: string | null;
|
||||
withinGrace: boolean;
|
||||
graceExpiresAt: string | null;
|
||||
/** OVERSTAY: paid transient, walk-back grace expired, no exit — a new period began;
|
||||
* owes a fresh top-up (amountMinor); cannot exit for free. */
|
||||
overstay: boolean;
|
||||
/** A subscription occurrence (prepaid — no pay flow; barrier-open assist only). */
|
||||
subscription: boolean;
|
||||
subscriptionId: string | null;
|
||||
@@ -717,6 +720,10 @@ export interface ActiveSession {
|
||||
currency: string | null;
|
||||
withinGrace: boolean;
|
||||
graceExpiresAt: string | null;
|
||||
/** OVERSTAY: paid transient whose walk-back grace lapsed with no signed exit — a new
|
||||
* period began (re-parked) or the car is faulty/abandoned. Owes a fresh top-up;
|
||||
* flagged so the operator reconciles, never a free exit. */
|
||||
overstay: boolean;
|
||||
/** A subscription occurrence (prepaid — no pay flow; barrier-open assist only). */
|
||||
subscription: boolean;
|
||||
subscriptionId: string | null;
|
||||
|
||||
Reference in New Issue
Block a user