POS shifts: opening, closing, X and Z reports

Markdown

View as Markdown

POS shifts: opening, closing, X and Z reports

A shift is the business day at a register. Every cash sale, refund, drop, and paid-in is bound to one. When you close it, LaunchMyStore freezes a Z-report — the immutable record of the day’s drawer.

The shift lifecycle

  1. Open — declare opening cash float, choose a device and warehouse.
  2. Trade — sell, refund, drop cash, pay-in, pay-out. Cashiers can join the shift as contributors.
  3. X-report (optional, any number of times) — mid-day snapshot, shift stays open.
  4. Close — count the drawer, declare closing cash, generate the Z-report. Shift is now immutable.

Opening cash float

The opening float is the cash you put in the drawer at the start of the day to make change — typically $100 or $200 in mixed denominations. When you open a shift, the register asks for it and stores it as the shift’s opening float.

This number anchors the math at close. The system computes:

expected_cash = opening_float
             + sum(cash sales)
             - sum(cash refunds)
             + sum(paid_in)
             - sum(paid_out)
             - sum(drops)

If your hand-count at close matches expected_cash, your variance is $0 and the drawer balances.

Cash movements during the shift

The five cash-movement types recorded against the shift:

  • sale — auto-created when a cash-tender order posts.
  • refund — auto-created when a cash refund posts.
  • drop — cashier moves cash out of the drawer to the safe.
  • paid_in — cashier adds cash to the drawer (change-fund top-up).
  • paid_out — cashier removes cash for a non-sale reason (petty cash, expense).

Every movement carries an optional reason field. Use it — auditors and your future self will thank you.

X-report: mid-shift snapshot

An X-report is the same shape as a Z-report, but the shift stays open and nothing is persisted. Call it any time during the day to see:

  • Gross sales by tender (cash, card, gift card)
  • Refund and void totals
  • Expected cash currently in the drawer
  • Item count and discount totals

X-reports are great for handoffs (e.g., one cashier hands the drawer to another and they both want to agree on the count) without locking the shift.

Endpoint: GET /pos/shifts/:id/x-report. The shift must be open — closed shifts return 400 Use Z-report for closed shifts.

Z-report: end-of-day, immutable

The Z-report is generated once, at close, and cached on the shift in its zReport field. Re-printing it later returns the same bytes, even if movements are appended afterward (they can’t be — the shift is locked).

How to close a shift

  1. Open the POS tool, go to More → Shift.
  2. Tap Close shift.
  3. Hand-count the cash drawer.
  4. Enter the declared closing cash.
  5. Optionally leave a closing note — required if there is a variance.

At close, the system computes:

  • closingExpected = the formula above.
  • closingDeclared = what you typed.
  • variance = closingDeclared - closingExpected. Negative is short, positive is over.
  • zReport = full structured snapshot, frozen forever.

Reading the Z-report

The Z-report breaks the day down into three groups:

  • Tender totals — cash, card, gift card, split, with counts and amounts.
  • Cash reconciliation — opening, expected, declared, variance.
  • Staff activity — orders per contributor, refunds per contributor.

Multi-staff on one shift

A shift is shared across cashiers via a list of contributors on the shift. The opener is the “owner”; everyone else joins as a contributor with a joinedAt timestamp. When a contributor clocks out, their entry gets a leftAt stamp but is preserved for the audit trail.

This is why the register’s “current shift” lookup matches you whether you opened the shift or joined it as a contributor — a cashier who joined a shift opened by someone else still sees it as their current shift.

Force-close (manager-only)

If a cashier walks out without closing — or the register lost network mid-close — a manager can force-close from the backend (UI for this is coming to the admin). Force-close:

  • Defaults closingDeclared to expectedCash if not provided (variance = 0).
  • Stamps the Z-report with forceClosed: true and the reason.
  • Writes a shift.force_close staff-audit row.

Common issues

  • Variance keeps showing as positive every day — staff is forgetting to record cash paid_out for expenses.
  • Variance is large negative — check for missed refunds, miscounted change, or stolen-cash escalation.
  • “Shift already closed” at close — another cashier or manager closed it from a second device. Pull the Z-report instead.

FAQ

Can I edit a Z-report after the fact?

No. Once a shift is closed, the Z-report is immutable. If you noticed an error, post a correcting cash movement on a future shift with a clear reason note, or void/refund the offending order.

How many X-reports can I run?

As many as you like. X-reports are read-only snapshots and don’t change shift state.

What if I forgot to set an opening float?

The shift opens with a float of $0. Your expected cash will be off by the real opening amount — just declare it via a paid_in movement at the start of the day, with reason “Opening float correction”.

Where do I see end-of-day totals?

The Z-report card appears in the POS tool the moment you close the shift. Closed shifts also show up under Orders → Shifts history with their Z-reports re-printable on demand.

Can two shifts be open on the same register at the same time?

No. Only one open shift is allowed per register at a time — a new cashier opening on the same register joins the existing shift as a contributor instead of starting a fresh one.

What happens if power dies mid-sale?

The order isn’t persisted until the backend confirms. On reconnect, the cart is restored from the register’s local cache and you re-tender. Inventory and cash are never decremented for a sale that didn’t finalize.


Was this article helpful ?