feat(tills): per-till activity log, wash bucket on the booth Z-report, wash-desk printer role
Closes the three known follow-ups of the Tills decision (venue-modules.md): - Activity log per till: `tillOfEvent(type, payload)` in @parking/shared (money events by payload till, other events by their owning module's till, everything else booth), applied by `/api/events?till=` in SQL and passed by the hub log, the Drawer "today" panel and the booth feed (history + live pushes). The events route admits a role that holds a module feed permission without event:read and returns only that module's event types — the live-socket rule. - Booth Z-report: `chargesByModuleMinor` sums the chargeLines on the till's payments by module; the ticket bucket excludes them (Bileta = parking only); printed "Lavazh (në biletë)" only when any was taken. The wash till's slip prints "Lavazh:". - Printer role `wash-desk`: the wash till's Z-report and vouchers print there, falling back to the booth printer; nothing falls back to the desk. `printerRoleOf()` is the one reading of the role field (the entry/booth loaders treated any non-booth role as an entry dispenser). Footer label "at wash desk". Also: `GET /api/carwash/settings` opens to carwash:read OR site:read (new requireAnyPermission) — the Wash operator job could not load the desk's category and service pickers. Tests for all four; wiki (shift, printer-roles-failover, venue-modules, log) updated. Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
This commit is contained in:
@@ -64,7 +64,7 @@ export function localIsoWithOffset(tz: string, at = new Date()): string {
|
||||
* - reader/camera → the direction inherited from its bound relay (entry/exit/both)
|
||||
* - access → entry/exit/both from its relays[]; "mixed" if it spans more
|
||||
* than one direction; null if it declares none yet
|
||||
* - printer → "lane" (entry-dispenser) | "booth" (booth-receipt)
|
||||
* - printer → "lane" (entry-dispenser) | "booth" (booth-receipt) | "wash" (wash-desk)
|
||||
*/
|
||||
function roleKindOf(db: Db, row: DeviceRow): DeviceStatusEvent["roleKind"] {
|
||||
switch (row.category) {
|
||||
@@ -89,6 +89,7 @@ function roleKindOf(db: Db, row: DeviceRow): DeviceStatusEvent["roleKind"] {
|
||||
const role = (row.config as { role?: string }).role;
|
||||
if (role === "booth-receipt") return "booth";
|
||||
if (role === "entry-dispenser") return "lane";
|
||||
if (role === "wash-desk") return "wash";
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user