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:
@@ -1,25 +1,25 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
ProductListResponseSchema,
|
||||
type ProductListQuery,
|
||||
type ProductListResponse,
|
||||
ProdutoListResponseSchema,
|
||||
type ProdutoListQuery,
|
||||
type ProdutoListResponse,
|
||||
} from '@sar/api-interface';
|
||||
import { apiFetch } from '../api-client';
|
||||
|
||||
export function useCatalog(params: Partial<ProductListQuery> = {}) {
|
||||
export function useCatalog(params: Partial<ProdutoListQuery> = {}) {
|
||||
const search = new URLSearchParams();
|
||||
if (params.q) search.set('q', params.q);
|
||||
if (params.category) search.set('category', params.category);
|
||||
if (params.codGrupo) search.set('codGrupo', String(params.codGrupo));
|
||||
if (params.page) search.set('page', String(params.page));
|
||||
if (params.limit) search.set('limit', String(params.limit));
|
||||
|
||||
const qs = search.toString();
|
||||
return useQuery<ProductListResponse>({
|
||||
return useQuery<ProdutoListResponse>({
|
||||
queryKey: ['catalog', params],
|
||||
queryFn: async () => {
|
||||
const res = await apiFetch(`/catalog${qs ? `?${qs}` : ''}`);
|
||||
if (!res.ok) throw new Error(`catalog error ${res.status}`);
|
||||
return ProductListResponseSchema.parse(await res.json());
|
||||
return ProdutoListResponseSchema.parse(await res.json());
|
||||
},
|
||||
staleTime: 4 * 60 * 60 * 1000, // TTL 4h — FR-4.4
|
||||
});
|
||||
|
||||
@@ -11,14 +11,13 @@ import { apiFetch } from '../api-client';
|
||||
export const CLIENT_KEYS = {
|
||||
all: ['clients'] as const,
|
||||
list: (params: Partial<ClientListQuery>) => ['clients', 'list', params] as const,
|
||||
detail: (id: string) => ['clients', 'detail', id] as const,
|
||||
detail: (id: number) => ['clients', 'detail', id] as const,
|
||||
};
|
||||
|
||||
export function useClientList(params: Partial<ClientListQuery> = {}) {
|
||||
const qs = new URLSearchParams();
|
||||
if (params.q) qs.set('q', params.q);
|
||||
if (params.status) qs.set('status', params.status);
|
||||
if (params.financialStatus) qs.set('financialStatus', params.financialStatus);
|
||||
if (params.page) qs.set('page', String(params.page));
|
||||
if (params.limit) qs.set('limit', String(params.limit));
|
||||
|
||||
@@ -27,18 +26,20 @@ export function useClientList(params: Partial<ClientListQuery> = {}) {
|
||||
return useQuery<ClientListResponse, Error>({
|
||||
queryKey: CLIENT_KEYS.list(params),
|
||||
queryFn: async () => {
|
||||
const raw = await apiFetch(`/clients${query ? `?${query}` : ''}`);
|
||||
return ClientListResponseSchema.parse(raw);
|
||||
const res = await apiFetch(`/clients${query ? `?${query}` : ''}`);
|
||||
if (!res.ok) throw new Error(`clients list error ${res.status}`);
|
||||
return ClientListResponseSchema.parse(await res.json());
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useClientDetail(id: string) {
|
||||
export function useClientDetail(id: number | string | undefined) {
|
||||
return useQuery<ClientDetail, Error>({
|
||||
queryKey: CLIENT_KEYS.detail(id),
|
||||
queryKey: CLIENT_KEYS.detail(Number(id)),
|
||||
queryFn: async () => {
|
||||
const raw = await apiFetch(`/clients/${id}`);
|
||||
return ClientDetailSchema.parse(raw);
|
||||
const res = await apiFetch(`/clients/${id}`);
|
||||
if (!res.ok) throw new Error(`client detail error ${res.status}`);
|
||||
return ClientDetailSchema.parse(await res.json());
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
OrderListResponseSchema,
|
||||
OrderDetailSchema,
|
||||
type OrderListQuery,
|
||||
type OrderListResponse,
|
||||
type OrderDetail,
|
||||
type OrderSummary,
|
||||
PedidoListResponseSchema,
|
||||
PedidoDetailSchema,
|
||||
type PedidoListQuery,
|
||||
type PedidoListResponse,
|
||||
type PedidoDetail,
|
||||
type PedidoSummary,
|
||||
} from '@sar/api-interface';
|
||||
import { apiFetch } from '../api-client';
|
||||
|
||||
export function useOrderList(params: Partial<OrderListQuery> = {}) {
|
||||
export function useOrderList(params: Partial<PedidoListQuery> = {}) {
|
||||
const search = new URLSearchParams();
|
||||
if (params.clientId) search.set('clientId', params.clientId);
|
||||
if (params.status) search.set('status', params.status);
|
||||
if (params.number) search.set('number', params.number);
|
||||
if (params.idCliente) search.set('idCliente', String(params.idCliente));
|
||||
if (params.situa) search.set('situa', String(params.situa));
|
||||
if (params.numPedSar) search.set('numPedSar', params.numPedSar);
|
||||
if (params.from) search.set('from', params.from);
|
||||
if (params.to) search.set('to', params.to);
|
||||
if (params.page) search.set('page', String(params.page));
|
||||
if (params.limit) search.set('limit', String(params.limit));
|
||||
|
||||
const qs = search.toString();
|
||||
return useQuery<OrderListResponse>({
|
||||
return useQuery<PedidoListResponse>({
|
||||
queryKey: ['orders', params],
|
||||
queryFn: async () => {
|
||||
const res = await apiFetch(`/orders${qs ? `?${qs}` : ''}`);
|
||||
if (!res.ok) throw new Error(`orders list error ${res.status}`);
|
||||
return OrderListResponseSchema.parse(await res.json());
|
||||
return PedidoListResponseSchema.parse(await res.json());
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useOrderDetail(id: string | undefined) {
|
||||
return useQuery<OrderDetail>({
|
||||
return useQuery<PedidoDetail>({
|
||||
queryKey: ['orders', id],
|
||||
enabled: !!id,
|
||||
queryFn: async () => {
|
||||
const res = await apiFetch(`/orders/${id}`);
|
||||
if (!res.ok) throw new Error(`order detail error ${res.status}`);
|
||||
return OrderDetailSchema.parse(await res.json());
|
||||
return PedidoDetailSchema.parse(await res.json());
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useClientOrders(clientId: string | undefined) {
|
||||
return useQuery<OrderSummary[]>({
|
||||
queryKey: ['clients', clientId, 'orders'],
|
||||
enabled: !!clientId,
|
||||
export function useClientOrders(idCliente: number | undefined) {
|
||||
return useQuery<PedidoSummary[]>({
|
||||
queryKey: ['clients', idCliente, 'orders'],
|
||||
enabled: idCliente != null,
|
||||
queryFn: async () => {
|
||||
const res = await apiFetch(`/clients/${clientId}/orders`);
|
||||
const res = await apiFetch(`/orders?idCliente=${idCliente}&limit=10`);
|
||||
if (!res.ok) throw new Error(`client orders error ${res.status}`);
|
||||
const data = await res.json();
|
||||
return data as OrderSummary[];
|
||||
const data = PedidoListResponseSchema.parse(await res.json());
|
||||
return data.data;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user