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

@@ -6,24 +6,17 @@ import {
faClipboardList,
} from '@fortawesome/free-solid-svg-icons';
import { Link } from '@tanstack/react-router';
import type { OrderSummary } from '@sar/api-interface';
import type { PedidoSummary } from '@sar/api-interface';
import { SITUA_LABEL } from '@sar/api-interface';
import { useRepDashboard } from '../../lib/queries/dashboard';
const { Title, Text } = Typography;
const STATUS_LABEL: Record<string, string> = {
budget: 'Orçamento',
pending_approval: 'Ag. Aprovação',
approved: 'Aprovado',
invoiced: 'Faturado',
cancelled: 'Cancelado',
};
const STATUS_COLOR: Record<string, string> = {
budget: 'default',
pending_approval: 'warning',
approved: 'processing',
invoiced: 'success',
cancelled: 'error',
const SITUA_COLOR: Record<number, string> = {
1: 'warning',
2: 'processing',
3: 'error',
4: 'success',
};
function fmt(v: number): string {
@@ -189,7 +182,7 @@ export function RafaelPainel() {
<Flex vertical gap={12}>
{clientesInativos.map((c) => (
<Flex
key={c.id}
key={c.idCliente}
justify="space-between"
align="center"
style={{
@@ -199,8 +192,8 @@ export function RafaelPainel() {
}}
>
<Space direction="vertical" size={0}>
<Link to="/clientes/$id" params={{ id: c.id }}>
<Text strong>{c.name}</Text>
<Link to="/clientes/$id" params={{ id: String(c.idCliente) }}>
<Text strong>{c.nome}</Text>
</Link>
{c.ultimaCompraValor && (
<Text type="secondary" style={{ fontSize: 'var(--text-xs)' }}>
@@ -241,16 +234,16 @@ export function RafaelPainel() {
<Text type="secondary">Nenhum pedido nos últimos 7 dias.</Text>
) : (
<Flex vertical gap={10}>
{pedidosRecentes.map((o: OrderSummary) => (
{pedidosRecentes.map((o: PedidoSummary) => (
<Flex key={o.id} justify="space-between" align="center">
<Space direction="vertical" size={0}>
<Link to="/pedidos/$id" params={{ id: o.id }}>
<Text strong className="tabular-nums">
{o.number}
{o.numPedSar}
</Text>
</Link>
<Text type="secondary" style={{ fontSize: 'var(--text-xs)' }}>
{o.clientName}
Cód. cliente {o.idCliente}
</Text>
</Space>
<Flex gap={8} align="center">
@@ -260,7 +253,9 @@ export function RafaelPainel() {
currency: 'BRL',
})}
</Text>
<Tag color={STATUS_COLOR[o.status]}>{STATUS_LABEL[o.status]}</Tag>
<Tag color={SITUA_COLOR[o.situa] ?? 'default'}>
{SITUA_LABEL[o.situa] ?? String(o.situa)}
</Tag>
</Flex>
</Flex>
))}