refactor(erp): integração direta com banco ERP — schema sar

Revoga ADR 0006 (BD-por-workspace separado). O SAR agora conecta ao
banco PostgreSQL do ERP (módulo SIG) e usa o schema `sar` para tudo.

PRISMA
- Remove: Client, Product, Order, OrderItem, OrderStatusHistory,
  RepTarget, RepDiscountLimit, PushSubscription (modelos isolados)
- Adiciona: Pedido, PedidoItem, HistoricoPedido, AlcadaDesconto,
  MetaRepresentante, PushSubscription (mapeados para sar.*)
- IDs: id_cliente/cod_vendedor/id_empresa são INTEGER (ERP)
- situa: Int (1=Pendente 2=Aprovado 3=Cancelado 4=Faturado)
- JWT: workspace_id:string → id_empresa:number
- URL: inclui ?schema=sar para Prisma rotear ao schema ERP

SERVICES
- ClientsService: $queryRawUnsafe contra sar.vw_clientes + sar.pedidos
- CatalogService: $queryRawUnsafe contra sar.vw_produtos + sar.vw_estoque
- OrdersService: Prisma models Pedido/PedidoItem/HistoricoPedido/AlcadaDesconto
- DashboardService: MetaRepresentante + queries raw para inativos
- NotificationsService: PushSubscription com codVendedor + idEmpresa

CONTRATOS (api-interface)
- client.contract: campos ERP (idCliente, nome, cgcpf, cod_vendedor…)
- order.contract: PedidoSummary/PedidoDetail/CreatePedido + SITUA_LABEL
- product.contract: ProdutoSummary/ProdutoDetail (vw_produtos)
- auth.contract: workspaceId:string → idEmpresa:number

WEB
- Todos os cockpits e queries atualizados para os novos tipos

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 21:51:16 +00:00
parent 246eb28bb1
commit b0b60d7a14
39 changed files with 1433 additions and 1544 deletions

View File

@@ -10,9 +10,10 @@ import { WorkspacePrismaPool } from '../workspace/workspace-prisma-pool.service'
import type { JwtPayload } from './jwt.types';
import { IS_PUBLIC_KEY } from './public.decorator';
// Guard global (APP_GUARD). Valida Bearer HS256 e atualiza CLS com workspace real.
// CODING-RULES PGD-AUTHZ-002: workspaceId sempre do JWT, nunca de body/param.
// Ordem NestJS: middleware CLS (workspace default) → este guard (workspace real).
// Guard global (APP_GUARD). Valida Bearer HS256 e atualiza CLS com idEmpresa real.
// CODING-RULES PGD-AUTHZ-002: idEmpresa sempre do JWT, nunca de body/param.
// Ordem NestJS: middleware CLS (idEmpresa default) → este guard (idEmpresa real).
// ADR 0006 revogado: workspace_id → id_empresa; URL inclui ?schema=sar
@Injectable()
export class JwtAuthGuard implements CanActivate {
@@ -44,16 +45,18 @@ export class JwtAuthGuard implements CanActivate {
(req as Request & { user: JwtPayload }).user = payload as JwtPayload;
// Sobrescreve CLS com workspace real do JWT (corre depois do middleware).
const workspaceId = payload.workspace_id;
this.cls.set('workspaceId', workspaceId);
// Sobrescreve CLS com idEmpresa real do JWT (corre depois do middleware).
const idEmpresa = payload.id_empresa;
this.cls.set('idEmpresa', idEmpresa);
this.cls.set('userId', payload.sub);
this.cls.set('role', payload.role);
const dbUrl =
// URL inclui ?schema=sar para o Prisma rotear ao schema correto no ERP
const baseUrl =
process.env['DATABASE_URL'] ??
`postgresql://sar:sar_dev_password@localhost:5432/sar_workspace_${workspaceId}`;
this.cls.set('prisma', this.pool.getOrCreate(workspaceId, dbUrl));
'postgresql://sar:sar_dev_password@localhost:5432/sar_workspace_dev';
const dbUrl = baseUrl.includes('?') ? `${baseUrl}&schema=sar` : `${baseUrl}?schema=sar`;
this.cls.set('prisma', this.pool.getOrCreate(idEmpresa, dbUrl));
return true;
} catch {