- 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.
4.0 KiB
type, tags, sources, updated, status
| type | tags | sources | updated | status | ||||
|---|---|---|---|---|---|---|---|---|
| concept |
|
2026-06-17 | 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 singleniuscolumn (Albanian deployments call the tax id NIUS; registration number dropped as unused). Migration0001was regenerated in place — it had not shipped beyond the dev DB, so there is no migration debt.
Read / write path
- API:
GET /api/site-configreturns 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:
SiteConfigtype +fetchSiteConfig/saveSiteConfiginapps/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).