147 lines
10 KiB
Markdown
147 lines
10 KiB
Markdown
# SPEC — Ciclo EOD → Closing Till → Remittance Pack → HO (definitiva)
|
||
|
||
**Status:** DEFINITIVA — aprovada por Roger em 2026-10-07 (blocos 1 e 2)
|
||
**Rules version:** `CYCLE_RULES_VERSION = 2026-10-07-r1`
|
||
**Substitui:** `SPEC-CLOSING-TILL-FREEZE-ARCHIVE.md` (2026-10-01-r1), `RULE-CLOSING-TILL-AFTER-CUT-LOCKED.md`, `releases/011.2026.md` (2026-10-06-r1) e `.cursor/rules/eow-cycle-start-rules.mdc` naquilo que contradizem esta spec.
|
||
**Implementação:** ⏳ ainda não implementada — PRD corre `2026-10-01-r1`. Implementar em TEST, validar com Roger, depois PRD.
|
||
|
||
---
|
||
|
||
## 1. Visão geral
|
||
|
||
```
|
||
Dia a dia Dia de fecho EOW – Closing Till EOW Remittance Pack HO
|
||
Save statement ─▶ Save EOD for Closing Till ─▶ Cycle Start → Apply → Draft ─▶ Freeze TEMPORÁRIO ─▶ Pack → Official Draft ─▶ Approve ROI → Send to HO
|
||
(editável) (linha de corte) (nada trava) (trava valores, reversível) (CONGELADO DEFINITIVO)
|
||
```
|
||
|
||
O congelamento **definitivo** acontece **só** no **Send to HO**.
|
||
|
||
---
|
||
|
||
## 2. Regras
|
||
|
||
### R1 — Save statement (dia a dia, EOD Transactions)
|
||
- Ao fim do dia o operador clica **Save statement** → cria um ficheiro EOD (cards *Saved EOD file* e *Recent saved EOD files*).
|
||
- Pode salvar **várias vezes** no mesmo dia (correcções, lançamentos esquecidos).
|
||
- O ficheiro fica **editável** (não imutável) enquanto o ciclo a que pertence não foi enviado ao HO.
|
||
|
||
### R1a — Auto-save às 23:55 (se o operador esquecer)
|
||
- Um job diário às **23:55 (hora local, Europe/Dublin)** verifica o dia:
|
||
- se há movimentos e **nenhum** statement salvo, **ou** o último save está **desactualizado** (R3a) → faz o **Save statement automaticamente** (salvo por `system (auto 23:55)`);
|
||
- envia aviso para **admin@myvexx.com** com a lista do que foi salvo automaticamente (dia, nº do ficheiro, total, nº de movimentos).
|
||
- Assim cada dia começa com os ficheiros do dia anterior salvos.
|
||
- O auto-save **não** faz *Save EOD for Closing Till* (o corte é sempre um acto do operador).
|
||
- Implementação: timer systemd `rently-prod-eod-autosave.timer` (padrão dos jobs existentes), `OnCalendar=*-*-* 23:55 Europe/Dublin`.
|
||
|
||
### R2 — Save EOD for Closing Till (dia de fecho: quinta ou outro dia escolhido)
|
||
- Faz o mesmo que o Save statement **e** marca a hora do clique, colocando a **linha de corte** após o último lançamento:
|
||
- **before-cut** (00:00 → corte) = este ciclo;
|
||
- **after-cut** (corte → 23:59) = próximo ciclo.
|
||
- Um **Save statement** no dia de fecho **depois** do corte gera/actualiza o **after-cut** (próximo ciclo).
|
||
- **Segundo clique no mesmo dia:** avisar *"Já existe uma linha de corte neste dia (HH:MM). Deseja criar uma nova?"*
|
||
- Se o EOW **ainda não foi enviado**: o novo corte **substitui** o ficheiro final da semana no Cycle Start e o processo recomeça (drafts anteriores ficam desactualizados).
|
||
- Se existir **freeze temporário** activo: pedir primeiro para o libertar (R5).
|
||
- Se o EOW **já foi enviado**: bloquear.
|
||
|
||
### R3 — Week EOD files (Cycle Start) — EOW Closing Till
|
||
Lista **todos** os ficheiros do ciclo aberto:
|
||
1. o **after-cut** do último fecho (semana anterior);
|
||
2. o ficheiro de **cada dia** entre os fechos — **só o save mais recente** de cada dia;
|
||
3. o **before-cut** do dia de fecho actual (até à hora do clique).
|
||
|
||
- Ficheiros do ciclo aberto **nunca** aparecem como *used · immutable*.
|
||
- O dia de fecho dividido não mostra o ficheiro de dia inteiro (só before/after).
|
||
- Ficheiros de ciclos já enviados não aparecem.
|
||
- Nada vem pré-seleccionado; *used · applied* só depois de marcar + **Apply start & preview**.
|
||
|
||
### R3a — Ficheiro desactualizado
|
||
- Se houver lançamento ou correcção num dia **depois** do último save desse dia, o ficheiro aparece no Cycle Start com o selo **"desactualizado — salve de novo"** (com o nº de movimentos novos).
|
||
- O auto-save das 23:55 (R1a) re-salva automaticamente estes casos.
|
||
|
||
### R4 — Apply start & preview / Generate draft
|
||
- **Apply start & preview** une os ficheiros marcados num **ficheiro único** (preview). Pode repetir-se.
|
||
- **Generate draft** gera um draft a partir de uma selecção de cada vez.
|
||
- Pode haver **vários drafts**; **os drafts não trancam ficheiros** (os mesmos ficheiros podem estar em vários drafts). Só um será usado; os outros ficam para leitura e podem ser apagados.
|
||
|
||
### R4a — Limpeza de drafts não usados (card "Drafts" já existente no Closing Till)
|
||
- O card **Drafts (n)** passa a mostrar em cada draft o estado: **Em uso** (é o pacote em freeze temporário ou enviado) ou **Não usado**.
|
||
- Drafts **Não usados** têm **Delete** individual e um botão **"Apagar todos os não usados"** (com confirmação), para evitar lixo na base.
|
||
- Drafts **Em uso** não podem ser apagados.
|
||
- Depois do **Send to HO**, o card sugere apagar os drafts não usados daquele ciclo.
|
||
|
||
### R5 — Freeze temporário (Closing Till) — OBRIGATÓRIO antes do Remittance Pack
|
||
- O operador escolhe **um** draft e faz **Freeze** → estado **Temporarily frozen**.
|
||
- Trava os ficheiros e valores desse pacote, para que o envelope e o pack batam com o que vai ser enviado (edições nesses dias ficam bloqueadas com mensagem).
|
||
- **O operador pode libertar** (Unfreeze) enquanto não houver envio — volta a draft e terá de refazer as etapas seguintes.
|
||
- O Unfreeze **não apaga** a linha de corte (o corte pertence ao *Save EOD for Closing Till*, R2).
|
||
- Selo na UI: **"Temporarily frozen"** (nunca "FROZEN — immutable" antes do envio).
|
||
|
||
### R6 — EOW Remittance Pack
|
||
- **Pack Summary** mostra o montante do pacote em freeze temporário.
|
||
- Operador preenche os dados do **envelope** e gera **previews** da revisão (quantos quiser; os não usados podem ser apagados e não ficam congelados).
|
||
- **Create Official Draft** → fica disponível em **3. Approve selected ROI**.
|
||
- **Aviso obrigatório:** se não houver pacote em freeze temporário, mostrar no topo do Remittance Pack:
|
||
> *"Ainda não existe um Closing Till em Freeze temporário. Volte a EOW – Closing Till, escolha o draft e clique em Freeze antes de montar o pack."*
|
||
— e desactivar *Create Official Draft* até existir.
|
||
|
||
### R7 — Approve selected ROI → Send to HO (congelamento DEFINITIVO)
|
||
- Neste momento os ficheiros do pacote (incluindo o **before-cut**) passam a **Frozen · Sent**: imutáveis, indisponíveis para novos ciclos.
|
||
- O **after-cut** **não** fica congelado — pertence ao próximo ciclo (R3.1).
|
||
- Depois do envio **só o admin** pode reverter, como excepção:
|
||
- **motivo obrigatório**, registado em auditoria;
|
||
- fica um registo visível no **ROI Archive** e o pacote é marcado **"Re-aberto"**, para o HO saber que haverá reenvio;
|
||
- os ficheiros voltam ao estado *Temporarily frozen* (não a editáveis) até novo envio ou unfreeze.
|
||
- Só existe **um** pacote em freeze temporário por ciclo; para trocar de draft é preciso libertar o freeze primeiro.
|
||
|
||
### R8 — Lançamentos atrasados em dias enviados
|
||
- Por regra **nada entra** nos ficheiros imutáveis/enviados. Um lançamento num dia já enviado é bloqueado.
|
||
- **Futuro (fora desta entrega):** módulo / conta de **Correcção Contabilística** para registar esses casos no ciclo seguinte, com rasto.
|
||
|
||
---
|
||
|
||
## 3. Estados
|
||
|
||
| Estado | Onde | Ficheiros travados? | Quem reverte |
|
||
|--------|------|---------------------|--------------|
|
||
| Ficheiro EOD salvo | EOD Transactions | Não | — |
|
||
| Draft (vários) | Closing Till | Não | apagar draft |
|
||
| **Temporarily frozen** (1 por ciclo) | Closing Till | Sim (valores do pacote) | **operador** (Unfreeze) |
|
||
| Official draft / previews | Remittance Pack | Sim (herda o freeze) | operador (apagar / unfreeze) |
|
||
| **Frozen · Sent** | após Send to HO | **Sim, definitivo** | **só admin** (excepção auditada) |
|
||
|
||
---
|
||
|
||
## 4. Diferenças face ao sistema actual (2026-10-01-r1 em PRD)
|
||
|
||
| Ponto | Hoje | Esta spec |
|
||
|-------|------|-----------|
|
||
| Ficheiros no Cycle Start | só `for_eow=1` | todos os Save statement (mais recente por dia) + before/after-cut |
|
||
| Draft tranca ficheiros | sim (`eod_ids_held_by_draft_or_freeze`) | **não** |
|
||
| Freeze | "FROZEN — immutable" | **Temporarily frozen**, reversível pelo operador |
|
||
| Unfreeze | só admin; apaga a linha de corte | operador; **mantém** o corte |
|
||
| Imutável definitivo | no Freeze | no **Send to HO** |
|
||
| After-cut do fecho anterior | preso no freeze (ex.: EOD-20261001-37722C €129) | aberto para o próximo ciclo |
|
||
| Corte | carimbado pelo Freeze | carimbado pelo **Save EOD for Closing Till** |
|
||
| 2.º clique no dia de fecho | sem tratamento | aviso + substituir enquanto não enviado |
|
||
| Remittance Pack sem freeze | sem aviso | aviso + Create Official Draft desactivado |
|
||
| Dia sem statement salvo | dinheiro fica fora do Cycle Start | **auto-save 23:55** + email admin@myvexx.com |
|
||
| Statement desactualizado | sem aviso | selo "desactualizado — salve de novo" |
|
||
| Drafts não usados | Delete um a um | estado Em uso / Não usado + "Apagar todos os não usados" |
|
||
| Reversão após envio | impossível | só admin, motivo + ROI Archive "Re-aberto" |
|
||
|
||
---
|
||
|
||
## 5. Notas de implementação (TEST primeiro)
|
||
|
||
- `eow_report.list_eod_choices`: listar todos os EOD do ciclo aberto (último save por dia), excluir só os de ciclos **enviados**.
|
||
- `eod_ids_held_by_draft_or_freeze` → passa a "held by **sent**" (e "temporarily frozen" só para bloquear edição, não a listagem).
|
||
- `freeze_eow_draft`: não acrescentar o after-cut à lista do pacote; não carimbar corte (R2 já o fez).
|
||
- `unfreeze_eow_report`: permitir operador quando não enviado; não limpar `closing_till_cut`; admin com motivo depois do envio.
|
||
- `eod_report`: *Save EOD for Closing Till* gera before/after + aviso de 2.º clique.
|
||
- Remittance Pack (frontend + API): aviso R6 e bloqueio de *Create Official Draft*.
|
||
- Auto-save (R1a): job `app/jobs/eod_autosave.py` + `send_email` (já existe em `modules/users/service.py`) + timer systemd 23:55 Europe/Dublin (VM em UTC).
|
||
- Card Drafts (R4a): estado Em uso / Não usado + apagar em massa (API protege drafts em uso).
|
||
- Reversão admin (R7): motivo, evento de auditoria, marca "Re-aberto" no ROI Archive.
|
||
- Testes de regressão: reescrever `tests/test_eow_cycle_start_rules.py` para esta versão.
|
||
- Ao implementar: actualizar `.cursor/rules/eow-cycle-start-rules.mdc` para apontar para esta spec.
|