obsidian-vault/Infra-Network/SPEC-ACCOUNT-RECEIVABLES.md

259 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SPEC — Account Receivables / Credit Book / Period dashboard
**Data:** 2026-09-08 → 2026-09-09 (noite)
**Status:** implementado na VM500 (`rentcharge-backend` + `rentcharge-frontend`)
**Produto:** RentCharge / RenteCharge Weekly & Arrears
**Operador:** Roger
**Relacionados:** `SPEC-VM500-RENTCHARGE.md` (infra) · `PROJECT-RENTCHARGE.md` (produto) · Rules UI `/rules` secção **12. Credit Book (R-CB01…R-CB05)** · **`SPEC-AR-QR-BINARY-EYE.md`** (cartões QR 1–50 + Binary Eye — draft) · **`SPEC-TRANSACTION-IDS.md`** (prefixos ME/KC/EL/DN/LY · CR/CT · hash ROI)
---
## 1. Escopo desta noite
Módulo **Account Receivables** (ancillary, ≠ rent SA / arrears):
- Meals (Lunch / Dinner / Cup of tea)
- Access key
- Electricity top-up
Canais:
| Canal (código) | Label IE | Cor |
|----------------|----------|-----|
| `cash` | Cash sale | Verde |
| `credit` | Credit sale (ex-fiado) | Vermelho |
| `credit_payment` | Credit settlement | Azul |
Glossário contabilístico (Irlanda):
| Conceito | Termo canónico |
|----------|----------------|
| Fiado | **Credit sale** |
| Pagamento do fiado | **Credit settlement** |
| Crédito a haver (pagou a mais) | **Over-settlement** |
| Ainda a limpar | **To clear** |
| Status | Clear · Outstanding · Over-settlement |
---
## 2. Credit Book — saldo assinado (R-CB01…R-CB05)
### Fórmula
```
signed_balance = Σ credit sales − Σ credit settlements
```
| signed_balance | UI | Cor |
|----------------|----|-----|
| `> 0` | **To clear** / status **Outstanding** | Vermelho |
| `< 0` | **Over-settlement** | Azul |
| `≈ 0` | **Clear** | Neutro |
Helpers: `backend/app/services/ledger.py` → `credit_book_balance`, `credit_book_position`.
### R-CB02 — Settlement pode criar over-settlement
Exemplo: deve €25, paga €50 settlement → limpa €25; sobra **€25 over-settlement** (signed −€25).
Cash do settlement entra no remittance ROI Finance; o surplus fica no Credit Book (não é crédito de rent).
**Implementação:** deixou de bloquear `credit_payment > to_clear`.
### R-CB03 — Novos tickets consomem over-settlement primeiro
Novo **Credit sale** (meals / key / electricity) com over-settlement existente: o lançamento move o saldo em direção a zero; só o excedente vira **Outstanding**.
### R-CB04 — Credit consumption statuses
Clear · Outstanding · Over-settlement (filtro + cores no report).
### R-CB05 — Modal Post sale
Mostra **To clear** (vermelho) + **Over-settlement** (azul) do residente seleccionado + stamp + hints R-CB02/03.
Documentado também em `/rules` secção 12.
---
## 3. APIs ledger
Base: `/api/ledger/…` · auth: utilizador logado; create/edit/delete: `require_payment_editor` (`can_edit_payments` / superuser).
| Método | Path | Notas |
|--------|------|-------|
| GET | `/api/ledger/accounts` | Catálogo MEALS_* / ACCESS_KEY / ELEC_TOPUP |
| GET | `/api/ledger/entries` | Filtros date/resident/account/channel |
| POST | `/api/ledger/entries` | Create; stamp week/weekday/time |
| PUT | `/api/ledger/entries/{id}` | Edit + `confirm_password` |
| POST | `/api/ledger/entries/{id}/delete` | Delete + `confirm_password` |
| GET | `/api/ledger/credit-book` | Overview + `to_clear` / `credit_available` / `status` |
| GET | `/api/residents/{id}/credit-book` | Posição + entries |
| GET | `/api/ledger/reports/roi-finance` | Pack ROI Finance |
| GET | `/api/ledger/reports/credit-consumption` | Credit report |
| GET | `/api/ledger/reports/roi-finance` | Pack JSON ROI Finance |
| GET | `/api/ledger/reports/roi-finance/pack` | **A4 remittance pack HTML** (print) |
| GET | `/api/brand/sa-shield` | Escudo Salvation Army (PNG) |
| GET | `/api/ledger/reports/payables-remittance` | Remittance view |
Tabela: `service_ledger_entries`.
**Public Txn id:** ver **`SPEC-TRANSACTION-IDS.md`**. Cash sale manual → curto **`000000-AA`** padded (`000084-ME`, `000010-EL`, …). Credit sale → `CR-…`. Credit settlement → `CT-…`. Import mantém ids do ficheiro.
Edit/delete: mesma matriz de acesso que pagamentos de rent (`User.can_edit_payments`); password do utilizador obrigatória.
---
## 4. Stamp padrão (todo lançamento AR)
Em create/list/UI:
- Dia da semana (Mon…Sun)
- Semana ISO `Wxx/yyyy`
- Hora `HH:MM` (`created_at`)
Campo composto: `stamp` (ex.: `Tue · W37/2026 · 23:58`).
Modal mostra preview live antes do post.
---
## 5. UI — Account Receivables `/receivables`
- Layout estilo dashboard Residents (grelha + painel Credit Book)
- Nav colorida: Receivables · Payables · ROI Finance · Credit report
- Botões: **+ Cash sale** (verde) · **+ Credit sale** (vermelho) · **+ Credit settlement** (azul)
- Modal Post sale / credit / settlement com tabs coloridas
- Coluna Stamp; Actions Edit / Delete (senha)
- Painel lateral: saldos Credit Book (Outstanding vermelho / Over-settlement azul)
---
## 6. UI — ROI Finance report `/receivables/roi-finance`
### Cards (drill-down → modal de lançamentos)
| Card | Cor | Conteúdo |
|------|-----|----------|
| Rent cash | Verde | SAGE SA cash no range |
| Ancillary cash | Verde | Cash meals/keys/elec |
| Credit settlements | Azul | Cash que limpa Credit Book |
| Credit sales | Vermelho | Credit sales (≠ cash till) |
| Credit net | Cinza / ± cor | Sales − Settlements |
| Total cash to ROI Finance | Verde | Rent + ancillary cash + settlements |
**Regra remittance:** Total cash = rent + ancillary cash + settlements.
Credit sales **não** entram no cash to ROI Finance.
Credit net = movimento do livro (≠ dinheiro físico).
### By account (colunas)
Account · Cash · Credit sales · Settlements · **Remit to ROI Finance** · **Credit net** · Family · (footer Total)
- Remit to ROI Finance = Cash + Settlements
- Credit net = Credit sales − Settlements (+ vermelho / − azul)
### By resident
Room · Resident · Rent cash · Ancillary cash · Credit sales · Credit paid · Total cash
### A4 remittance pack (print)
UI fields on the same page + **Print ROI Finance pack (A4)**:
| Campo UI | No documento |
|----------|--------------|
| Bank logbook no. | Controlo depósito / livro banco |
| Brinks Priority Bag no. | Selo Priority Bag |
| Brinks Malote / collection bag no. | Malote / bag de coleta Brinks |
| Manager 1 / Manager 2 / Prepared by | Três blocos de assinatura |
Documento HTML A4 (~98% da folha):
- Letterhead **The Salvation Army** + escudo oficial (`sa-shield-white-bg.png`, embutido base64)
- Período do material (From → To)
- KPIs: Rent cash · Ancillary cash · Settlements · Credit sales · Credit net · Cash to ROI Finance
- Tabela **Accounts remittance schedule** (todas as contas + Remit to ROI Finance + Credit net)
- Tabela **Resident cash detail** (linhas com movimento)
- Nota contabilística (cash ≠ credit sales; R-CB02/03)
- Assinaturas: Manager 1 · Manager 2 · Prepared / presented by
- Rodapé SA vermelho com total cash + período + ref `ROI-FINANCE-YYYYMMDD-YYYYMMDD`
**API:** `GET /api/ledger/reports/head-office/pack` (HTML, auth cookie)
**Template:** `backend/app/templates/ho_remittance_pack.html`
**Brand:** `GET /api/brand/sa-shield` · `backend/app/static/brand/`
---
## 7. UI — Credit consumption report `/receivables/credit-report`
- Head período: Opening · Issued (vermelho) · Paid (azul) · Closing (cards clicáveis)
- Botão **Today** + Generate
- Grelha estilo Residents: # · Room · SAGE · Name · Staff · Opening · Issued · Paid · Closing · Status · View
- Filtros por coluna; Status inclui **Over-settlement**
- Closing &lt; 0 mostrado como over-settlement (azul)
- Lista todos os residentes activos (+ inactivos com movimento)
---
## 8. UI — Period dashboard (ficha residente)
### Cards principais (5)
1. **Should have paid by now** — weeks × weekly due
2. **Actually paid** — cash SA no período (verde)
3. **Arrears / Positive balance** — paid − due (vermelho se − / azul se +)
4. **% vs amount due** — variance % + liquidation %
5. **Still to pay to year-end (W52/53)**
Removido o bloco duplicado “Period position” (Should/Actually/Arrears/%).
### Other balances (4 cards)
1. **Prior years unpaid** — preview agreement cut-off dia anterior ao From; link Payment map
2. **Credit Book · to clear** — vermelho; link Credit consumption
3. **Credit Book · over-settlement** — azul; link Receivables
4. **Agreements** — balance activo(s); link `#agreements-panel`
---
## 9. Payables
`/payables` — remittance view (cash + settlements por conta) alinhado ao ROI Finance.
---
## 10. Ficheiros tocados (noite)
Backend:
- `backend/app/services/ledger.py` (`render_ho_remittance_pack`, Credit Book helpers)
- `backend/app/modules/ledger/router.py` (`/roi-finance/pack`)
- `backend/app/templates/ho_remittance_pack.html`
- `backend/app/main.py` (`/api/brand/sa-shield`)
- `backend/app/database.py` (`ServiceLedgerEntry` — já existente)
Frontend:
- `frontend/src/app/receivables/page.tsx`
- `frontend/src/app/receivables/roi-finance/page.tsx` (pack fields + Print A4)
- `frontend/src/app/receivables/credit-report/page.tsx`
- `frontend/src/app/payables/page.tsx`
- `frontend/src/app/residents/[id]/page.tsx`
- `frontend/src/app/rules/page.tsx` (secção 12)
- `frontend/src/lib/api.ts` (`openRoiFinancePack`)
Docs:
- Este ficheiro: `docs/SPEC-ACCOUNT-RECEIVABLES.md`
---
## 11. Checklist agente (AR)
1. Nunca misturar Credit Book com rent arrears / SAGE SA.
2. Total cash to ROI Finance = rent cash + ancillary cash + settlements (não inclui credit sales).
3. Over-settlement = settlement &gt; to clear; novos credit sales consomem primeiro.
4. Edit/delete ledger = senha + `can_edit_payments`.
5. Stamp Mon–Sun week + hora em todo post AR.
6. Cores: cash verde · credit sale vermelho · settlement azul · over-settlement azul.
7. Rebuild frontend sem `.env.local`; restart `rentcharge-backend` + `rentcharge-frontend`.