Files
sar/docs/plano-migracao-modelo-canonico.md
julian 400fcb3360 feat(web+api): ficha do cliente — contatos, CTR, NF-e, pedidos e produtos
- Contatos: grid de cards 3 colunas, botão "Novo Contato" no topo da página
- Sync ERP↔SAR corrigido: vw_contatos aceita formato COR#<id>, trigger normaliza id_empresa (9001→1)
- CTR + NF-e: layout 50/50 — lista de títulos abertos com badge vencido/a vencer e lista de notas com botão copiar chave NF-e
- Histórico de pedidos: UNION SAR+ERP, top 5 + modal "Ver todos"
- Produtos mais comprados: top 5 com último preço + modal "Ver todos"
- Novos endpoints: ctr-list, notas, orders-history, top-produtos
- AppShell: overflow-x travado, sem scroll horizontal na aplicação

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 14:13:21 +00:00

266 lines
11 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.
# Plano de Migração — Modelo de Dados Canônico SAR
**Data:** 2026-06-22
**Autor:** Julian (Product Owner SAR)
**Status:** Proposta para avaliação
---
## 1. Contexto e Problema
### Situação atual
O SAR foi iniciado consultando diretamente as **views do ERP JCS** (`vw_clientes`, `vw_pedidos_erp`, `vw_produtos`, etc.) que existem dentro do banco de dados do cliente (`libreplast@192.168.0.43`). Isso funcionou para o cliente piloto, mas cria uma dependência estrutural que inviabiliza a expansão do produto.
### Problema identificado
| Sintoma | Consequência |
|---|---|
| SAR acessa views do ERP via SQL raw | Cada novo ERP exige reescrever queries |
| Schema `sar` vive *dentro* do banco ERP | Sem isolamento; SAR depende de acesso ao servidor do cliente |
| Views são específicas do ERP JCS | ERP diferente = produto diferente |
| Sem camada de abstração | Impossível oferecer o SAR como SaaS multi-tenant real |
### Diagnóstico técnico (levantamento 2026-06-22)
```
Módulos 100% acoplados ao ERP: auth, catalog, clients
Módulos parcialmente acoplados: orders (leitura), dashboard
Módulos já independentes: notifications, workspace
Views ERP consumidas: 11 views + 1 tabela direta
Tabelas próprias SAR existentes: 6 models Prisma
```
---
## 2. Solução Proposta
### Modelo Canônico + Connectors
```
┌─────────────────────────────────────────────────────┐
│ APP SAR │
│ (frontend + API NestJS) │
│ Lê APENAS tabelas próprias do SAR │
└──────────────────────┬──────────────────────────────┘
│ Prisma ORM
┌─────────────────────────────────────────────────────┐
│ Banco de Dados SAR │
│ (PostgreSQL isolado por workspace) │
│ tabelas canônicas: clientes, produtos, pedidos... │
└──────────┬──────────────────────┬───────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────────────┐
│ Connector │ │ Connector │
│ ERP JCS │ │ ERP X (futuro) │
│ (PostgreSQL) │ │ (REST API / CSV / outro) │
└──────────────────┘ └──────────────────────────────┘
```
**Princípio:** O ERP é uma **fonte de dados**, não o sistema de registro do SAR. Cada cliente tem um connector específico para seu ERP. O SAR opera exclusivamente sobre seu próprio modelo de dados.
### O que não muda
Os dados transacionais do SAR já estão corretos e **permanecem sem alteração**:
- `pedidos`, `pedido_itens`, `historico_pedido`
- `alcada_desconto`, `meta_representante`
- `push_subscription`
---
## 3. Tabelas Canônicas a Criar
### 3.1 Entidades mestres (sincronizadas do ERP)
| Tabela SAR | Substitui | Campos principais |
|---|---|---|
| `sar.clientes` | `vw_clientes` | codigo, razao_social, nome_fantasia, cnpj, cidade, uf, ativo, representante_codigo |
| `sar.representantes` | `vw_representantes` | codigo, nome, email, senha_hash, tipo (rep/supervisor), ativo |
| `sar.produtos` | `vw_produtos` | codigo, descricao, unidade, ncm, ativo |
| `sar.estoques` | `vw_estoque` | produto_codigo, deposito, saldo (snapshot com timestamp) |
| `sar.pautas` | `vw_pautas` | codigo, descricao, ativa |
| `sar.pauta_produtos` | `vw_pauta_produtos` | pauta_codigo, produto_codigo, preco, desconto_max |
| `sar.formas_pagamento` | `vw_formas_pagamento` | codigo, descricao, parcelas, ativa |
| `sar.municipios` | `vw_municipios` | ibge, nome, uf |
| `sar.empresa` | `gestao.empresa` | cnpj, razao_social, nome_fantasia, endereco, logo_url |
### 3.2 Histórico ERP (read-only, sincronizado)
| Tabela SAR | Substitui | Propósito |
|---|---|---|
| `sar.pedidos_erp` | `vw_pedidos_erp` | Histórico de pedidos anteriores ao SAR |
| `sar.pedido_itens_erp` | `vw_peditens_erp` | Itens dos pedidos ERP |
### 3.3 Controle de sincronização
| Tabela SAR | Propósito |
|---|---|
| `sar.sync_log` | Registro de cada execução de sync (início, fim, erros, registros processados) |
| `sar.sync_config` | Configuração do connector por workspace (tipo ERP, credenciais, frequência) |
---
## 4. Plano de Execução por Fases
### Fase 0 — Banco de Dados Isolado `[Fundação]`
**Objetivo:** Separar o banco SAR do banco ERP do cliente.
**Ações:**
- Provisionar banco PostgreSQL exclusivo para o SAR (`sar_db`)
- Configurar variável `DATABASE_URL` apontando para o novo banco
- Manter `ERP_DB_*` apenas no connector (não no app principal)
- Estrutura multi-tenant: um schema por workspace ou banco por workspace (já previsto na stack)
**Resultado:** SAR pode funcionar mesmo sem acesso ao ERP; connector roda separado.
**Estimativa:** 23 dias
---
### Fase 1 — Schema Canônico `[Estrutura]`
**Objetivo:** Criar todos os models Prisma das tabelas canônicas.
**Ações:**
- Adicionar 11 models ao `schema.prisma` (seção 3.1 e 3.2)
- Adicionar 2 models de controle de sync (seção 3.3)
- Gerar e aplicar migrations
- Nenhuma mudança no código da API ainda
**Resultado:** Tabelas existem no banco, prontas para receber dados.
**Estimativa:** 34 dias
---
### Fase 2 — Sync Service (Connector ERP JCS) `[Motor]`
**Objetivo:** Criar a camada que lê o ERP e popula as tabelas canônicas.
**Ações:**
- Criar módulo `SyncModule` no NestJS
- Implementar `ErpJcsConnector` com leitura das 11 views existentes
- Sync completo na inicialização do workspace
- Sync incremental por cron (ex: a cada 5 minutos para estoque, 30 min para cadastros)
- Registrar execuções em `sync_log`
- Endpoint admin `/api/v1/sync/trigger` para forçar sync manual
**Estratégia de sync:**
```
┌────────────────────────────────────────────────────┐
│ Frequências recomendadas │
│ │
│ A cada 5 min: estoques (alta volatilidade) │
│ A cada 30 min: produtos, pautas, preços │
│ A cada 60 min: clientes, representantes │
│ A cada 6h: pedidos_erp (histórico) │
│ 1x por dia: municipios, empresa, formas_pgto │
└────────────────────────────────────────────────────┘
```
**Resultado:** Tabelas SAR ficam populadas e atualizadas automaticamente.
**Estimativa:** 58 dias
---
### Fase 3 — Migração dos Módulos `[Execução]`
**Objetivo:** Substituir todos os `$queryRaw` por queries Prisma nas tabelas canônicas.
**Prioridade e ordem:**
| Ordem | Módulo | Complexidade | Motivo da prioridade |
|---|---|---|---|
| 1 | `catalog` | Baixa | Somente leitura, sem lógica de negócio complexa |
| 2 | `clients` | Média | Base do dashboard e pedidos |
| 3 | `auth` | Baixa | Bem delimitado; lê apenas `representantes` |
| 4 | `dashboard` | Média | Depende de clients migrado |
| 5 | `orders` (leitura) | Média | Parte escrita já usa Prisma corretamente |
**Processo por módulo:**
1. Com o sync rodando, os dados já estão nas tabelas canônicas
2. Substituir `$queryRaw` por `prisma.cliente.findMany(...)` etc.
3. Manter o contrato de resposta da API (frontend não muda)
4. Teste comparativo: mesmo resultado via ERP vs. via tabela SAR
5. Remover a query antiga após validação
**Resultado:** Zero dependência de views ERP no código da API.
**Estimativa:** 58 dias
---
### Fase 4 — Segundo Connector (Validação da Abstração) `[Prova]`
**Objetivo:** Onboarding de um cliente com ERP diferente do JCS.
**Ações:**
- Identificar segundo ERP (ex: TOTVS, Sankhya, outro)
- Criar `ErpXConnector` implementando a mesma interface do `ErpJcsConnector`
- Mapear campos do ERP X para o schema canônico SAR
- Sem nenhuma mudança no app SAR
**Resultado:** Prova de conceito real de que a arquitetura é ERP-agnóstica.
**Estimativa:** 46 dias (variável conforme ERP)
---
## 5. Cronograma Estimado
```
Semana 1: Fase 0 (banco isolado) + Fase 1 (schema Prisma)
Semana 2: Fase 2 (Sync Service — maior esforço)
Semana 3: Fase 3 (migração dos módulos)
Semana 4: Fase 4 (segundo connector) + testes + documentação
Total estimado: 4 semanas (1925 dias úteis)
```
---
## 6. Riscos e Mitigações
| Risco | Probabilidade | Impacto | Mitigação |
|---|---|---|---|
| Divergência de dados entre ERP e tabela SAR durante sync | Médio | Alto | Sync comparativo com log de diferenças; alertas |
| Latência do sync afeta experiência do rep | Baixo | Médio | Sync de estoque a cada 5 min é suficiente para força de vendas |
| ERP do cliente sem conectividade temporária | Médio | Baixo | SAR continua funcionando com dados do último sync |
| Campos do segundo ERP sem equivalência no schema canônico | Médio | Médio | Schema canônico flexível com campo `metadata jsonb` por entidade |
| Custo de manutenção de dois bancos | Baixo | Baixo | Banco SAR é pequeno; ERP continua como está |
---
## 7. Benefícios Esperados
| Benefício | Impacto |
|---|---|
| **Multi-ERP real** | Onboarding de qualquer cliente independente do ERP |
| **Isolamento de falhas** | Queda do ERP não derruba o SAR |
| **Performance** | Queries no banco SAR são mais rápidas (schema otimizado) |
| **Funciona offline** | Rep consulta dados mesmo sem VPN/internet no cliente |
| **Multi-tenant limpo** | Banco SAR separado por workspace desde o início |
| **Evolução independente** | SAR pode adicionar campos sem depender do ERP |
---
## 8. Decisão
O projeto SAR **não precisa ser refeito do zero**. A infraestrutura (NestJS, autenticação, frontend React, ciclo de pedidos, alçadas, metas, push notifications) está correta e é reaproveitada integralmente.
A mudança é **cirúrgica e incremental**:
- Adicionar banco e tabelas canônicas (Fases 0 e 1)
- Construir o motor de sync (Fase 2)
- Substituir queries raw módulo a módulo (Fase 3)
O risco de **não fazer** essa migração agora é maior: quanto mais o produto crescer sobre as views do ERP JCS, mais caro fica refatorar depois.
---
*Documento gerado em 2026-06-22. Para dúvidas: jcsinfo@gmail.com*