Skip to content

Feature: Shift lifecycle management, cash drawer reconciliation, & business day close #279

Closed

Description

@khaira777

Refs: #370 — POS feature roadmap (Phase 1)

Important

Status: Needs maintainer review — ported from fork codewithsharma/FloCafe (branch develop). Requires maintainer review/approval before implementation.

Operations & Shift Management Feature Request

Extracted from fork codewithsharma/FloCafe (branch: develop):

Overview

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

  1. 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).
  2. 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.
    • Reference: main/services/shift.ts, frontend/src/components/shifts/.
  3. Shift Enforcement Middleware:
    • Option to require an open shift prior to performing cash transactions.
    • Reference: main/middleware/shift-enforcement.ts.
  4. Day Close & Business Date Accounting:
    • Migration 71 (day_closes table storing business date, closed user, and summary JSON).
    • Timezone-safe local day boundary calculation (localDayBoundsUtc) to avoid UTC vs local business day discrepancies.
    • Reference: main/services/day-close.ts.

Acceptance criteria

  • Shift open/close/force-close with opening float and cash-drawer count + variance calculation.
  • Optional shift-enforcement middleware gates cash transactions.
  • day_closes table + timezone-safe local day boundary calculation.

Activity

  1. khaira777 commented on Aug 16, 2026

    @khaira777
    ContributorAuthor

    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)?

  2. itsbkm commented on Sep 4, 2026

    @itsbkm
    Contributor

    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:

    1. Cash session/shift lifecycle with opening float, close count, expected-vs-actual variance, timestamps, and printed summary.
    2. Optional shift enforcement.
    3. Separate business-day close/reporting, including timezone-safe boundaries.
  3. added
    type:featureNew capability or enhancement request
    state:needs-designNeeds a design/scope decision before work starts
    on Sep 21, 2026
  4. itsbkm commented on Sep 21, 2026

    @itsbkm
    Contributor

    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.

  5. carvalab commented on Sep 23, 2026

    @carvalab
    Contributor

    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).

  6. khaira777 commented on Oct 20, 2026

    @khaira777
    ContributorAuthor

    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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:backendBackend (Express/SQLite)area:frontendFrontend (React/Next.js)enhancementNew feature or requeststate:needs-designNeeds a design/scope decision before work startstype:featureNew capability or enhancement request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions