2026-05-27 Gate 2 ship. Third follow-up touch to the closing-session PDF today (after U7 + U7.1). Narong: "under As of Date, can we include From Time → To Time?". The "As of MM/DD/YYYY" boxed cell now has a second smaller line below showing the session's open/close window — HH:MM → HH:MM for closed sessions, HH:MM → (open) for X (mid-session) reports.
09:00 → 17:30. 24-hour format via Intl.DateTimeFormat("en-GB", { hour: "2-digit", minute: "2-digit", hour12: false }).09:00 → (open). Using "now" or the PDF generation time would mislead — for an X (mid-session) report the close time genuinely isn't known yet, so the literal is the most honest signal.tzForDate = shopTimezone || tenant.timezone resolution as U7.1, so the date and the time range stay consistent. Both reflect the BRANCH's local clock for multi-country tenants.safe() sanitizer would strip it. The new drawAsOfCell checks for arrow-loss after safe() and substitutes ASCII "->" when needed. (On prod, pdf-lib's text encoder embeds the arrow correctly, so the visible PDF shows "→".)nix-cafe/lib/reports/closing_session_pdf.ts — sessionTimeRange: string on input interface; drawAsOfCell grew 22pt → 34pt to fit two lines + new timeRange param + arrow encoding fallbacknix-cafe/app/api/cafe/sessions/[sessionId]/closing-session-pdf/route.ts — new fmtHHMM helper formats both opened_at + closed_at via Intl en-GB 24h with timeZone: tzForDate; composes sessionTimeRange = `${fromTime} → ${toTime}`; open sessions branch to literal "(open)"| ✓ | Find a closed lumiere session w/ orders + its branch (Z test) — session b967eb21, shop "Lumière BKK1" |
| ✓ | 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 + tenant name (branch labeled) |
| ✓ | U7.2: PDF As of cell shows session time range — at least 2 HH:MM endpoints extracted from PDF text for the closed session |
| ✓ | U7.1: Content-Disposition filename includes shop code prefix (-bkk1-) |
| ✓ | 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' AND U7.2: shows "(open)" upper bound |
| ✓ | No 5xx HTTP responses during the suite |
Fetched live from lumiere-coffee.nixtech.app. The "As of" cell in the top-right corner of each PDF now shows two lines: date primary, session time range smaller below.
HH:MM → HH:MMHH:MM → (open)| test-phase1-prod.mjs | 11/11 |
| test-phase2-sso-outdoor-prod.mjs | 6/6 |
| test-m1-prod.mjs | 10/10 |
| test-r7-prod.mjs | 14/14 |
| test-r8-prod.mjs | 4/4 |
| test-phase2-cafe-multishop-prod.mjs (solo) | 6/6 |
narongix chain ran sequentially and was first-attempt green this time (no r7 flake retry needed — clean first run). phase2-cafe-multishop ran solo per feedback_phase2_cafe_multishop_solo_retry — first-attempt green (10th validation today).
First prod test attempt ran ~75s after push and failed with "expected at least 2 HH:MM time stamps; found 1" + "'(open)' upper bound missing" — the new U7.2 features were missing from the rendered PDF. wrangler deployments list confirmed the CF Workers Build hadn't landed yet (last deploy was U7.1 at 06:24 UTC; my U7.2 push was 06:51 UTC). Used a backgrounded until [ ... ]; do sleep 15; done loop polling wrangler deployments list for the new timestamp prefix, then auto-reran the test. Deploy landed within ~30s of the loop starting and the retest came back 12/12. Clean recovery path — no manual intervention.