docs(wiki): tariff research — legacy ParkSQL2017 schema, time-tiers & validation/sponsorship design

Ingest the predecessor SQL Server schema (raw + source summary) and file design
pages for time-of-day/seasonal tariff tiers and merchant validation/postpaid
sponsorship. Cross-link tariff.md and validation-discounts.md. No code.
This commit is contained in:
2026-06-18 10:59:21 +02:00
parent 71aaad03b9
commit 58d8f06ba0
6 changed files with 1582 additions and 3 deletions
+32 -2
View File
@@ -124,6 +124,24 @@ time references**, not one:
`gracePeriodExit` is therefore a real revenue/UX parameter, not a nicety: too short traps people
who paid; too long gives free parking between pay and exit.
> **As-built correction (2026-06-17):** the overstay top-up reprices from **entry**, not `paidAt` —
> `computeFee(enteredAt, now, …)` (so the timer never restarts; the customer pays the true entry→now
> total). The line above (`f(paidAt, now, …)`) was the original sketch; the implementation uses entry.
### ⚠ Open question — walk-back grace renews on every payment
A consequence of the two-time-reference model, surfaced via the [[booth-exit-flow|booth exit /
voucher]] path: every `payment` event stores its own `gracePeriodExit`, and the exit check reads the
**latest** payment's value. So an **overstay top-up re-grants a full, fresh grace window** each time.
The fee is correct (always recomputed from entry — no free exit), but the **walk-back grace doubles**
(or repeats) on every top-up — a customer could pay → wait → pay a tiny delta → earn another window →
repeat. The leak is **time, not money**, bounded by increment coarseness but real.
Candidate policies (business call): grant grace on a top-up **only when it charged new money**
(recommended), a **single non-renewing window** from the first payment, or a **per-session grace
cap**. Full analysis + the decided/undecided halves live in [[booth-exit-flow]]. Pick a policy before
production.
## Permit holders
A valid [[permit]] bypasses tariff computation entirely for the covered period (subscription
@@ -169,12 +187,24 @@ Unlike the event log, tariff data is **mutable master data** in the sense that n
on the network — [[offline-first]]), a base currency, and a rounding policy. Deferred to
[[open-questions]].
## Extensions under design
Two operator asks extend this engine; both have design pages (not yet built), grounded in
[[parksql2017-legacy-schema|the legacy schema]] + external research:
- **Time-of-day / weekday / seasonal tiers** (happy hour, off-peak, weekend, vehicle category) —
see [[tariff-time-tiers]]. Chosen shape: **time-windowed rate cards** selected by wall-clock window,
layered additively on this structure (a bare default card = today's behaviour). The hard part is
slicing a stay at window boundaries while keeping the block ladder + daily cap continuous.
- **Validation & sponsorship** (merchant comps, coupons, **postpaid B2B** "enter/exit free, bill the
business monthly") — see [[validation-sponsorship]]. A validation is a **typed modifier applied as a
signed event** on a transient session, distinct from a [[permit]]; postpaid sponsors accrue a
monthly-invoiced liability derivable from the chain.
## Open
- The **actual rate cards** are owner-authored at runtime — nothing to confirm at build time; the
composer UI + validation (sane blocks, non-negative, ordered `uptoMin`) is the work.
- **Time-of-day / weekday tiers** — not in the block model yet; add as a tier wrapper if a site
needs day/night/weekend cards (deferred until asked).
- **Blank-tariff policy** — free vs. gated until a rate card is published (operator policy).
- **In-progress version-boundary** — entry-version (decided) vs. pro-rate (revisit if needed).
- **FX** — exchange-rate system, offline rate source, base currency ([[open-questions]]).