121 lines
5.4 KiB
Markdown
121 lines
5.4 KiB
Markdown
# SPEC — Session 2026-09-19 (Rently / RentCharge)
|
||
|
||
**Status:** implemented · **Operador:** Roger
|
||
**Ambientes:** prod + test (VM500)
|
||
**Versão:** **006.2026** → noite **007.2026**
|
||
|
||
---
|
||
|
||
## Alterações do dia
|
||
|
||
### 1. Week Payments Maps (`/mapa`)
|
||
|
||
**All cash payments in this period** (única secção com Hash / Ticket / Txn):
|
||
- Colunas: Date, Resident, Room, **Hash**, **Invoice / Ticket**, **Txn**, **Time** (só Rent), Account, **Rent €**, **Other €**, **Total €**
|
||
- Cabeçalho profissional + botão **Period** (`period_headline`)
|
||
- Ancillary cash incluído nesta tabela; rodapé com totais
|
||
- Fontes Hash/Txn alinhadas às outras colunas
|
||
|
||
**Residents in period** (comportamento — **não** alterar para detalhe de txn):
|
||
- Removida coluna “Payments this period”
|
||
- Cabeçalhos: **weekly due** · **cash done**
|
||
- Prior lookback: **6 semanas** (W−1…W−6)
|
||
|
||
### 2. Public Txn IDs — `SPEC-TRANSACTION-IDS.md`
|
||
|
||
| Tipo | Formato |
|
||
|------|---------|
|
||
| Rent manual | `NNNNNN-M` · Ref `02_XXXXXX` |
|
||
| Cash ancillary | **`000000-AA`** (9 chars): `000084-ME`, `000010-EL`, `000001-KC`, `DN`, `LY` |
|
||
| Credit sale / settlement | `CR-…` / `CT-…` (canal) |
|
||
| Import | Mantém ids do ficheiro |
|
||
|
||
- Hash ROI/EOD: `payment_txn_hash` / `payments.txn_hash` no post de renda
|
||
- Migração histórica: `CS-…` → prefixo conta → **padded** `000000-AA`
|
||
- EOD gravados **descongelados** e regenerados (totais iguais; content hash atualizado)
|
||
- Backups: `backend/data/arrears_pre_*_20260919_*.db` (+ test)
|
||
|
||
### 3. Nomes de tabelas (fora ROI)
|
||
- Ficha residente: **Payment history**
|
||
- People hub tab: **Recent cash payments**
|
||
- Payables: **Remittance by account**
|
||
|
||
### 4. Invoice / Ticket — flag Required
|
||
- Componente partilhado `TicketInvoiceField`
|
||
- Verde **Required** por defeito (desmarcável → Optional) em **todos** os tabs do QuickPost (+ Add payment em dashboard, people, residents, mapa, receivables)
|
||
- Campo pisca a vermelho se Required e vazio no Post
|
||
- Também no **Edit payment** da ficha do residente
|
||
- Evita assumir Receipt No (SA) como ticket
|
||
|
||
### 5. People hub — Search pulse
|
||
- Com **All Residents** selecionado, o campo Search pisca (verde) para o operador localizar a pesquisa
|
||
|
||
### 6. Specs / docs
|
||
- Novo: `SPEC-TRANSACTION-IDS.md`, `SPEC-SESSION-2026-09-18.md`, este ficheiro, `releases/006.2026.md`
|
||
- Atualizados: `SPEC-PAYMENTS-MAP-WEEK-PRINT.md`, `SPEC-ACCOUNT-RECEIVABLES.md`, `VERSION.md`
|
||
|
||
## Ficheiros principais
|
||
- `backend/app/services/ledger.py`, `payment_map.py`, `eod_report.py`, `weekly_charges.py`, `main.py`
|
||
- `frontend/src/app/mapa/page.tsx`, `people/page.tsx`, `payables/page.tsx`, `residents/[id]/page.tsx`
|
||
- `frontend/src/components/QuickPostModal.tsx`, `TicketInvoiceField.tsx`, `residents/ResidentSearchToolbar.tsx`
|
||
- `frontend/src/app/globals.css`, `lib/api.ts`
|
||
- `docs/SPEC-TRANSACTION-IDS.md`, `docs/VERSION.md`
|
||
|
||
## Deploy
|
||
- `npm run build` prod + test (`NEXT_PUBLIC_APP_ENV=test` no test)
|
||
- `systemctl restart` `rentcharge-{backend,frontend}` + `rentcharge-test-*`
|
||
- Specs → Forgejo `myvexx/rently` + Obsidian CT130 via `scripts/sync_obsidian.py`
|
||
|
||
|
||
---
|
||
|
||
## Continuação (noite 2026-09-19) — versão **007.2026**
|
||
|
||
### 7. Money privacy (olho €) — app-wide
|
||
|
||
**Problema:** o botão Show € / Hide € só actualizava o Dashboard. Nas outras páginas os valores ficavam congelados (Next.js App Router: o layout/AppShell re-renderiza, mas o slot da página não).
|
||
|
||
**Solução:**
|
||
- `moneyFormat.ts` — pub/sub (`subscribeMoneyHidden` / `setMoneyHiddenFlag` notifica listeners)
|
||
- `MoneyPrivacy.tsx` — `useMoneyPrivacyRender()` via `useSyncExternalStore`; `useMoneyPrivacy()` também subscreve
|
||
- Todas as páginas/componentes que mostram euros chamam o hook (Residents, Mapa, Receivables, ROI, Reports, ficha residente, KPIs, QuickPost, …)
|
||
- Idle 30s continua a esconder montantes
|
||
- Deploy: **prod + test** (VM500)
|
||
|
||
### 8. Profile status — audit log (4 flags)
|
||
|
||
Checkboxes na ficha do residente + Settings edit:
|
||
|
||
| Flag | Campo |
|
||
|------|--------|
|
||
| Temporary | `is_temporary` |
|
||
| Deceased | `is_deceased` |
|
||
| In custody | `is_in_custody` |
|
||
| In treatment | `is_in_treatment` |
|
||
|
||
- Tabela append-only `resident_status_events` (flag, value on/off, `changed_at`, `changed_by_user_id`, `changed_by_username`)
|
||
- Ao lado de cada checkbox: último evento `On|Off dd/mm/yyyy HH:mm · user` (Europe/Dublin)
|
||
- Histórico completo no tooltip; mantém eventos ao desmarcar
|
||
- API: `status_flags` em `ResidentOut` (get/update/create); `GET /api/residents/{id}/status-history`
|
||
- UI: `/residents/[id]` + `/settings` edit modal
|
||
|
||
### 9. SMTP / auth mail (já em AUTH-USERS-SPEC)
|
||
|
||
- `mail.myvexx.com:465` SSL · `admin@myvexx.com` · E2E forgot-password + OTP OK
|
||
- Credenciais só em `rentcharge.env` (não no Git)
|
||
|
||
### 10. Cybersec hardening (F2–F6 + F1 scrub docs)
|
||
|
||
- TLS verify no envio de email; cookie-only JWT web; path reset `/reset-password/{token}`; tips anti-phishing nos templates; docs sem passwords em claro
|
||
|
||
## Ficheiros (007)
|
||
|
||
- `frontend/src/lib/moneyFormat.ts`, `components/MoneyPrivacy.tsx`, páginas com euros
|
||
- `frontend/src/lib/statusFlags.ts`, `app/residents/[id]/page.tsx`, `app/settings/page.tsx`
|
||
- `backend/app/database.py` (`ResidentStatusEvent`), `schemas.py`, `main.py`
|
||
- `docs/SPEC-MONEY-PRIVACY.md`, `docs/SPEC-RESIDENT-PROFILE-STATUS.md`, `docs/releases/007.2026.md`
|
||
|
||
## Deploy 007
|
||
|
||
- `npm run build` + restart `rentcharge-*` e `rentcharge-test-*`
|
||
- Specs → Forgejo `myvexx/rently` + Obsidian CT130
|