# User Stories — TinyPOS (`tnx-pos`)

> Produced by the Reversa **Writer** (phase: generation) · doc_level: `complete`
> Generated on 2026-09-21

**Confidence scale:** 🟢 CONFIRMED (read directly from code) · 🟡 INFERRED (pattern-based, may be wrong) · 🔴 GAP (needs human validation)

This directory is the **behavioural view** of the system: what each actor is trying to achieve, told as user stories with `Given / When / Then` acceptance criteria. It is a global artifact — it re-tells the same facts already captured per-endpoint in the 23 unit folders (`requirements.md` / `design.md` / `tasks.md` / `contracts.md`) and in `openapi/tnx-pos.yaml`, but organised by **journey** instead of by route. Every story traces back to the unit(s) that own the mechanics, and confidence markers carry through from those units.

These stories describe the **legacy system as it behaves today** — they are reverse-engineered, not aspirational. Where the current behaviour is a defect or an open question, it is recorded as a 🔴/🟡 note on the story rather than silently corrected.

---

## Actors

| Actor | Kind | Role in the stories | Confidence |
|-------|------|---------------------|------------|
| **Store Administrator** (cashier / owner) | Person | The **only** system user. Operates the POS terminal and the entire back-office. There is a single Encore\Admin `Administrator` role and authorization is authenticate-only — every authenticated admin can do everything. | 🟢 (`permissions.md`, ADR-0009) |
| **Shopper / Customer** | Person (indirect) | Physically shops and is served at the terminal by the Administrator. Has **no login**; exists only as a `customers` CRM record used for pricing tier, loyalty points and debt. Never an authenticated actor in any story. | 🟢 (`c4-context.md`) |
| **Scheduler / Cron** | System | Runs `Order::summaryLogging` nightly to rebuild the `customer_order_summary` read model that the statistics stories read. | 🟢 (`app/Console/Kernel.php`, ADR-0005) |
| **Operator** (deploy-time) | Person | The same human as the Administrator, acting to run database migrations over HTTP (`GET /artisan`). Called out separately because the intent is maintenance, not shop operation. | 🟡 (`maintenance.md`) |

> Because access control collapses to "authenticated admin, or not" (🟢, ADR-0009), the stories deliberately do **not** invent role-based variants. Every story below is performed by the one Administrator persona unless it explicitly names the Scheduler.

---

## Story map (journeys → unit coverage)

| Journey file | What it covers | Owning units |
|--------------|----------------|--------------|
| [authentication.md](authentication.md) | Sign in, sign out, change own password | `auth` |
| [point-of-sale.md](point-of-sale.md) | The daily checkout: scan, build cart, pick customer, price by tier, discount, partial debt, park as draft or finalise, print receipt, resume a draft | `pos-terminal`, `pos-scan`, `products-pricing`, `customers-scan`, `orders-crud`, `orders-scan`, `orders-print` |
| [order-management.md](order-management.md) | Back-office order list, detail, re-print, note editing, deletion with reversals | `orders-crud`, `orders-print`, `orders-note`, `orders-scan` |
| [product-catalog.md](product-catalog.md) | Product master data: create/edit/list/soft-delete, multi-unit conversions, wholesale tiers, expiry filter | `products-catalog`, `products-pricing` |
| [customer-management.md](customer-management.md) | CRM: create/edit/list/soft-delete customers, POS quick-add, purchase history, per-customer statistics | `customers-crud`, `customers-scan`, `customers-purchase-history`, `customers-statistics` |
| [accounts-receivable.md](accounts-receivable.md) | Debt: debtor overview, per-customer ledger, record manual debt, record repayment | `debts`, `customers-debt-actions` |
| [loyalty-and-gifts.md](loyalty-and-gifts.md) | Points-for-gifts: gift catalogue, availability pre-flight, redemption, redemption history | `gifts-crud`, `gifts-scan`, `customers-loyalty` |
| [reference-data.md](reference-data.md) | Brands, categories, measurement units admin | `brands`, `categories`, `units` |
| [reporting.md](reporting.md) | Home dashboard KPIs and sales chart | `dashboard` |
| [maintenance.md](maintenance.md) | Run database migrations over HTTP | `artisan-migrate` |

All 23 units are represented. `customers-statistics` appears in both customer-management (the screen) and is fed by the Scheduler journey noted above.

---

## How to read a story

Each story uses:

```
### US-<area>-<n> — <title>

**As a** <actor>, **I want** <capability>, **so that** <business value>.

- **Given** <precondition>
- **When** <action>
- **Then** <observable outcome>   🟢/🟡/🔴

Notes / gaps: ...
Traces to: <unit>/ (<file/route>)
```

The `Traces to` line is the contract: for the authoritative field-level rules, validation, and error strings, open the referenced unit folder. Vietnamese UI strings are reproduced verbatim where they are part of the observable contract (toastr messages, validation errors); all surrounding prose is in English.
