Skip to main content

EP-007: POS & F&B Management — Phase 1 Hardening

Phase 1 hardening sprint, 2026-04. All work committed to feature branches in hmp-pos-service, hmp-shared-packages, and hmp-mobile-apps. Not yet pushed.

POS picked up four improvements in Phase 1: WebSocket auth on the kitchen gateway, the xPrisma → ServiceClient migration for room-charge lookups, branded ESC/POS receipt templates, and the KeyNova rebrand on the F&B mobile app.


C1 — Kitchen Gateway JWT Authentication​

Branch: feat/ws-jwt-auth (in hmp-pos-service, hmp-mobile-apps)

What was fixed​

KitchenGateway (/kitchen namespace) follows the same pattern as housekeeping:

  • JWT validated on handleConnection.
  • joinOutlet checks the requested outlet against the JWT-claimed propertyId (then verifies the outlet belongs to that property).
  • KOT events (kotCreated, kotStatusChanged, orderItemReady) emit to namespaced rooms property:<id>:outlet:<id>.
  • F&B mobile app forwards the auth token via Socket.IO auth.token on every reconnect.

Files touched​

  • hmp-pos-service/src/kitchen/kitchen.gateway.ts (+ .spec.ts)
  • hmp-mobile-apps/packages/shared-realtime/src/useRealtimeKitchen.ts
  • hmp-mobile-apps/apps/fnb/src/screens/KotBoardScreen.tsx

Tests​

11 of the 22+ C1 tests live on the kitchen gateway. All passing.


C4 — xPrisma → ServiceClient Migration (Room Charge)​

Branch: feat/xprisma-to-serviceclient (in hmp-pos-service, hmp-shared-packages)

What was fixed​

orders.service.ts looked up rooms via xPrisma.room.findFirst() to validate room-charge requests. The lookup crashed because pos-service's Prisma schema doesn't carry the room model. Migrated both call sites to PropertyServiceClient.getRoom({ roomNumber }), which hits property-service over HTTP and is cached for 5 minutes per (propertyId, roomNumber) pair via BusinessCacheService.

Files touched​

  • hmp-pos-service/src/orders/orders.service.ts (2 sites)
  • hmp-pos-service/src/orders/orders.service.spec.ts (mocks updated)
  • hmp-shared-packages/packages/service-clients/src/PropertyServiceClient.ts (getRoom method)

Tests​

79/79 POS tests pass after migration.


D6 — Branded Receipt Templates​

Branch: feat/branded-receipts (in hmp-shared-packages)

What was fixed​

@hmp/common/printing/receipt-templates.ts now exposes:

  • generateFolioReceipt(folio, options) — front-desk folio receipts
  • generatePosReceipt(order, options) — POS order receipts and KOTs

Both produce 48-character ESC/POS output with:

  • KeyNova brand header (centered logo line, brand colors, address, GSTIN)
  • Full GST breakdown (CGST/SGST/IGST split, HSN/SAC codes per line item)
  • IST date/time formatting
  • Indian number grouping (₹1,23,456.50)
  • IRN (Invoice Reference Number) line when present (e-invoice integration)
  • Cut command at the end

Files touched​

  • hmp-shared-packages/packages/common/src/printing/receipt-templates.ts (new)
  • hmp-shared-packages/packages/common/src/printing/receipt-templates.spec.ts (new)
  • hmp-shared-packages/packages/common/src/printing/escpos.ts (control code helpers)
  • hmp-shared-packages/packages/common/src/printing/index.ts (exports)

Tests​

47 unit tests, all passing. Tests verify:

  • Byte-level ESC/POS control codes (escape sequences for bold, center align, cut)
  • GST math (CGST + SGST = total tax for intra-state, IGST for inter-state)
  • IST timezone correctness (no UTC drift)
  • Number grouping at lakh boundaries
  • IRN line presence/absence based on input
  • Long-name truncation at 48-char boundary

D5 — Mobile F&B App KeyNova Branding​

Branch: feat/mobile-keynova-branding (in hmp-mobile-apps)

What was fixed​

  • apps/fnb/app.json renamed to "KeyNova F&B". Bundle ID updated.
  • KOT board, order list, table layout, and modifier sheets re-themed using shared @hmp/shared-ui tokens.
  • 0 "HMP" text references remaining in the F&B app.

Files touched​

  • hmp-mobile-apps/apps/fnb/app.json
  • hmp-mobile-apps/apps/fnb/src/screens/* (3 screens)
  • hmp-mobile-apps/apps/fnb/src/components/ModifierSheet.tsx

Open follow-ups​

  • Same as EP-006 D5: logo placeholder, Satoshi font fallback.

Summary​

StoryStatus beforeStatus afterNotes
US-007-006 (Room Charge)PartialBuiltC4: xPrisma migration unblocked happy path
US-007-008 (KOT Real-time)PartialBuiltC1: kitchen gateway secured
US-007-014 (Receipt Print)PartialBuiltD6: branded ESC/POS receipts shipped
US-007-019 (Mobile F&B App)PartialPartialD5: brand pass; live API integration pending

Story-level status promotions: 3 (US-007-006, -008, -014).