- 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>
11 KiB
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_pedidoalcada_desconto,meta_representantepush_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_URLapontando 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: 2–3 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: 3–4 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
SyncModuleno NestJS - Implementar
ErpJcsConnectorcom 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/triggerpara 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: 5–8 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:
- Com o sync rodando, os dados já estão nas tabelas canônicas
- Substituir
$queryRawporprisma.cliente.findMany(...)etc. - Manter o contrato de resposta da API (frontend não muda)
- Teste comparativo: mesmo resultado via ERP vs. via tabela SAR
- Remover a query antiga após validação
Resultado: Zero dependência de views ERP no código da API.
Estimativa: 5–8 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
ErpXConnectorimplementando a mesma interface doErpJcsConnector - 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: 4–6 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 (19–25 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