POS multi-staff & permissions

Markdown

View as Markdown

POS multi-staff & permissions

A real shop has more than one person at the counter. LaunchMyStore POS supports a shared-drawer shift model so a single register can be passed between cashiers across a business day, with every action attributed to the person who did it.

The role tiers

POS layers a permission scope on top of your store’s broader staff roles. Four tiers:

  • merchant — you, the owner. Everything unlocked.
  • Admin — trusted operations lead. Same caps as merchant for POS.
  • manager — floor manager. Can refund, void, close shifts, cap discount at 50%.
  • staff — cashier. Can ring sales, accept payment, open the drawer for change — but cannot refund, void, or close the shift.

The scope matrix

CapabilityOwnerAdminManagerCashier
RefundYYYN
VoidYYYN
Max discount %UnlimitedUnlimited5010
Open cash drawerYYYY
can_close_shiftYYYN
can_edit_priceYYYN
can_view_activityYYYN
can_pair_hardwareYYYN

All four tiers can open the cash drawer (cashiers need to make change). But only the upper three can close the shift — otherwise a cashier could walk out mid-day and lock the drawer numbers.

Adding POS staff

  1. Open Settings → Staff.
  2. Click Add staff.
  3. Fill in email, name, role (Admin / Manager / Cashier).
  4. Optionally set a POS PIN — a 4-6 digit code the cashier types at the register to clock in. Faster than email + password every shift handoff.
  5. Save. The staffer receives an invite email and lands in your store after accepting.

POS PINs are short-lived (typed at the terminal, never sent to a customer’s browser) and rotate independently of the staff’s admin login password.

The shared-drawer model

One physical register = one shift = one cash drawer. When a second cashier shows up for their afternoon block, they don’t open a new shift — they join the existing one as a contributor.

Each shift tracks its opener plus a list of additional cashiers who joined and (optionally) clocked out. For each contributor, the register records who they are, when they joined, and when they clocked out — preserving the full handoff timeline for the day.

How clock-in works

When Bob arrives mid-day:

  1. Bob taps Switch cashier on the register.
  2. Bob enters his POS PIN.
  3. Backend adds Bob to contributors with the current timestamp.
  4. The cart resets; Bob starts ringing as himself.

Every order from this moment is attributed to Bob. Reports per-cashier work because the active cashier is recorded on every order, refund, and cash movement.

How clock-out works

Bob ends his shift block without closing the day:

  1. Bob taps Clock out.
  2. Backend stamps leftAt on Bob’s contributor entry.
  3. The shift stays open for the next cashier.

Why this matters for “current shift” lookups

The register’s “current shift” lookup matches the shift when you are the opener OR an active contributor. If we filtered owner-only, a cashier who clocked in but didn’t open the shift would see a fake “Shift closed” card right after recording a sale — the cart still has items but the UI thinks no shift exists. The contributor-aware match prevents this.

Force-close: when a cashier abandons the drawer

Sometimes a cashier walks out without closing — or their browser crashes on a flaky tablet and they go home. The shift sits open overnight. A manager can force-close:

  • Endpoint: POST /pos/shifts/:id/force-close
  • Body: { closingDeclared?, reason? } — if closingDeclared is omitted, defaults to the system-computed expectedCash (so variance = 0).
  • The Z-report is generated with forceClosed: true and the reason recorded.
  • A shift.force_close staff-audit row is written so the activity log shows who did it and why.

The force-close UI is rolling out to the admin Shifts list; until then this is a manager-only API call.

Auditing who did what

Every meaningful action writes to the staff audit log:

  • shift.open, shift.close, shift.force_close
  • shift.movement.sale, shift.movement.refund, shift.movement.drop, shift.movement.paid_in, shift.movement.paid_out
  • Order create, refund, void

Open POS → More → Activity (manager-only) to see the day’s timeline grouped by cashier.

Common issues

  • Cashier sees “Shift closed” right after a sale — they never clocked in. Have them tap Switch cashier on the register and enter their PIN.
  • Switching cashier doesn’t reset the cart — the register’s local cart cache persists in the browser. The register flow clears it automatically when you switch cashiers; if you’re scripting tests, clear browser storage between POS identities.
  • Wrong cashier’s name on a receipt — the previous cashier didn’t clock out. The Z-report still attributes correctly per-order.
  • 403 on refund as a cashier — expected. Hand the till to a manager.

FAQ

Can two cashiers share one shift?

Yes — that’s the whole point of the contributor model. The opener is the “owner”; everyone else clocks in as a contributor. The shift is one drawer, but every order is stamped with the cashier who rang it.

Do contributors split the variance at close?

No — variance is per-drawer, not per-cashier. The Z-report attributes orders per cashier so you can see who handled what volume, but the cash count is a single shop-wide number.

What’s the difference between a Manager and an Admin?

Functionally on POS, they’re identical. Admin is a broader admin role on the whole platform (can see store settings, billing). manager is POS-floor scoped. Pick whichever fits the human.

Can I disable the 10% discount cap for cashiers?

Not from the UI. The caps are part of the role definition. Promote the cashier to Manager (50% cap) or Admin (uncapped) if they need more leeway.

Can a cashier reset their own PIN?

Not yet — PIN management is done by an Owner or Admin from Settings → Staff. Self-service PIN reset is on the roadmap.

What if I want manager approval for big discounts but let the cashier ring the sale?

That’s the manager-override pattern. When a cashier hits their cap, the register prompts for a manager PIN; once entered, the discount applies under the manager’s audit trail. The cashier keeps ringing as themselves — only the discount line is attributed to the manager.


Was this article helpful ?