feat(subscription): rename permit→subscription + monthly pricing
The "permit/lejet" feature is really a subscription. Full rename of the mutable master data, plus a recurring monthly price. - DB (migration 0004, data-preserving ALTER RENAME): permits→subscriptions, permit_credentials/_plates→subscription_*, sessions.permit_id→subscription_id. - Pricing: per-subscription priceMinor + period(monthly) + currency, with a site default (site_config.subscription_monthly_price_minor) pre-filling the form. - Server: subscription-flow.ts (SubscriptionFlow), routes/subscriptions.ts (/api/subscriptions). Web: SubscriptionManager, route, i18n (sq Abonimet/en). - The signed ledger `permitId` payload is intentionally kept — immutable hash-chained history; renaming it would break verification of past events. Deferred (wiki notes): fee collection into the ledger/shift (a shift-attributed payment), LPR/ANPR plate source, time-of-day access windows (overnight subscriber). Also carries the device-footer UI surface (api DeviceStatus, router mount, i18n devices) due to shared-file overlap with the preceding footer commit. Verified end-to-end on a fresh DB and migration on a live-DB copy (sessions preserved). Live DB migrated. Full monorepo builds clean. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -11,7 +11,7 @@ status: open
|
||||
The project's **QR-code reader** (GEE NFC LIMITED). A static optical scanner for **QR /
|
||||
DataMatrix / 1D barcode**, optional ID/IC card. This is the **[[ticket-encoding|QR ticket]]
|
||||
scanner** the design called for — read at the pay station and exit lane — and a path for **QR
|
||||
[[permit]]** credentials. On hand: variant **`-Q-W`** (QR scanner; Wiegand/RS-232/RS-485).
|
||||
[[subscription]]** credentials. On hand: variant **`-Q-W`** (QR scanner; Wiegand/RS-232/RS-485).
|
||||
(See [[gee-qr-er80|datasheet summary]] / `raw/`.)
|
||||
|
||||
## What it is (and isn't)
|
||||
@@ -39,7 +39,7 @@ GET /qa/mcardsea.php?cardid=<QR>&mjihao=<devId>&cjihao=<devSN>&status=<2 chars>&
|
||||
This is **host-in-the-loop and SYNCHRONOUS**: the GET *is* the access query and **our reply is the
|
||||
decision** — it drives the reader's beep + output. So unlike a fire-and-forget reader, the endpoint
|
||||
must decide (valid/invalid, direction from `status`) and reply, then also emit a `DeviceReadEvent`
|
||||
on the `read` bus for the entry/exit/permit flows ([[parking-session]], [[permit]]) to open the
|
||||
on the `read` bus for the entry/exit/permit flows ([[parking-session]], [[subscription]]) to open the
|
||||
barrier. ([[device-input-flow]] is the analogous push pattern; this one also returns a verdict.)
|
||||
|
||||
> **This explains the "no beep":** feedback comes from the server's JSON reply, not locally. A
|
||||
|
||||
Reference in New Issue
Block a user