# DALSEEN — Decision Register (D1–D11)

> **Verified accurate:** 2026-05-02 — created today as the canonical home for D1–D11; all sibling docs (POS-flow, onboarding-chain, shifts-day-close, BACKEND-MAPPING, ACCOUNTING-AUDIT) now resolve their D-references here.
> **Status:** active source-of-truth doc; the D-register every other handoff cites.

> **Document type:** canonical decision register. Cited from every endpoint-mapping handoff doc.
> **Last updated:** 2026-05-02
> **Status:** D1–D10 signed off **owner, 2026-04-27** (per `POS-flow-endpoint-mapping.md §7`). D11 signed off **owner, 2026-04-29** (per `shifts-day-close-endpoint-mapping.md §6`).
> **Authority:** When Postman fixtures, OpenAPI shapes, or older draft docs contradict a row here, **this register wins**.

This file consolidates the D-numbered decisions previously scattered across `README.md`, `POS-flow-endpoint-mapping.md §7`, and inline notes in the four endpoint-mapping docs (`POS-flow-endpoint-mapping.md`, `onboarding-chain-endpoint-mapping.md`, `shifts-day-close-endpoint-mapping.md`, `ACCOUNTING-AUDIT.md`). Those docs cite D-numbers; this is where the full text lives.

---

## §5a — Canonical D1–D11 list

The "§5a" anchor is referenced from many docs by historical convention; it points to the table immediately below.

| # | Topic | Locked decision | Status |
|---|---|---|---|
| **D1** | Envelope + IDs | **ULIDs** (26-char strings, sortable). Success envelope: `{ data, meta }`. Error envelope: `{ error: { code, message_en, message_ar, fields? } }`. Client never mints server-owned IDs. | ✅ Approved 2026-04-27 |
| **D2** | Money in JSON | Always `{ amount_minor, currency_code }`. Halalas in `amount_minor` (5600 = 56.00 SAR). Bigint in DB. **No SAR floats.** Display-format on client only. | ✅ Approved 2026-04-27 |
| **D3** | `/me` permissions | `roles[]` + `permissions[]` — **flat strings**, server-resolved (Spatie or equivalent). Frontend gates use `permissions.includes('...')`. Errors carry both `message_en` + `message_ar`. | ✅ Approved 2026-04-27 |
| **D4** | Login branches | `branches: [{ id }]` only on `/auth/login` response. Full DTOs come from `/me` and `/me/branches`. | ✅ Approved 2026-04-27 |
| **D5** | Tender catalog | `GET /tenders` returns the canonical 9-code list with all flags (cash, mada, visa, mastercard, amex, stc_pay, apple_pay, gift_card, store_credit). Per-branch flags govern which tenders are accepted. | ✅ Approved 2026-04-27 |
| **D6** | JE auto-post | Voids, refunds, and credit-notes always emit a journal entry in the same DB transaction as the source record. Response includes `journal_entry_id`. | ✅ Approved 2026-04-27 |
| **D7** | Receipt sharing | `POST /sales/{id}/share` body `{ channel: 'whatsapp' \| 'email', recipient }` returns 202. Async delivery; client doesn't block. | ✅ Approved 2026-04-27 |
| **D8** | Idempotency | All POST/PATCH/PUT/DELETE accept `Idempotency-Key` (UUID v4). Replay with same body = same response (cached 24h). Replay with different body = 409 `idempotency.conflict`. | ✅ Approved 2026-04-27 |
| **D9** | Shift discovery | `GET /shifts/current` returns `{ data: null }` (NOT 404) when no open shift. POS shell depends on this contract. | ✅ Approved 2026-04-27 |
| **D10** | Bilingual fields | **Pattern A** — `name_ar` + `name_en` siblings — for indexed/searchable names. **Pattern B** — `{ ar, en }` JSON object — for prose (descriptions, notes, narrations). Per `02-CONVENTIONS.md § Bilingual`. Setup-progress is **derived**, not stored — computed from domain state on each `GET /me/setup-progress` call. | ✅ Approved 2026-04-27 |
| **D11** | Cashier-immediate refund | `POST /sales/{id}/refund` exists as a lightweight cashier-floor path. **Same-shift only.** Cross-shift refunds force the RMA path. Independent of accounting `credit-notes` (the back-office bookkeeping trail). | ✅ Approved 2026-04-29 |

---

## §0 — Required headers (all tenant routes)

```http
Authorization:   Bearer {token}
Accept:          application/json
Accept-Language: ar | en
Content-Type:    application/json     ← writes only
X-Branch-Id:     {ULID}               ← branch-scoped routes
Idempotency-Key: {UUID v4}            ← all POST/PATCH/PUT/DELETE
```

`X-Branch-Id` is required on `/sales`, `/shifts/*`, `/orders`, `/inventory/adjustments`, `/grns`, and any other branch-scoped resource.

---

## §1 — How to cite a decision

In any new mapping doc:

```markdown
**Decisions applied:** D1 ULIDs, D2 Money, D10A `name_ar`/`name_en`.
```

…and link back here for the full text:

```markdown
See [`DECISIONS.md §5a`](./DECISIONS.md) for the canonical D1–D11 list.
```

This keeps every doc thin on convention boilerplate and consistent on the authoritative wording.

---

## §2 — D11 detail (POS lane refund vs accounting credit-note)

D11 is the only decision that frequently confuses readers, so it gets extra treatment here.

**D11 governs the POS register's immediate same-tender refund** (and its async RMA fallback when the refund is cross-shift). It does **not** govern the Accounting `refund.issue` flow or the `credit-notes` resource — those are the back-office bookkeeping trail and run on different endpoints.

The two flows can fire for the same physical return:
- **D11 path** — `POST /sales/{id}/refund` — handles the customer-facing reversal at the lane (cash back to customer, card reversal to acquirer).
- **Accounting path** — `POST /accounting/credit-notes` — records the bookkeeping side (DR Sales Returns, CR AR or Cash; DR VAT Output reversal).

When `POST /sales/{id}/refund` succeeds, the backend auto-emits the matching credit-note + JE per D6.

For the full state-machine, error contract, and migration shape, see `shifts-day-close-endpoint-mapping.md §6`.

---

## §3 — Change log

| Date | What | Doc that approved it |
|---|---|---|
| 2026-04-27 | D1–D10 signed off | `POS-flow-endpoint-mapping.md §7` |
| 2026-04-29 | D11 added (cashier-immediate refund) | `shifts-day-close-endpoint-mapping.md §6` |
| 2026-05-02 | This `DECISIONS.md` file created — consolidates references previously scattered across `README.md` table + `POS-flow-endpoint-mapping.md §7`. No D-rows changed; just centralized. | this commit |

---

## §4 — Where to add D12+

When a new convention needs to be locked:

1. Propose it in the relevant flow-mapping doc with a "**Decision proposed**" callout.
2. Once owner approves, add a new row to the table in §5a above.
3. Add an entry to §3 (Change log).
4. Update `README.md` recap table.
5. Update `BACKEND-MAPPING.md` if any endpoint rows reference the new D-number.

---

## §5 — Related authoritative docs

- `README.md` — on-ramp summary table (mirrors §5a above).
- `POS-flow-endpoint-mapping.md §7` — original sign-off narrative for D1–D10.
- `shifts-day-close-endpoint-mapping.md §6` — D11 narrative + state machine.
- `BACKEND-MAPPING.md` — every endpoint row carries a D-number column referencing this register.
- `docs/02-CONVENTIONS.md` (backend repo `Mohamkh93/DS-PL`) — the implementation spec these decisions instantiate.
