# Paridade definitiva com LegadoSPB — segregação de tipos de mensagem (financeiro / consulta / arquivo / alerta / não-financeiro)

**Data:** 2026-06-09 · **Escopo:** `spb/services/bacen_gateway` (backend) + `spb/frontend-vue` (frontend)
**Mandato do dono:** "fazer a paridade com LegadoSPB que tem todos esses fluxos bem desenhados, toda segregação do que é cada tipo de mensagem … EU QUERO TUDO." Parar de inventar; usar a classificação REAL do legado.

## 0. Fonte da verdade (citada — NÃO inventada)
- **Classificação por tipo:** `priv/repo/seeds/data/legacy_message_config.csv` (1452 linhas = dump de `spb_tb_gen_msg_detalhe` do EvolutionPro), decodificada por `priv/repo/seeds/034_legacy_message_config.exs`. Colunas-chave: **`tp_oper_grid`** (idx 15: F/C/A/N/D/X) + `financial_flag` (idx 3: F/D/N) + `debit_credit_flag` (idx 2: D/C/N/T) + `direction_flag` (idx 10: E/R) + `id_tipo_msg` (idx 8: O/A/C/R/E/X/I/Y).
- **Mecanismo de segregação do legado** (verbatim): Angular `LegadoSPB/EvolutionDotNet/www-angular/574.js` → `TipoMsg = [{A:"Alerta"},{C:"Consultas"},{F:"Oper Financeiras"},{N:"Oper Não Financeiras"}]` (os `vlr` A/C/F/N **são** os códigos `tp_oper_grid`); proc `spb_sp_filtro_movto_msgs`/`spb_sp_filtro_piloto`: `AND (@pTipoMsg IS NULL OR a.tp_oper_grid = @pTipoMsg)`.
- **Extrato/arquivo:** procs `spb_sp_gera_STR0014_prog_envio` (requisição), `spb_sp_trata_PAG0113R1_STR0014R1` (resposta→`spb_tb_pil_rsp_extr_pag_str`), `spb_sp_exp_movto` (gera o CSV) — UI `exp_movto` ("Gerar Arquivo"/"Download"); amostras `LegadoSPB/EvolutionDotNet/www/arquivos/movto/EVO-12345678-*.csv` (colunas: `dt_movto;cd_msg;ent_ext;vl_operacao;nr_ctrl_IF;ds_status;finldd_if;cpf_cnpj_db;cpf_cnpj_cr;ag_db;ct_db;ag_cr;ct_cr;ds_legado;dt_hr_envio;dt_hr_retorno;tmp_gasto`).
- **Saldo:** STR0013 (`tp_oper_grid=C`) → proc `spb_sp_get_saldos` (dashboard de saldo, NÃO transação).

## 1. Regra de segregação (a implementar = a do legado)
A **tela** segrega por `tp_oper_grid` (como o legado): **F**=Oper Financeiras · **C**=Consultas · **A**=Alertas/Avisos · **N**=Oper Não Financeiras. `financial_flag IN ('F','D')` é o gate de contabilidade/saldo (uso secundário, procs do legado). Direção da instância = `direction_flag`/`direction` (Envio/Recebido) — separado de `tp_oper_grid` (categoria/tipo de fluxo).

## 2. Causa raiz única
`message_type_config` (com `tp_oper_grid`/`financial_flag`) foi seedada mas: (a) `tp_oper_grid` foi dropado na importação de runtime (`post_integration/message_config.ex:290`) e nunca ligado às operações; (b) as telas usam hardcode (`control_messages.ex` lista inventada; `TransactionsView` STR/LPI/SEL) em vez de `tp_oper_grid`; (c) a coluna "Direção" usa `flow_label` (propriedade do tipo) em vez de `direction` (instância); (d) extrato/arquivo (STR0014) nunca implementado; (e) `message_type_driver` lê `"S"` vs seed `"F"`.

## 3. Plano (fases — TODAS; TDD; review; deploy só com OK do dono)

### Fase 1 — Fundação: ligar `tp_oper_grid` às operações/mensagens (a espinha)
- Garantir que `message_type_config.grid_type` (= `tp_oper_grid`) está populado (seed 034). Confirmar valores F/C/A/N por tipo.
- **Stamp** `tp_oper_grid` em `spb_operations` + `bacen_messages` na criação (resolver de `message_type_config` por `message_type`); migration adiciona coluna `tp_oper_grid` (se não existir) + **backfill** das linhas existentes via JOIN. Inbound STR materializado (STR0004R2/0008R2) recebe `tp_oper_grid='F'`.
- Expor `tp_oper_grid` + um rótulo de categoria (`Financeira/Consulta/Alerta/Não-Financeira`) na serialização de transações e mensagens.
- **Aceite:** toda operação/mensagem carrega `tp_oper_grid` real; STR0004/0008/0013/0014 batem com o CSV (F/F/C/C).

### Fase 2 — Tela de Transações + Mensagens: paridade de segregação
- **Filtro financeiro:** trocar `ControlMessages.financial_sql_clause` + hardcodes por `tp_oper_grid = 'F'` (parametrizável p/ o dropdown). **Parar de dropar R2/R3 financeiras** (`non_artifact_sql_clause` mata as confirmações de crédito recebido — remover essa exclusão; as R2 financeiras (`financial_flag=F`) SÃO a perna de liquidação).
- **Dropdown de categoria** F/C/A/N (legado `TipoMsg`): "Oper Financeiras / Consultas / Alertas / Oper Não Financeiras". Transações default = F.
- **Coluna "Direção":** renderizar `getDirectionLabel(item.direction)` (Envio/Recebido), nunca `flow_label`. Adicionar coluna separada "Categoria"/"Tipo de fluxo" (de `tp_oper_grid`/`id_tipo_msg`) em `TransactionsView.vue` + `MessagesView.vue` (admin + operator).
- **Aceite:** STR0004R2/0008R2 recebidas → "Recebido"; "Consulta" sai da coluna Direção; tela de Transações mostra exatamente os `tp_oper_grid='F'` (incl. as R2 de crédito).

### Fase 3 — Consultas / Saldo
- Superfície para `tp_oper_grid='C'` (STR0013 saldo, STR0014 extrato, CTP/CAM/etc.) — aba/filtro Consultas; STR0013 alimenta display de saldo (paridade `spb_sp_get_saldos`), não linha de transação.
- **Aceite:** consultas aparecem como consulta; saldo via STR0013 num display de saldo.

### Fase 4 — STR0014 extrato / disponibilização de arquivo (feature faltante)
- Requisição STR0014 (paridade `spb_sp_gera_STR0014_prog_envio`); ingestão do retorno (já existe parcial em `str_handler handle_extract_query_response`); **geração do arquivo de movimento** `EVO-{ISPB}-{de}-{ate}.csv` (paridade `spb_sp_exp_movto`, mesmas colunas do EVO-*.csv) + endpoint de **download** + UI "Gerar Arquivo / Arquivos disponíveis / Download".
- **Aceite:** operador gera e baixa o extrato de movimento em CSV (formato EVO), como no legado.

### Fase 5 — Correção latente: `message_type_driver` "S" vs "F"
- `requires_balance?/requires_accounting?` comparam `financial_flag: "S"`; o seed carrega `"F"/"D"`. Corrigir para `IN ("F","D")` (ou normalizar o seed) — destrava saldo/contabilidade por config. Avisar o dono do backend (caminho money-adjacent).
- **Aceite:** tipos financeiros disparam balance/accounting via config.

## 4. Fora de escopo (YAGNI, por ora)
Reescrever o catálogo de 1292; relatórios além do extrato de movimento (rpt_extrato_reserva etc. — fase futura); câmbio/SEL DVP tabs dedicadas (a categoria N/D já segrega).

## 5. Notas de ambiguidade (resolvidas pela fonte)
- 26 tipos PAG têm `tp_oper_grid='F'` mas `financial_flag='N'`: a TELA segrega por `tp_oper_grid` (proc `spb_sp_filtro_movto_msgs`), então entram em "Financeiras" — **seguimos o legado** (grid, não flag). `financial_flag` fica só para o gate contábil (Fase 5).
- 5 SEL `financial_flag='D'`/`grid='D'` (DVP título-contra-pagamento): entram em Financeiras (D⊂financeiro); aba dedicada = futuro.

---

## STATUS (2026-06-09) — Fases 1/2/4 feitas, 3 coberta, 5 ADIADA

- **Fase 1 ✅** (`f8e2aeb78`): `tp_oper_grid` ligado a operações+mensagens (resolver da classificação real, stamp+backfill+serialização).
- **Fase 2a ✅** (`2a068691d`): filtro financeiro = `tp_oper_grid='F'` (paridade), para de dropar as R2/R3 de crédito; param de categoria F/C/A/N.
- **Fase 2b ✅** (`adb03344d`): Direção=Envio/Recebido; coluna Categoria; dropdown F/C/A/N; sem hardcode STR/LPI/SEL. (4 telas)
- **Fase 4 ✅** (`7247d6443`): Exportação de Movimento (CSV de 17 colunas, download) + sanitização EVO→CEC em todo o trabalho SPB da sessão.
- **Fase 3 ✅ COBERTA (sem build novo):** consultas agora filtráveis via dropdown F/C/A/N=C; STR0013 já é grid C (Consulta Saldo, excluído das transações financeiras); display de saldo já existe (`BalanceController` `/balances/positions` + `BalanceDashboardView.vue`). Refinamento futuro: ligar SldInial/SldFinl de STR0013R1 ao BalanceDashboard se ainda não estiver.
- **Fase 5 ⏸️ ADIADA (decisão money-path, NÃO flipar no susto):** `message_type_driver` compara `financial_flag: "S"` mas o seed carrega `"F"/"D"` → `requires_balance?/requires_accounting?` sempre falso HOJE. **Corrigir LIGA posting de saldo/contabilidade** para todos os tipos financeiros num gateway BACEN ao vivo. Há um 2º caminho (post_integration handlers + `BalanceTracker.update_balance` + `post_accounting_on_confirmation`) + os wrappers `message_type_requires_balance?/accounting?(nil)` fazem default `true`. Risco de **duplo-posting**. Precisa investigação própria + decisão do dono ANTES de habilitar — não bundlar num deploy de paridade de telas. (Regra: "já tomamos prejuízo por isso na Owem".)

## Fase 1.5 — Gap de deploy descoberto + fechado (Aurora homolog) ✅

Pós-deploy (TD 179), validação no banco vivo mostrou os 2 créditos recebidos do ICBC
(STR0004 R$40 / STR0008 R$80, ISPB `17453575` → `46026562`) com `tp_oper_grid = nil` — a
correção estava no código mas **inerte** no banco. **Causa raiz**: `message_type_config`
tinha **0 linhas** no Aurora homolog. O catálogo nunca foi semeado lá: `Release.migrate/0`
não roda seeds, `run_all_seeds.exs` **não inclui** o `034_legacy_message_config.exs` (seed
numerado órfão do orquestrador), e não havia entry point de Release pra ele. Com o catálogo
vazio, tanto o backfill da migration quanto o fallback COALESCE em runtime resolviam pra nil
→ o filtro `tp_oper_grid='F'` excluía os recebidos.

**Fix (sem redeploy de serviço — só dado):** semeado `message_type_config` no Aurora homolog
via task one-off contra a imagem TD 179 (lê o CSV empacotado). Resultado: **1452 tipos**,
distribuição de grid batendo o LegadoSPB (**F=146 · C=68 · A=134 · N=369** + NIL/X/D técnicos);
STR0004/STR0008→**F**, STR0013/STR0014→**C**; **112 operações + 207 mensagens** carimbadas;
os 2 créditos do ICBC agora em escopo Financeiro (provado: `financial_by_direction` =
inbound 2 / outbound 9). Telas passam a exibir os recebidos como **Recebido / Financeira**.

**Artefato permanente (reprodutível):** `Release.seed_message_type_config/0` (semeia o
catálogo do CSV empacotado, idempotente, recarrega o cache ETS do `MessageGrid`) +
`Release.backfill_tp_oper_grid/0` (carimba `spb_operations`/`bacen_messages` idempotente) —
mesmo padrão dos `seed_message_flow_types/0`/`seed_grade_message_map/0`. Em DB novo:
`migrate()` → `seed_message_type_config()` → `backfill_tp_oper_grid()`.

## Débito de sanitização (pré-existente, varrer depois)
Nomenclatura legada (`EVO`/`EvolutionPro`/`spb_sp_*`/`spb_tb_*`) em arquivos de sessões anteriores (não tocados): `legacy_parity.ex`, `file_encoding.ex` (EVOCryptoXP), `exports/circular_3290_controller.ex`, `entity_status_controller.ex`, `admin_controller.ex:1095`/`api.ts:1616`/`router.ex:355` (`exp_movto_pcr`), refs `spb_sp_abre_fecha_clearing`/`spb_sp_concilia_extrato` em ldl_handler/inbound_consumer/clearing_lifecycle. Sweep dedicado.
