727c62da90
- site_config gains optional park identity (park_name, operator_name, nius, address, phone, email); additive Drizzle migration 0001. GET/PUT /api/site-config read/write the full config (PUT partial patch, admin only); SiteSettings + SetupWizard expose the fields. - renderTicket() prints an Albanian header sourced from site_config, the all-numeric 13-digit ticket id (12 random + Luhn) as Code128, large digits, and a lost-ticket footer. CP852 codepage so ë/ç render. - Widen the Code128 module width 2->3 and height 80->100 dots so the short-range "Simple" QR/barcode reader decodes reliably (was barely reading at module width 2 on the 80mm head). See wiki/concepts/site-metadata.md and ticket-encoding.md.
79 lines
4.0 KiB
Markdown
79 lines
4.0 KiB
Markdown
---
|
|
type: concept
|
|
tags: [parking, domain, config, devices]
|
|
sources: []
|
|
updated: 2026-06-17
|
|
status: settled
|
|
---
|
|
|
|
# Site Metadata (Park Identity)
|
|
|
|
Optional, admin-set identity/metadata for the park itself, beyond the operational
|
|
`capacity` knob. Feeds the ticket/receipt header and admin display. All fields are
|
|
**optional** — the lot runs fine with none set (the ticket falls back to a generic
|
|
`PARKING` header).
|
|
|
|
## Where it lives
|
|
|
|
A single-row extension of the existing **`site_config`** table (`id` always 1) — the
|
|
established home for site-wide knobs ([[capacity-occupancy]]). **Not** a new table:
|
|
park identity is one-per-site, same cardinality as capacity, so it shares the row.
|
|
|
|
| Column | Purpose |
|
|
| --- | --- |
|
|
| `park_name` | Display name on the ticket header / UI (e.g. "Acme Parking"). |
|
|
| `operator_name` | Legal entity operating the lot — for receipts; may differ from the display name. |
|
|
| `nius` | **NIUS** — Albanian tax/identification number, printed on the receipt when set (commonly required). |
|
|
| `address` | Free-text postal address (multi-line allowed; printed line-by-line). |
|
|
| `phone` | Contact phone — also the ticket "Keni humbur biletën?" footer. |
|
|
| `email` | Contact email (stored; not yet printed). |
|
|
|
|
All are **nullable `text`**. Added in migration `0001` (additive `ADD COLUMN`, no
|
|
data loss). A **metadata change is not a schema change for the ticket id**, but
|
|
adding these *fields* IS a schema change — done via a Drizzle migration.
|
|
|
|
> **Field history.** The first cut (2026-06-17) had `vat_number` + `registration_number`.
|
|
> Renamed/trimmed the same day to a single `nius` column (Albanian deployments call the
|
|
> tax id NIUS; registration number dropped as unused). Migration `0001` was regenerated
|
|
> in place — it had not shipped beyond the dev DB, so there is no migration debt.
|
|
|
|
## Read / write path
|
|
|
|
- **API**: `GET /api/site-config` returns capacity + every metadata field (null when
|
|
unset). `PUT /api/site-config` (**admin only**) accepts a **partial** body — only the
|
|
fields present are updated; blank string → null (clears). `apps/server/src/routes/site.ts`.
|
|
- **UI**: `apps/web/src/SiteSettings.tsx` — admin edits capacity + the metadata fields
|
|
in one form (`saveSiteConfig`).
|
|
- **API client**: `SiteConfig` type + `fetchSiteConfig` / `saveSiteConfig` in `apps/web/src/api.ts`.
|
|
|
|
## On the ticket
|
|
|
|
`renderTicket()` ([[rongta-printer]]) prints a header from a `TicketHeader` (the metadata):
|
|
park name large (or `PARKING` if unset), then operator / `NIUS: <n>` / address lines
|
|
that are present; a `Keni humbur biletën? <phone>` footer if a phone is set. The entry
|
|
flow (`#ticketHeader()` in `apps/server/src/entry-flow.ts`) reads `site_config` per print.
|
|
See [[ticket-encoding]].
|
|
|
|
## Localisation (Albanian)
|
|
|
|
The ticket prints in **Albanian** for now. Strings are centralised in a `STR` table in
|
|
[[rongta-printer]] (`Printuar më:`, `Keni humbur biletën?`, `NIUS:`) so a real i18n layer
|
|
(per-locale tables + a `t()` helper, covering the web UI too) can replace them later
|
|
without touching the render functions — that broader site translation is the next step.
|
|
|
|
**Codepage (resolved 2026-06-17).** Albanian text needs `ë`/`ç`, which ASCII can't carry.
|
|
The driver now selects **CP852 (Latin-2)** via `ESC t 18` in each print preamble and
|
|
`line()` encodes text to CP852 (with an ASCII transliteration fallback for anything
|
|
unmapped, and `?` as a last resort — never a wrong glyph). Verified at byte level: `ë` →
|
|
`0x89` in "Printuar më" / "biletën" / a sample address.
|
|
|
|
## Open
|
|
|
|
- **Receipt vs entry ticket** — the same header is used for the entry ticket today;
|
|
a paid receipt may want more (fee, tariff version, paid-at). Design with [[tariff]].
|
|
- **Email** is stored but not yet printed (no use decided).
|
|
- **Full i18n** — only the ticket is Albanian so far; the web UI is still English. A
|
|
proper locale system (and admin language choice) is the broader task this seeds.
|
|
- **CP852 coverage** — the map covers the common Albanian/Latin-2 letters; extend if a
|
|
park name/address uses a glyph outside it (currently transliterated to ASCII).
|