Files
sar/apps/api/src/app/workspace/workspace.module.ts
julian b0b60d7a14 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>
2026-05-28 21:51:16 +00:00

49 lines
1.9 KiB
TypeScript

import { Module } from '@nestjs/common';
import { ClsModule } from 'nestjs-cls';
import { randomUUID } from 'node:crypto';
import type { Request, Response } from 'express';
import type { WorkspaceClsStore } from './workspace.types';
import { WorkspacePrismaPool } from './workspace-prisma-pool.service';
// CLS middleware roda ANTES dos guards (ordem NestJS).
// Aqui: apenas requestId + idEmpresa default (0 = não autenticado).
// JwtAuthGuard atualiza idEmpresa, userId e prisma após validar o token.
// CODING-RULES PGD-DB-009: prisma via cls.get('prisma'), nunca singleton.
// CODING-RULES PGD-AUTHZ-002: idEmpresa real vem do JWT (guard), não do env.
// ADR 0006 revogado: workspaceId: string → idEmpresa: number
@Module({
imports: [
ClsModule.forRootAsync({
global: true,
useFactory: () => ({
middleware: {
mount: true,
generateId: true,
idGenerator: (req: Request) => {
const fromPino = (req as Request & { id?: unknown }).id;
if (typeof fromPino === 'string' && fromPino.length > 0) return fromPino;
const headerVal = req.headers['x-request-id'];
return typeof headerVal === 'string' && headerVal.length > 0 ? headerVal : randomUUID();
},
setup: (cls, req: Request, res: Response) => {
const store = cls as unknown as {
set: <K extends keyof WorkspaceClsStore>(key: K, value: WorkspaceClsStore[K]) => void;
getId: () => string;
};
const requestId = store.getId();
res.setHeader('x-request-id', requestId);
store.set('requestId', requestId);
// Fallback para rotas públicas (ping, health). Guard sobrescreve em rotas protegidas.
store.set('idEmpresa', 0);
},
},
}),
}),
],
providers: [WorkspacePrismaPool],
exports: [ClsModule, WorkspacePrismaPool],
})
export class WorkspaceModule {}