You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Feature: Shift lifecycle management, cash drawer reconciliation, & business day close #279
Full shift management lifecycle, cash drawer float tracking, drawer count reconciliation with variance calculation, shift enforcement middleware, and business date day-close reporting.
Proposed Changes
Shift Schema & Migrations:
Migration 69 (shifts table, shift_id on orders and bills, indices) and Migration 70 (expected_cash_cents and variance_cents columns on shifts).
Shift Lifecycle & Cash Reconciliation:
Open shift modal (opening float input), Close shift modal (cash drawer count), Force close shift option.
Shift reconciliation logic comparing system-calculated expected cash vs actual cash count to determine variance.
Verdict: VALID ENHANCEMENT — large; needs product decision before implementation
Findings:
No shifts, day_closes, drawer-float, or enforcement logic exists on main (the only "shift" hit is a timezone comment at main/db.ts:4785). X/Z report menu items (main/index.ts:529-530) just navigate the renderer to the reports page; reports.ts has daily-stats (main/routes/reports.ts:105) but no business-day close.
Timezone-aware local-day logic already exists for order/bill numbering (dateStampInTimezone, see feat: configure invoice numbering #297) and is reusable for localDayBoundsUtc-style day boundaries.
Migrations 69-71 referenced are fork-only; current schema is v68.
Suggested scope (MVP first): shifts table + open/close modals with opening float and drawer count + expected-vs-actual variance; then shift enforcement middleware and day-close accounting as separate follow-ups. Overlaps: #278 (cash refunds in day-close expected cash), #287 (SHIFT_START/END audit events), #280 (inventory snapshot at close). Maintainer decision needed: is shift enforcement a desired workflow change (forces open shift before cash transactions)?
Research follow-up: day-end closing terminology and comparable POS behavior
I reviewed documentation from several established POS systems to compare their day-end closing workflows.
Findings
The most common model is a shift or cash session. It is opened with starting cash, supports cash-in/cash-out, and is closed by entering the actual drawer cash. The system calculates expected cash and the over/short difference.
Many systems provide an interim X report and a final Z report. The X report is a read-only snapshot; the Z report is produced when the cash session is finally closed.
Other terminology includes Work Period, Close Cash, Cash Closing, and Register Close.
Typical history/report fields include the POS or terminal, opening time, closing time, expected cash, actual cash, variance, payment totals, refunds, and cash movements.
The final close report is commonly printable from the POS, with historical reports available in the back office.
Product recommendation for FloCafe
“Day close” is the business workflow, but the underlying record should be a cash session/shift, tied to a specific till/register/device. A day can contain multiple tills or multiple shifts, and a shift can cross midnight.
Recommended terminology:
Internal model: cash_session
POS actions: Open Shift / Close Shift
Physical object: Till, Register, or Cash Drawer
Store-level report: Day-End Sales Summary
Final printed reconciliation: Shift Close Report or Z Report
The MVP close report should include:
Session number, terminal/till, opened by, closed by
Opening date/time and closing date/time
Opening cash
Expected cash
Actual cash
Over/short variance
Pay-ins and pay-outs
Sales by payment method
Refunds
Receipt/order count
Discounts/voids, where available
Tax totals
Printed report status
Important distinction: a shift/till close reconciles money; a day-end report summarizes business activity. If FloCafe has one till and one daily session, the UI may present this as “Close Day”, but it should still persist a shift/cash-session record underneath.
This research supports the existing issue scope, with the likely implementation sequence:
Cash session/shift lifecycle with opening float, close count, expected-vs-actual variance, timestamps, and printed summary.
Optional shift enforcement.
Separate business-day close/reporting, including timezone-safe boundaries.
Re-scoping check per the stabilization plan: the plan's original instruction was "rewrite against cash_closures" — that table now exists (main/db.ts, migration add_cash_closures) with business_date tracking, and shift_id-based drawer attribution already flows through main/services/refund.ts. So part of this issue's foundation has landed since it was filed.
Full shift lifecycle management is explicitly out of this stabilization milestone's scope (0-5phases.md, "Explicitly not in this milestone: Full shift/cash-session lifecycle"), so this issue correctly stays open — it just needs re-scoping against the current cash_closures foundation rather than a from-scratch design. Labeling state:needs-design; owner scoping needed before implementation starts.
Approach A is implemented in #836, ready for review (branch shift-lifecycle).
What it builds, following the three comments above:
Open state in a new cash_sessions table (migration v90); closes persist as cash_closures rows with scope='session', using the extension door this issue anticipated. Day close is untouched.
Cashiers open (Abrir caja) and close (Cerrar turno) their own shift from the POS terminal. The opener closes their own session; manager/owner can force-close. Day close stays owner-only.
Enforcement ships as a default-off setting, per the open product question: with it on, cash payments, cash refunds, and drawer movements need an open session. Custom methods resolving to cash are covered.
Human closes are blocked by unpaid or partial in-window bills; stale sessions auto-close. The opening float mirrors as the day's movement so both Zs reconcile the same drawer.
Session-Z printing is open to shift roles; day Z stays owner-only.
Checks: new 65-test session suite plus the day-close, payments, refunds, reports, and export suites green; lint, build, and i18n checks green; three review rounds with every high and medium fixed; walked end to end in a real browser (open float, live expected, variance preview, close result, confirmed in the database).
Left out on purpose: concurrent multi-till sessions, inventory snapshot at close, audit events, per-user grants. Two small follow-ups if you want them: a confirm step on negative variance, and a shared print helper with day close (skipped to avoid touching that path here).
Delivered and verified on main in merged PR #836 (commit ec08aa008833b9e043af40b8b02eca715be11c5d). Cashiers can open and close cash shifts with opening float tracking, automated variance computation, shift enforcement gates, and session Z printing (main/routes/cash-sessions.ts, main/routes/cash-closures.ts, main/services/shift-session-gate.ts, tests/cash-sessions.test.ts).
Activity
khaira777 commentedon Aug 16, 2026
Verdict: VALID ENHANCEMENT — large; needs product decision before implementation
Findings:
shifts,day_closes, drawer-float, or enforcement logic exists on main (the only "shift" hit is a timezone comment atmain/db.ts:4785). X/Z report menu items (main/index.ts:529-530) just navigate the renderer to the reports page;reports.tshasdaily-stats(main/routes/reports.ts:105) but no business-day close.dateStampInTimezone, see feat: configure invoice numbering #297) and is reusable forlocalDayBoundsUtc-style day boundaries.Suggested scope (MVP first): shifts table + open/close modals with opening float and drawer count + expected-vs-actual variance; then shift enforcement middleware and day-close accounting as separate follow-ups. Overlaps: #278 (cash refunds in day-close expected cash), #287 (SHIFT_START/END audit events), #280 (inventory snapshot at close). Maintainer decision needed: is shift enforcement a desired workflow change (forces open shift before cash transactions)?
itsbkm commentedon Sep 4, 2026
Research follow-up: day-end closing terminology and comparable POS behavior
I reviewed documentation from several established POS systems to compare their day-end closing workflows.
Findings
Product recommendation for FloCafe
“Day close” is the business workflow, but the underlying record should be a cash session/shift, tied to a specific till/register/device. A day can contain multiple tills or multiple shifts, and a shift can cross midnight.
Recommended terminology:
cash_sessionThe MVP close report should include:
Important distinction: a shift/till close reconciles money; a day-end report summarizes business activity. If FloCafe has one till and one daily session, the UI may present this as “Close Day”, but it should still persist a shift/cash-session record underneath.
This research supports the existing issue scope, with the likely implementation sequence:
itsbkm commentedon Sep 21, 2026
Re-scoping check per the stabilization plan: the plan's original instruction was "rewrite against cash_closures" — that table now exists (main/db.ts, migration add_cash_closures) with business_date tracking, and shift_id-based drawer attribution already flows through main/services/refund.ts. So part of this issue's foundation has landed since it was filed.
Full shift lifecycle management is explicitly out of this stabilization milestone's scope (0-5phases.md, "Explicitly not in this milestone: Full shift/cash-session lifecycle"), so this issue correctly stays open — it just needs re-scoping against the current cash_closures foundation rather than a from-scratch design. Labeling state:needs-design; owner scoping needed before implementation starts.
carvalab commentedon Sep 23, 2026
Approach A is implemented in #836, ready for review (branch
shift-lifecycle).What it builds, following the three comments above:
cash_sessionstable (migration v90); closes persist ascash_closuresrows withscope='session', using the extension door this issue anticipated. Day close is untouched.Checks: new 65-test session suite plus the day-close, payments, refunds, reports, and export suites green; lint, build, and i18n checks green; three review rounds with every high and medium fixed; walked end to end in a real browser (open float, live expected, variance preview, close result, confirmed in the database).
Left out on purpose: concurrent multi-till sessions, inventory snapshot at close, audit events, per-user grants. Two small follow-ups if you want them: a confirm step on negative variance, and a shared print helper with day close (skipped to avoid touching that path here).
feat(shifts): cashier shift open/close with variance and session Z (F…
feat(shifts): cashier shift open/close with variance and session Z (#279
khaira777 commentedon Oct 20, 2026
Delivered and verified on
mainin merged PR #836 (commitec08aa008833b9e043af40b8b02eca715be11c5d). Cashiers can open and close cash shifts with opening float tracking, automated variance computation, shift enforcement gates, and session Z printing (main/routes/cash-sessions.ts,main/routes/cash-closures.ts,main/services/shift-session-gate.ts,tests/cash-sessions.test.ts).