obsidian-vault/Infra-Network/PROJECT-RENTCHARGE.md

140 lines
5.9 KiB
Markdown
Raw 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.

# PROJECT — Rent and Charge (Weekly and Arrears)
Produto de cobrança semanal de aluguel e atrasos (arrears) para hostel/residência Granby Lifehouse (quartos, SAGE, staff).
**Atualizado:** 2026-09-19 · **Versão:** **006.2026**
**SPEC infra:** `SPEC-VM500-RENTCHARGE.md`
**SPEC AR / Credit Book:** `SPEC-ACCOUNT-RECEIVABLES.md`
**SPEC Txn / Ticket:** `SPEC-TRANSACTION-IDS.md`
**SPEC MAP WEEK:** `SPEC-PAYMENTS-MAP-WEEK-PRINT.md`
**Sessões:** `SPEC-SESSION-2026-09-18.md` · `SPEC-SESSION-2026-09-19.md`
**App:** https://rentcharge.itecnologys.com · Forgejo: https://git.itecnologys.com/myvexx/rently
## O que o sistema faz (escopo actual)
- Lista residentes / quartos (padrão SAGE: filtros por coluna, `#`, Room estreita, badges NP / Name dup / Room conflict)
- Valor semanal devido via **charge bands** (RENT_35/40/41/45/65, FB_85/91, BANK_ACCOUNT, FLEXIBLE_FB)
- **Pagamentos:** fonte única = exports SAGE *Customer Invoices Due* (não o Excel de arrears)
- Totais do mês / ano; statements HTML/PDF; debit letter; agreements
- UI: Residents, Reporting (mesmo layout), Settings, ficha do residente com grelha de pagamentos
- **Account Receivables:** cash / credit sale / settlement (meals, keys, electricity); Credit Book com **over-settlement**; ROI Finance + Credit consumption; Period dashboard (due vs paid vs % + other balances)
- Utilizadores: registo público com código de e-mail, recuperação de senha, sessões revogáveis e auditoria no menu Admin
- Infra: VM500 BIG + Traefik CT120 + Cloudflare Tunnel
## Stack
- Backend FastAPI + SQLite (`arrears.db`)
- Frontend Next.js 15
- Tudo do projeto: `/home/mini/rentcharge` (código, venv, sage-payments, config, archive)
- Host: BIG VM 500 — **não** big1
---
## Regras de negócio — ocupação de quarto
### RN-01 — Um quarto físico = um residente
1. O mesmo `room_no` físico **não pode aparecer duas vezes** na lista de ocupação.
2. Um quarto só pode ter **um** residente activo.
3. A dívida pertence à **pessoa** (SAGE ID), nunca ao quarto.
### RN-02 — Validação de ocupação pelo último pagamento (**cash SA**)
1. Prova operacional = **último pagamento cash** (SAGE Type **SA**, category `cash` > 0).
2. **RENTSUPP e refunds não contam** como pagamento de renda para esta regra.
3. Em conflito de quarto, prevalece quem tem o cash mais recente.
### RN-03 — Not Present (NP##) vs nome em duplicidade
- **A:** não pagou / saiu ou mudou → `NP01`, `NP02`, … + `last_room_no`.
- **B:** nome duplicado → badge para revisão humana; sem merge automático.
API: `POST /api/residents/reconcile-occupancy`.
---
## Regras de negócio — pagamentos SAGE (2026-09-05/06)
### RN-PAY-01 — Fonte única
- Exports SAGE **Customer Invoices Due** são a **única** fonte de pagamentos.
- O Excel de arrears (`JUN 2026` / `Total Arrears-2025`) **não grava** pagamentos (`excel_import._upsert_payment` = no-op).
- Endpoint: `POST /api/import/sage-payments` (`replace_all=true` apaga pagamentos anteriores).
- Código: `backend/app/services/sage_import.py`.
### RN-PAY-02 — Semana e data
- Semana = **segunda → domingo** (ISO).
- `period_start` / `period_end` = Mon–Sun da `payment_date`.
- Reports usam a **data de pagamento** da linha SAGE.
### RN-PAY-03 — Type SA = cash (pago)
| SAGE | Campo BD | Conta como pago? |
|------|----------|------------------|
| Type **SA** + Details CASH/CHQ/… | `category=cash`, `cash_paid=abs(Amount)` | **Sim** |
| Type **SA** + Details **RENTSUPP** | `category=rentsupp`, `rentsupp=abs` | **Não** (arquivo / relatório próprio) |
| Refund / Type SP / Details *REFUND* | `category=refund`, `refund_amount=abs` | **Não** (não subtrai do pago) |
Amount no ficheiro SAGE é **negativo** → armazenar valor absoluto.
### RN-PAY-04 — ID único
- Coluna SAGE **No** → `payments.txn_no` (único; índice `ux_payments_txn_no`).
- Também: `txn_ref`, `sage_type`, `details`, `payment_date`, `counts_as_paid`.
- Reimport não duplica pelo mesmo `txn_no`.
### RN-PAY-05 — Match residente
- Match obrigatório por **SAGE A/C** ↔ `residents.sage_id`.
- Ex.: **Mapule Uwaene** = A/C **481** · band **RENT_35**.
- **Patrick McNamara** = A/C **272** · B15 · band FB_85.
### RN-PAY-06 — Due vs pago (accounting)
- Due semanal = charge band (`get_cap`); excess cash **não credita** semanas futuras.
- `summarize_payments` agrega **cash por semana** antes do cap; RENTSUPP/refund ignorados no pago.
- Statement / lista de pagamentos: **default só cash**; filtro UI para rentsupp / refund / all.
### Ficheiros fonte (operador)
`E:\Reports Week\PAYMENTS-REPORTS-BY-WEEK\2026\`
Import consolidado (sem duplicar):
1. `Payments_week_01_to_52_from_2025.xlsx`
2. `Payments_week_2026-total_partial.xlsx` (até ~30/08/2026)
Cópia VM: `/home/mini/rentcharge/sage-payments/reimport/`.
---
## UI (padrão SAGE) — estado 2026-09-06
| Ecrã | Padrão |
|------|--------|
| Residents `/` | Command bar, views, filtros por coluna, pager, export |
| Reporting `/reports` | Mesmo layout que Residents |
| Ficha Payments | Grelha SAGE; colunas **ID · Ref · SAGE · Details · Status · Amount**; search + filtros; Type default **Cash (SA)** |
---
## Utilizadores e autenticação
A especificação completa está em `AUTH-USERS-SPEC.md`.
- `/login` oferece **Register new user**.
- O novo utilizador valida o cadastro com um código de seis dígitos enviado por e-mail e entra imediatamente após a validação.
- Recuperação de senha só usa e-mail verificado e token longo, de uso único.
- Sessões são mantidas no servidor, expiram por inatividade/tempo absoluto e podem ser revogadas.
- O menu **Admin** reúne contas, sessões (IP, SO, browser, duração e features) e eventos de segurança.
- O cookie do browser é `Secure`, `HttpOnly` e `SameSite=Strict`; o frontend não persiste credenciais em `localStorage`.
---
## Fora de escopo (por agora)
- Cloudflare Access na borda
- Merge automático de residentes só por nome
- Alterar `/etc/network/interfaces` do Proxmox
- Contar RENTSUPP como renda paga