# Investigation: Pedidos — Valores incorretos e vinculação clientes × vendedor ## Hand-off Brief 1. **O que aconteceu.** Pedidos exibem valores/status errados e a vinculação cliente↔vendedor está inconsistente; suspeita confirmada de 5 bugs distintos, sendo o mais grave o mismatch de códigos `situa` entre ERP e SAR. 2. **Onde o caso está.** Cinco problemas confirmados ou fortemente deduzidos; `vw_pedidos_erp` (view central usada pelo service) **não está definida em nenhum arquivo de código** — sua definição existe apenas no banco. 3. **O que é necessário agora.** Verificar a DDL de `vw_pedidos_erp` diretamente no banco (`\d+ sarweb.vw_pedidos_erp`) e confirmar se ela normaliza `situa` — isso resolve ou agrava o Bug #1. ## Case Info | Campo | Valor | | ---------------- | ------------------------------------------------------------------ | | Ticket | N/A | | Data | 2026-05-30 | | Status | Active | | Sistema | Node 24 / NestJS 11 / Prisma 7 / PostgreSQL (SIG+GERENTE schemas) | | Fontes | orders.service.ts, clients.service.ts, sarweb_views.sql, schema.prisma, .env, jwt-auth.guard.ts | ## Problem Statement Usuário relata: "pedidos com valores errados e vinculação clientes × vendedor"; complementou que a empresa usa `id_empresa = 9001` (schema SIG) e a empresa gerencial é a `1` (schema GERENTE), e que às vezes dados estão duplicando nas telas. ## Evidence Inventory | Fonte | Status | Notas | | --------------------------------------- | ---------- | -------------------------------------------------------- | | `orders.service.ts` | Available | Lido completo — queries brutas sem esquema qualificado | | `clients.service.ts` | Available | Lido completo | | `sarweb_views.sql` | Available | Define `vw_pedidos`, NÃO define `vw_pedidos_erp` | | `schema.prisma` | Available | Schema `sar` no PG; tabela `pedidos` é SAR-only | | `jwt-auth.guard.ts` | Available | Em dev usa `DEV_EMPRESA_ID` e `DEV_REP_CODE` do `.env` | | `.env` | Available | `DEV_EMPRESA_ID=1`, `DEV_REP_CODE=29` | | DDL de `vw_pedidos_erp` no banco | **Missing** | Não está no repo — requer `\d+` direto no PG | | Logs do PG / EXPLAIN com id_empresa=9001| **Missing** | Requer execução manual | ## Confirmed Findings ### Finding 1: `DEV_EMPRESA_ID=1` mas a empresa real é SIG (id=9001) **Evidência:** `.env:DEV_EMPRESA_ID=1` e `jwt-auth.guard.ts:56` — em dev, `idEmpresa` é forçado para `1` (GERENTE), ignorando o JWT. **Detalhe:** Em desenvolvimento, todas as queries usam `WHERE id_empresa = 1` e buscam dados do schema GERENTE. A empresa real do usuário está no schema SIG com `id_empresa = 9001`. Portanto, os testes locais estão apontando para dados diferentes dos de produção. **Fix imediato:** Alterar `.env`: `DEV_EMPRESA_ID=9001`. --- ### Finding 2: `vw_pedidos_erp` não existe em nenhum arquivo do repositório **Evidência:** - `orders.service.ts:77` — `FROM vw_pedidos_erp e` - `sarweb_views.sql` — define `sarweb.vw_pedidos`, não `vw_pedidos_erp` - `grep -rn "vw_pedidos_erp"` → apenas `orders.service.ts` e `dashboard.service.ts`; zero arquivos SQL **Detalhe:** A view existe somente no banco (criada manualmente). Seu comportamento exato — especialmente se normaliza `situa` do ERP para valores SAR — é desconhecido sem inspecionar o banco. --- ### Finding 3: Mismatch de códigos `situa` entre ERP e SAR **Evidência:** `sarweb_views.sql:367-378` (GERENTE) vs `sarweb_views.sql:411-418` (SIG) vs `order.contract.ts:13-18` (SAR). | Situa | GERENTE ERP | SIG ERP | SAR (app) | |-------|-------------|-------------|-----------------| | 1 | Pendente | Pendente | Ag. Aprovação | | 2 | Liberado | Liberado | Aprovado | | 3 | **Faturado**| Liberado | **Cancelado** | | 4 | **Cancelado**| **Faturado**| **Faturado** | | 5 | — | **Cancelado**| — | **Efeito confirmado (GERENTE):** Um pedido FATURADO no ERP (`situa=3`) exibe cor **vermelha** (Cancelado) no SAR — porque `OrderStatusBadge` usa o número cru para definir `tagColor`. O texto pode estar correto (via `statusDescr`) mas a cor é errada. **Efeito no filtro de status:** `situaFilter = situa != null ? 'AND e.situa = ${situa}' : ''` — se o usuário filtra `situa=3` (SAR=Cancelado), recebe pedidos FATURADOS do GERENTE. --- ### Finding 4: `dt_ultima_compra` ignorando histórico ERP — `activityStatus` sempre errado **Evidência:** `clients.service.ts:100` — ```sql LEFT JOIN pedidos p ON p.id_cliente = c.id_cliente AND p.id_empresa = c.id_empresa AND p.situa != 3 ``` `pedidos` aqui é a tabela SAR (`sar.pedidos`, Prisma), não os pedidos históricos do ERP. **Detalhe:** Clientes que têm anos de histórico no ERP mas nunca fizeram pedido pelo SAR ficam com `dt_ultima_compra = NULL` → `activityStatus = 'inactive'`. Portanto, a carteira inteira aparece como **"Inativo"** na tela de Clientes. **Fix necessário:** O JOIN deve usar `vw_pedidos_erp` (ou equivalente) em vez da tabela SAR. --- ### Finding 5: Filtro por `status` de clientes aplicado DEPOIS da paginação SQL **Evidência:** `clients.service.ts:138` — ```typescript if (status) mapped = mapped.filter((c) => c.activityStatus === status); ``` O `total` vem de `SELECT COUNT(*)` sem o filtro de status (`clients.service.ts:114-122`). **Efeito:** Ao filtrar por `status=active`, a API retorna menos itens que `limit` (ex.: 8 de 50), mas `total` ainda diz 2606. A paginação fica quebrada e a portfólio card mostra totais incorretos quando usa `useClientList({ limit:1, status:X })`. --- ## Hypothesized Paths ### Hypothesis 1: `vw_pedidos_erp` causa duplicação via UNION sem filtro por empresa **Status:** Open **Teoria:** `vw_pedidos_erp` faz UNION ALL de GERENTE + SIG sem filtrar por `id_empresa`, e para uma empresa que existe nos dois schemas (id=1 e id=9001), as mesmas ordens aparecem duas vezes. **Confirmaria:** `\d+ sarweb.vw_pedidos_erp` mostrando UNION ALL sem cláusula WHERE por empresa, + query retornando duplicatas com `id_empresa` distintos. **Refutaria:** View com UNION ALL onde cada SELECT tem `AND id_empresa = X` fixo. --- ### Hypothesis 2: SAR-created orders nunca aparecem na listagem **Status:** Open **Teoria:** `orders.service.ts list()` só consulta `vw_pedidos_erp` (ERP), nunca `sar.pedidos` (Prisma). Pedidos criados pelo SAR somem da lista após criação. **Confirmaria:** Criar pedido via SAR → abrir `/pedidos` → pedido não aparece na lista. **Refutaria:** `vw_pedidos_erp` inclui `sar.pedidos` via UNION ALL. --- ## Missing Evidence | Gap | Impacto | Como obter | | -------------------------------- | -------------------------------------------- | --------------------------------------------- | | DDL de `vw_pedidos_erp` | Confirma/refuta H1, H2 e Bug #3 (situa) | `\d+ sarweb.vw_pedidos_erp` no psql | | Query real com id_empresa=9001 | Confirma duplicação e valores | Rodar GET /orders com JWT prod ou DEV_ID=9001 | | Confirmar se `sar.pedidos` aparece na lista | Confirma H2 | Criar pedido SAR → verificar lista /orders | ## Source Code Trace | Elemento | Detalhe | | -------------- | ------------------------------------------------------------- | | Bug #1 origem | `jwt-auth.guard.ts:56` — `DEV_EMPRESA_ID` sobrescreve JWT | | Bug #2 origem | Banco de dados (DDL não versionada) | | Bug #3 origem | `orders.service.ts:43,45,98-99` — `situa` cru do ERP | | Bug #4 origem | `clients.service.ts:100` — JOIN com `sar.pedidos` (não ERP) | | Bug #5 origem | `clients.service.ts:138` — filter JS pós-paginação SQL | ## Conclusion **Confidence:** Medium (root causes identificadas; DDL de `vw_pedidos_erp` é peça faltante) Cinco bugs confirmados ou fortemente deduzidos explicam os sintomas: 1. **DEV aponta para empresa errada** (`DEV_EMPRESA_ID=1` vs real=9001) — dados diferentes entre dev e prod. 2. **`situa` ERP ≠ SAR** — cores/filtros de status errados para pedidos históricos. 3. **`dt_ultima_compra` ignora ERP** — carteira toda aparece inativa. 4. **`status` filter pós-paginação** — totais e paginação quebrados. 5. **`vw_pedidos_erp` não versionada** — comportamento opaco, possível fonte de duplicação. ## Recommended Next Steps ### Fix imediato (sem risco) Alterar `.env`: `DEV_EMPRESA_ID=9001` para que dev espelhe produção. ### Antes de qualquer outro fix: verificar `vw_pedidos_erp` no banco ```sql -- Rodar diretamente no psql: \d+ sarweb.vw_pedidos_erp -- ou SELECT pg_get_viewdef('sarweb.vw_pedidos_erp', true); ``` O resultado define o caminho dos próximos fixes. ### Fix #3 — `situa` — normalizar na `vw_pedidos_erp` (ou no service) Adicionar CASE na view (ou no service) mapeando ERP situa → SAR situa: ```sql -- GERENTE: 2→2, 3→4(Faturado), 4→3(Cancelado) -- SIG: 2→2, 4→4(Faturado), 5→3(Cancelado) ``` ### Fix #4 — `dt_ultima_compra` — usar ERP orders Em `clients.service.ts:100`, substituir `pedidos` por `vw_pedidos_erp` (ou a view equivalente): ```sql LEFT JOIN vw_pedidos_erp p ON p.id_cliente = c.id_cliente AND p.id_empresa = c.id_empresa AND p.situa NOT IN (3, 4, 5) -- situa=cancelado nos dois sistemas ``` ### Fix #5 — `status` filter — mover para SQL Em `clients.service.ts`, incluir o filtro de `activityStatus` na query SQL via subquery ou CTE com `dt_ultima_compra`, eliminando o filter JS pós-paginação. ## Reproduction Plan 1. Alterar `DEV_EMPRESA_ID=9001` no `.env` 2. Reiniciar a API 3. Abrir `/clientes` → verificar se clientes aparecem e se `activityStatus` faz sentido 4. Abrir `/pedidos` → verificar se pedidos aparecem e se status está correto 5. Rodar `\d+ sarweb.vw_pedidos_erp` no banco e trazer o resultado para continuar a investigação ## Side Findings - `ALERT_DAYS=30` e `INACTIVE_DAYS=60` estão hardcoded em `clients.service.ts:11-12`. O comentário diz "Configuráveis por empresa futuramente" — tarefa pendente. - `orders.service.ts:46` usa interpolação de string direta para `numPedSar` (ILIKE). O `escSql()` de `clients.service.ts:24` não é reutilizado aqui — potencial SQL injection menor para campo de busca. - `vw_pedidos` em `sarweb_views.sql` não é usada em lugar nenhum do código fonte — `vw_pedidos_erp` é usada em seu lugar. Possível que `vw_pedidos_erp` seja um rename ou extensão da `vw_pedidos`.