obsidian-vault/Infra-Network/SPEC-TRANSACTION-IDS.md

101 lines
3.7 KiB
Markdown

# SPEC — Public transaction IDs (Txn) & Invoice / Ticket
**Date:** 2026-09-19 (rev. short suffix)
**Status:** implemented (prod + test)
**Operator:** Roger
**Code:** `backend/app/services/ledger.py` → `account_manual_suffix`, `allocate_short_txn_id`, `new_transaction_id`, `payment_txn_hash`
**Related:** `SPEC-ACCOUNT-RECEIVABLES.md` · `SPEC-PAYMENTS-MAP-WEEK-PRINT.md` · EOD/EOW / ROI line hash
---
## 1. Purpose
Every cash / credit-book movement has a **public Txn id** for audit screens (mapa “All cash payments”, receivables, EOD).
Separately, the operator may enter an **Invoice / Ticket** (optional free text / imported ticket number).
| Field | Meaning |
|-------|---------|
| **Txn** (`transaction_id` / rent `txn_no`) | System public id — unique in DB — **short** |
| **Invoice / Ticket** (`ticket_number`) | Optional number entered or imported |
| **Hash** (`txn_hash` / EOD `line_hash`) | 16-char SHA-256 fingerprint (ROI/EOD formula) |
---
## 2. Rent (SAGE SA)
| Source | Receipt No (`txn_no`) | Ref (`txn_ref`) |
|--------|----------------------|-----------------|
| **Import** | Keep file values unchanged | Keep file values unchanged |
| **Manual** | `NNNNNN-M` (sequential, unique) | `02_XXXXXX` (sequential, unique) |
Examples: `302108-M`, `302084-3M`.
At payment post, rent stores `payments.txn_hash` (`source=payment`, `account=RENT`, `invoice=txn_no`).
---
## 3. Ancillary cash — short suffix (same shape as rent)
**Canonical format:** `NNNNNN-AA` — **always 6 zero-padded digits**, hyphen, **2-letter suffix** (9 characters total).
Examples: `000075-ME`, `000010-EL`, `000001-KC`.
**Not** `75-ME` and **not** `ME-YYYYMMDD-HEX`.
| Account family | Suffix | Example |
|----------------|--------|---------|
| Meals (`MEALS_*`) | **ME** | `000012-ME` |
| Access key (`ACCESS_KEY`) | **KC** | `000003-KC` |
| Electricity (`ELEC_*`) | **EL** | `000007-EL` |
| Donation (`DONATION`) | **DN** | `000001-DN` |
| Laundry (`LAUNDRY_*`) | **LY** | `000001-LY` |
- Sequence is **per suffix** (meals and electricity each have their own counter).
- Allocated at post via `allocate_short_txn_id` / `new_transaction_id(..., account_code=…, db=…)`.
- **Import:** keep file ids unchanged.
### Credit Book (unchanged long channel ids)
| Channel | Prefix | Example |
|---------|--------|---------|
| `credit` | **CR** | `CR-20260918-A1B2C3` |
| `credit_payment` | **CT** | `CT-20260918-D4E5F6` |
---
## 4. Hash (ROI / EOD fingerprint)
```
line_hash = sha256(
source | source_id | amount(2dp) | account | invoice | received_at
)[:16].upper()
```
- **invoice** = public Txn id (`transaction_id` or rent `txn_no`).
- Changing a Txn id changes the live hash → regenerate frozen EOD/EOW if ids are migrated.
---
## 5. Week Payments Maps
| Section | Shows Txn / Hash / Ticket? |
|---------|----------------------------|
| **Residents in period** | No — `weekly due` / `cash done` / prior weeks |
| **All cash payments in this period** | Yes — Hash, Invoice/Ticket, **Txn** (short), Time (rent only), Rent € / Other € / Total € |
---
## 6. Migrations
1. `CS-YYYYMMDD-HEX` → account long prefix `ME-…` / `EL-…` (intermediate).
2. Long `ME-…` / `EL-…` / `LY-…` → short `NNNNNN-ME` / `-EL` / `-LY` (this revision).
3. Prod EOD books regenerated after each rewrite; backups under `backend/data/*_pre_txn_*rewrite_*.db`.
---
## 7. Acceptance
1. New cash meal → Txn matches `^\d{6}-ME$` (e.g. `000015-ME`).
2. New electricity → `^\d{6}-EL$`; key → `^\d{6}-KC$`.
3. Rent manual still `…-M`; credit sale `CR-…`; settlement `CT-…`.
4. Mapa **Txn** column shows 9-char codes (`000075-ME`) next to rent `…-M`.
5. EOD / mapa Hash align for the same movement.