diff --git a/Infra-Network/SPEC-ACCOUNT-RECEIVABLES.md b/Infra-Network/SPEC-ACCOUNT-RECEIVABLES.md new file mode 100644 index 0000000..b8b8bab --- /dev/null +++ b/Infra-Network/SPEC-ACCOUNT-RECEIVABLES.md @@ -0,0 +1,259 @@ +# 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 < 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 > 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`.