← All tests

#37 — Telegram Groups & Shift Time Management (prod)

SHIPPED 2026-06-10 · nix-cafe c745bf2 · migration · Gate 2 8/8 UI + 3/3 cron · regression 51/51

The “proactive POS” piece. Each shop gets configurable shift windows (Session 1 = 07:00→14:00, Session 2 = 14:00→22:00…). An every-minute cron checks for registers whose POS session is still open past a window’s end-time and pings the shop’s Telegram group — a reminder only, staff still close the shift at the register. Verified on lumiere-coffee.

How it works

Customer leaves register open past shift end ↓ every-minute cron (nix-cafe-cron-trigger) → /api/cafe/cron/shift-reminder-check ↓ for each shop window whose end-time has passed (in tenant tz) & a register session is still OPEN (and was open at the boundary): ↓ claim dedup row (cafe.shift_reminder_log, UNIQUE(session_id, window_id) → once per window) ↓ send a per-register reminder to the shop’s Telegram group(s) (shop-scoped groups, or tenant-wide groups, with “Shift reminder” on)

Shift schedules editor (per shop)

New Shift schedules section on the Telegram page. Pick a shop, add windows with start/end times (an end earlier than the start is treated as crossing midnight), save. Persists to the new cafe.shop_shift_windows table (times stored as minutes-of-local-day). The page is now reachable from Settings → Notifications (it was previously unlinked).

Telegram & Shift Reminders page with Shift schedules editor
Telegram & Shift Reminders — groups table (Shop + Shift-reminder columns) and the Shift schedules editor
A saved shift window
A saved window (08:00→14:00) — Gate 2 asserts it persists to the DB as 480/840 minutes and survives a reload

Per-shop group targeting + Shift-reminder toggle

The groups table gained a Shop selector (leave as All shops for tenant-wide) and a Shift reminder toggle. A shop-scoped group only receives its own shop’s reminders; an All shops group receives every shop’s. New shop_id + receive_shift_reminder columns on cafe.telegram_groups (extend, not replace).

Group with Shop selector and Shift-reminder toggle
Group row with Shop scope + Shift-reminder toggle

Cron verified end-to-end on prod

A separate DB-driven Gate 2 (_gate2_37_cron.mjs) seeded an open session + a past-end window + a shift-reminder group on lumiere, waited for the live every-minute cron, and asserted it: claimed the dedup row for (session, window) and attempted the Telegram send (logged as failed only because the test group’s chat is a bogus id — proving the send path ran). Then cleaned everything up. 3/3.