Commit Graph

14 Commits

Author SHA1 Message Date
8a5db57f35 feat(api,web): logo da empresa na impressao e cabecalho A4 compacto
- Tabela sar.config_empresa (logo em data URL por empresa matriz) com
  migration idempotente, espelho no schema SQL e GRANT no provision
- PUT /catalog/company/logo (gerente/admin) e logoBase64 no GET
  /catalog/company - vale para a impressao de todos os representantes
- Nova tela /ger/config "Configuracoes" com upload/preview/remocao do
  logo (PNG/JPG/WebP ate 500KB)
- Cabecalho da impressao redesenhado: logo a esquerda, dados da empresa
  condensados em 3 linhas, numero/status/data compactos a direita -
  ocupa ~metade da altura anterior no A4

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 19:48:05 +00:00
f543b8ac7f feat(politicas): regras de desconto por grupo/subgrupo/rep e condicoes comerciais no catalogo
- Nova tabela sar.regras_desconto (grupo, subgrupo, representante, % e
  vigencia; campos nulos = todos) com migration idempotente, espelho no
  sar-erp-schema.sql e GRANT no provision-client
- CRUD manager-only em /politicas/regras + aba "Regras de Desconto" na
  tela de Politicas Comerciais (selects com nomes de rep/grupo/subgrupo
  via /politicas/grupos-produto)
- GET /politicas/regras/vigentes (rep ve so as que o alcancam) e
  GET /politicas/promocoes/vigentes para o catalogo
- Regra vigente pre-aplica o desconto no carrinho do novo pedido
- Selos "Promocao"/"Cond. especial" na busca de produto, catalogo do
  pedido e pagina de catalogo; secao "Condicoes Comerciais" no modal de
  detalhe do produto (descricao, % e validade)
- Empty imageStyle deprecado -> styles.image no carrinho

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 17:24:21 +00:00
bf6e21ce47 refactor(infra)!: schema sar no banco ERP substitui banco-por-workspace
Revoga o ADR 0006. O isolamento multi-tenant deixa de ser um banco por
workspace e passa a ser o schema `sar` dentro do proprio banco ERP do
cliente, com `id_empresa` discriminando o tenant em todas as tabelas.

Provisionamento:
- `provision-client.ts` substitui `provision-workspace.ts`. Nao cria mais
  banco: aplica schema + views + triggers num banco ERP ja existente.
  Trata o encoding LATIN1 dos bancos ERP via `toLatinSafe()`.
- `sar-erp-schema.sql` vira a fonte unica: absorve as views que estavam em
  `sarweb_views.sql` e passa a conter tambem `sar.chamados` /
  `sar.chamado_mensagens`, que so existiam via migration.

Correcoes necessarias para o provisionamento rodar ponta a ponta:
- `migrate deploy` abortava com P3005, porque o schema SQL roda antes do
  Prisma e o schema `sar` nunca esta vazio. O script agora detecta banco
  pre-existente e faz o baseline sozinho.
- `_prisma_migrations` ia parar no schema `public` do ERP do cliente; a URL
  de migracao agora leva `?schema=sar`.
- `sar.pedidos` nao tinha `end_entrega`, coluna que o schema.prisma ja
  declarava desde a feature de endereco de entrega, e que derrubava
  GET /orders com 500. Migration adicionada.
- `vw_sitpedido` se perdeu junto com `sarweb_views.sql` e e usada pela
  consulta de pedidos ERP. Restaurada.

Remove o seed de dados demo e os fallbacks de DATABASE_URL hardcoded: sem
a variavel configurada a API agora falha explicitamente, em vez de apontar
silenciosamente para um banco de desenvolvimento inexistente.

Verificado ponta a ponta contra um banco ERP real: schema aplicado, 13
tabelas + 20 views, migrations registradas, e segunda execucao idempotente.

BREAKING CHANGE: DATABASE_URL passa a ser obrigatoria. O comando de
provisionamento muda para `pnpm client:provision --host <host> --db <banco>`
(rename efetivado no commit de dependencias).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:11:35 +00:00
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
34368e8006 feat(web+api): contatos vinculados a clientes com sync ERP e base WhatsApp
DB:
- sar.vw_contatos: view sobre gestao.contato com join sig.corrent
  (id_entidade CHAR20 = id_corrent; cod_vendedor para filtro por rep)
- sar.contatos_novos: staging com nome, cargo, departamento, telefone,
  celular, whatsapp, email, dt_aniversario, anotacoes
- trg_contato_novo: AFTER INSERT → gestao.contato; grava id_contato_erp

API:
- GET  /clients/:id/contacts  — lista contatos ativos do cliente
- POST /clients/:id/contacts  — cria via staging; retorna { idContatoErp, sincronizado }

Web:
- ClientContacts: tabela de contatos no detalhe do cliente
- Links diretos WhatsApp (wa.me) + mailto por contato
- Modal "Novo Contato" com todos os campos; feedback de código ERP no sucesso
- whatsapp é o campo principal para envio futuro via ChatWoot

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 17:25:48 +00:00
236dd69eba feat(web+api): tela de cadastro de cliente novo (CNPJ/CPF) com sync ERP
Web (NewClientPage):
- Segmentado PJ/CPF com campos específicos por categoria
- PJ: razão social, nome fantasia, CNPJ, IE, indicador IE, consumidor final
- PF: nome completo, CPF
- Endereço com auto-preenchimento via ViaCEP (CEP → rua/bairro/município)
- Município: Select com busca server-side (/catalog/municipios)
- Contato: DDD, telefone, email
- Comercial: forma pagamento, tabela de preços, limite crédito
- Feedback: código ERP exibido no sucesso; alerta de erro de sync sem bloquear

API:
- GET /catalog/municipios?q= — busca municipios da vw_municipios
- POST /clients/novo — INSERT em sar.clientes_novos; trigger sincroniza para sig.corrent
- Retorna { id, idCorrentErp, sincronizado, erroSync } após o trigger disparar
- Fix trigger fn_sync_cliente_to_erp: NULLIF para cgcpf vazio (evita violação
  do unique index key_corrent_cgcpf quando cliente não tem CPF/CNPJ)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 17:06:27 +00:00
ec0b7c1611 fix(triggers): advisory lock e fconta corretos em fn_sync_pedido_aprovado_to_erp
- FOR UPDATE é inválido com MAX() no PG 18; substituído por pg_advisory_xact_lock
- fconta=0 violava CHECK (1,2,3,4,5,6,9); corrigido para 1 (padrão SAR)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 16:52:10 +00:00
35d0ba68d6 feat(infra): triggers ERP + reset migrations Prisma para schema correto
Triggers SAR→ERP (scripts/sar-triggers.sql):
- trg_pedido_aprovado: ao aprovar (situa 1→2) em sar.pedidos, replica
  automaticamente em sig.pedidos + sig.peditens e grava erp_id_pedido
- trg_cliente_novo: INSERT em sar.clientes_novos replica em sig.corrent
  com todos os campos obrigatórios; grava id_corrent_erp e flag sincronizado
- Corrige trigger tsvectorupdate do ERP para PG 18 (bpchar→text cast)
- Adiciona coluna erp_id_pedido em sar.pedidos e tabela sar.clientes_novos

Migrations Prisma:
- Remove 5 migrations obsoletas com nomes PascalCase (Order, Client, etc.)
  que não batiam com os @@map snake_case do schema atual
- Cria baseline 20260624000000_init_baseline apontando para estado correto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:07:54 +00:00
2abe5e8697 feat(infra): conecta ao banco ERP libreplast e fixa rep 29 como usuário dev
- sar-erp-schema.sql: corrige grupo.nome (era descricao), tp_pauta inexistente
  em pauxpro, COALESCE(id_empresa,1) em vw_clientes para bancos single-tenant,
  e nome do cliente via COALESCE(NULLIF(TRIM(nome),''), TRIM(razao))
- WorkspacePrismaPool: PrismaPg({ schema: 'sar' }) + options search_path=sar
  para ORM e queries raw funcionarem no schema correto
- JwtAuthGuard: força DEV_REP_CODE/DEV_EMPRESA_ID em não-prod — filtro
  global sem tocar em nenhum service
- env.schema: adiciona DEV_REP_CODE e DEV_EMPRESA_ID com defaults 29 e 1

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 14:07:04 +00:00
6cdb4c578e feat(infra): adiciona vw_metas ao schema SAR — metas do ERP (gestao.metavenda)
View sar.vw_metas expõe gestao.metavenda com joins descritivos:
- nome_vendedor (gestao.vendedor)
- desc_grupo / desc_subgrupo (gestao.grupo)
- nome_marca (gestao.marca)
- Campos calculados: ano e mes extraídos de mes_ano (date)

Campo tipo (char 2) controla o escopo da meta:
  G/GE=geral, GR=grupo, SG=subgrupo, MA=marca, PR=produto, AC=classe ABC

DashboardService usará tipo='G' (ou equivalente) para calcular %
atingido vs meta; os demais tipos ficam disponíveis para detalhamento
futuro. Taxas de comissão/flex vêm de vw_representantes (taxa_com),
não da tabela sar.meta_representante (que guarda apenas overrides SAR).

Renumera seções 4-16 → 5-17 para acomodar vw_metas como seção 4.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 11:45:55 +00:00
f363d22d90 feat(infra): adiciona vw_sarcfg ao schema SAR — regras de negócio por empresa
View sar.vw_sarcfg lê gestao.sarcfg + gestao.sarconfig e expõe:
- Flags booleanas decodificadas do bitmask bloq_preco_pedido (bits 0-5):
  blog_preco, blog_desconto, blog_limite_credito, blog_novo_cliente,
  blog_preco_promocional, blog_formapag_cliente
- Configurações gerais: ativar_prod_pauta, preco_padrao, preco_com_ipi,
  origem_descmax, cod_pauta1/2/3
- Configs sarconfig (key-value): bloq_pauta_preco, dias_bloq_credito,
  dias_bloq_comunicacao, tipo_bloq_comunicacao

Renumera seções de views: 1-15 → 1-16 (vw_sarcfg inserida como #1).
OrdersService usará esta view para aplicar restrições por empresa.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 11:38:55 +00:00
246eb28bb1 feat(infra): schema SAR no banco do ERP — views SIG + tabelas de escrita
Cria scripts/sar-erp-schema.sql com tudo no schema sar:
- 15 views de leitura (vw_clientes, vw_produtos, vw_estoque, vw_pautas,
  vw_representantes, vw_empresas, vw_ctr, vw_pedidos_erp, etc.) que
  espelham gestao.* e sig.* sem modificar o ERP
- Tabelas de escrita SAR: pedidos, pedido_itens, historico_pedido,
  alcada_desconto, meta_representante, push_subscription
- Índices e grants comentados prontos para prod

Arquitetura: SAR on-prem no mesmo PostgreSQL do ERP (módulo SIG).
Substitui ADR 0006 (BD-por-workspace separado) — workspace = id_empresa.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 20:51:24 +00:00
e3587e680a feat(infra): script de provisionamento de workspace — C9
pnpm workspace:provision --id <id> [--name <nome>] [--with-seed]
Cria banco sar_workspace_{id}, habilita extensões, aplica todas as
migrations e opcionalmente popula dados demo. Sem master DB necessário
— JwtAuthGuard resolve a URL pela convenção de nome (ADR 0006).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 01:06:43 +00:00
17c08e6392 chore: initial monorepo scaffold + WDS Phase 1+2 artifacts
- Nx 22.7 monorepo (pnpm 11.1, TypeScript 5.9, Node 24)
- apps/api: NestJS 11 (CJS conforme CODING-RULES.md PGD-DB-004)
- apps/web: React 19 + Vite 8 (ESM)
- libs/shared/api-interface: Zod contract base
- Docker Compose dev: Postgres 18, Valkey 8, MinIO, Mailpit
- WDS artifacts:
  - design-artifacts/A-Product-Brief/ (5 docs canônicos + 16 dialogs)
  - design-artifacts/B-Trigger-Map/ (hub + 4 personas + feature impact)
- Stack canon: STACK.md v2.2 + CODING-RULES.md v2.0 + brand.md
- AGENTS.md + README.md como entrada para devs/agentes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 14:34:20 +00:00