# 06 — Cash & Shifts

In a cash-dominant market with five branches the owner cannot visit, **shift control is the
primary loss-prevention mechanism**. Its purpose is to make one number visible every day
per branch: **cash variance**.

---

## 1. Shift

A cashier session on one device, with a counted start and a counted end.

| Field | Notes |
|---|---|
| `id`, `branch_id`, `device_id` | |
| `opened_by_user_id`, `opened_at`, `opening_float` | Counted cash placed in the drawer at start |
| `closed_by_user_id`, `closed_at` | |
| `counted_cash` | Physically counted at close, entered by denomination |
| `expected_cash` | Computed — see §3 |
| `variance` | `counted_cash − expected_cash` |
| `variance_reason`, `approved_by_user_id` | Required when variance exceeds tolerance |
| `status` | `open` / `closed` / `pending_review` / `reviewed` |
| `business_day` | |

### Hard rules

1. **No sale can be created outside an open shift.** The POS refuses and prompts to open one.
2. **One open shift per device at a time.** Two cashiers on one drawer makes variance
   unattributable — which is exactly what a dishonest cashier wants. With a single terminal
   per branch ([10 §9](10-cross-cutting-rules.md)) this means **one open shift per branch**,
   so shift handover is the only way cashiers change.
3. **A shift cannot be reopened once closed.** Corrections are adjustment records.
4. **The opening float must be counted and entered**, not defaulted. A defaulted float
   makes the closing variance meaningless.
5. **A shift belongs to a single business day.** A shift crossing the branch cutoff is
   flagged; the branch decides whether to enforce a hard close.

### Handover

When cashiers change mid-day, the correct action is **close the shift and open a new one**
with a counted float. A "user switch without recount" option exists but is off by default —
it saves two minutes and destroys accountability.

---

## 2. Cash drawer movements

Everything that moves cash other than a sale.

| Movement | Direction | Notes |
|---|---|---|
| `opening_float` | In | Counted at open |
| `sale_cash` | In | Automatic from cash tenders |
| `account_payment` | In | Tenant settling an invoice at the counter — **must be included** |
| `refund_cash` | Out | Requires approval |
| `pay_out` | Out | Paying a supplier/expense from the till. Reason + category + optional receipt photo. |
| `cash_drop` | Out | Moving cash to the safe mid-shift, to cap drawer exposure |
| `bank_deposit` | Out | Cash leaving for the bank |
| `float_adjustment` | Either | Correcting the float, approval required |

Each movement records `user_id`, `approved_by_user_id?`, `reason_code`, `amount`,
`timestamp`, and is audited.

**No-sale drawer opening** is itself a recorded event with a reason. Frequency per cashier
is a standing report — an unusually high count is a classic theft indicator.

---

## 3. Expected cash

```
expected_cash =   opening_float
                + cash sales
                + cash account payments received
                − cash refunds
                − pay-outs
                − cash drops
                − bank deposits
```

Non-cash tenders (card, wallet, transfer, on-account) are **excluded** — they are
reconciled separately.

### Close-of-shift screen

```
Denomination count:  50,000 × __   25,000 × __   10,000 × __
                      5,000 × __    1,000 × __      500 × __   250 × __

Counted cash        ____________
Expected cash       ____________   (revealed AFTER counting — see below)
Variance            ____________
```

**Blind close is the default.** The cashier counts and enters the cash *before* the system
reveals the expected figure. If the expected number is shown first, the count is written to
match it and the control is worthless. Managers see both immediately.

### Tolerance

| Variance | Behaviour |
|---|---|
| Within tolerance (e.g. ±1,000 IQD) | Shift closes normally |
| Beyond tolerance | `pending_review`; reason mandatory; manager approval required |
| Beyond hard threshold | Escalated to Owner automatically |

Tolerance is configurable per branch. It should never be zero — cash rounding alone
produces small differences (see doc 10 §2).

---

## 4. Non-cash reconciliation

| Tender | Reconciled against | Frequency |
|---|---|---|
| Card | Card terminal batch total | Per shift |
| Wallet | Provider statement / app total | Daily |
| Bank transfer | Bank statement | Daily or weekly |
| On-account | Charges posted to accounts | Automatic — always exact by construction |

Each produces a `reconciliation` record with `expected`, `actual`, `difference`, `note`,
`reconciled_by`. Differences follow the same review path as cash variance.

---

## 5. Business day close

Per branch, after the last shift closes and past `business_day_cutoff`:

1. All shifts for the day must be closed. Any still open blocks the day close and alerts
   the manager.
2. **Z-report** generated and frozen: gross sales, discounts, voids, refunds, net sales,
   tender breakdown, on-account total, order count, average ticket, items sold, prep-time
   average, cash variance.
3. Stock deductions for the day are finalised.
4. Daily-cycle accounts are picked up by the billing run (doc 05).
5. The day is marked closed. **Post-close entries are prohibited** — a late-arriving offline
   order posts to the next open day with a `late_arrival` flag.

The Z-report is an immutable snapshot. It is the document the owner reads each morning, and
it must not change retroactively when a straggler syncs.

---

## 6. Anti-fraud reporting (this module's real output)

| Report | Signal it exposes |
|---|---|
| **Variance by cashier over time** | Consistent small shortages — the most common pattern |
| **Variance by branch** | Which branch needs attention |
| **No-sale drawer opens per cashier per shift** | Drawer access without a transaction |
| **Voids by cashier** (count, value, % of sales) | Ringing up, taking cash, voiding after |
| **Discounts by cashier** | Unauthorised "friend pricing" |
| **Refunds by cashier**, especially cash refunds against card sales | Classic cash extraction route |
| **Pay-outs by cashier** without a receipt attached | Fictitious expenses |
| **Orders voided after being marked READY** | Goods left the counter without payment |
| **Shifts closed with zero variance, always** | Statistically implausible; suggests the count is being back-fitted |

These reports are **automatic and comparative across the five branches**. Their value comes
from ranking branches and cashiers against each other, not from absolute thresholds.
