2026-05-27 Gate 2 ship. Same-day followup to U7 (which shipped earlier today). Narong: "Do you know where the Branch gets labeled? Like if we have multiple shops, how do we distinguish which report belongs to where". The U7 PDF was labeling the tenant (e.g. "Lumière Coffee Roasters") but the branch — the actual distinguishing field for multi-shop tenants — was missing. This slice surfaces it.
shop.timezone (with tenant.timezone fallback). Each commerce.shops row carries its own IANA timezone column — useful for multi-country tenants where session boundaries should reflect the branch's local clock, not the HQ's.closing-session-2026-05-27-b967eb21.pdf. New: closing-session-bkk1-2026-05-27-b967eb21.pdf (bkk1 = shop code on lumiere's active shop). Code is sanitized to [A-Za-z0-9_-] only; omitted entirely when blank.session.shopId (NOT NULL FK, always present post-R5.2). One extra read in parallel with the existing fan-out; zero added latency on warm worker.storeName → shopName, storeAddressLines → shopAddressLines, new tenantName field for the muted secondary line.Test ran against session b967eb21 on shop "Lumière BKK1" (code bkk1) under tenant "Lumière Coffee Roasters":
closing-session-bkk1-2026-05-25-b967eb21.pdf ← the shop code prefix is in there.nix-cafe/lib/reports/closing_session_pdf.ts — interface rename + header rendering (shop bold primary, tenant muted secondary with case-insensitive dedup)nix-cafe/app/api/cafe/sessions/[sessionId]/closing-session-pdf/route.ts — load shop via session.shopId, address fallback chain, tzForDate = shopTimezone || tenant.timezone, branch-code filename prefix| ✓ | Find a closed lumiere session w/ orders + its branch (Z test) — session b967eb21, shop "Lumière BKK1" (bkk1), tenant "Lumière Coffee Roasters" |
| ✓ | SSO-login lumiere owner |
| ✓ | Z test: fetch closing-session PDF (200 / application/pdf / closing-session- filename / %PDF magic) |
| ✓ | Closed session PDF: title 'Daily Sales Report Z' + section headings |
| ✓ | U7.1: PDF header shows shop name "Lumière BKK1" + tenant name "Lumière Coffee Roasters" (branch labeled) |
| ✓ | U7.1: Content-Disposition filename includes -bkk1- shop code prefix |
| ✓ | Closed session PDF: legacy 'Order#' / 'Methods' table headers gone |
| ✓ | Counts in PDF body match raw SQL: Number of transactions: 1 + Transactions Refunded: 0 |
| ✓ | Find an open lumiere session for the X test |
| ✓ | X test: open-session PDF has title 'Daily Sales Report X' |
| ✓ | No 5xx HTTP responses during the suite |
Fetched live from lumiere-coffee.nixtech.app. Each PDF's header now shows "Lumière BKK1" bold on top + "Lumière Coffee Roasters" muted below.
closing-session-bkk1-...closing-session-bkk1-...| test-phase1-prod.mjs | 11/11 |
| test-phase2-sso-outdoor-prod.mjs | 6/6 |
| test-m1-prod.mjs | 10/10 |
| test-r7-prod.mjs (solo retry) | 14/14 |
| test-r8-prod.mjs | 4/4 |
| test-phase2-cafe-multishop-prod.mjs (solo) | 6/6 |
narongix chain ran sequentially. r7 hit a transient cold-worker flake on the first attempt (7/14 — Pro Live drawer + /reports bounced to login); solo-retry-green in under 2 minutes, no code change. phase2-cafe-multishop ran solo per feedback_phase2_cafe_multishop_solo_retry — first-attempt green (9th validation today).
Per [[project_prod_tenants_all_single_shop]], all 3 prod test tenants have exactly 1 active shop today (lumiere = "Lumière BKK1"; get-coffee + demo have 1 each). So the prod test validates the single-shop case end-to-end. The multi-shop case (different reports for different shops on the same tenant) is structurally identical — the header just shows a different shop name + the filename gets a different code — and is exercised in the local sample PDF rendering.