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>
49 lines
1.9 KiB
TypeScript
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 {}
|