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

11 KiB
Raw Blame History

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