feat(erp): pedidos e dashboard leem histórico do ERP (vw_pedidos_erp)

- OrdersService.list: substitui sar.pedidos por vw_pedidos_erp — 44k pedidos
  históricos do rep 29 visíveis; sar.pedidos continua sendo a tabela de escrita
  para novos pedidos SAR que serão integrados ao ERP
- DashboardService: atingido/pedidosMes/recentes/inativos todos via vw_pedidos_erp;
  supervisor usa vw_pedidos_erp para pedidosDia
- PedidoSummarySchema: id relaxado de uuid() para string(); adiciona numero,
  statusDescr e fonte ('sar'|'erp')
- orders.ts: corrige bug — apiFetch retorna JSON diretamente, não Response;
  remove res.ok/res.json() incorretos
- OrdersPage: coluna Nº mostra numero do ERP; statusDescr no badge
- DevLogin: atualiza para PAVEI COMERCIO cod 29

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 14:30:51 +00:00
parent 2abe5e8697
commit 24408ecd83
6 changed files with 204 additions and 146 deletions

View File

@@ -19,31 +19,39 @@ const SITUA_COLOR: Record<number, string> = {
const columns: TableColumnsType<PedidoSummary> = [
{
title: 'Nº',
dataIndex: 'numPedSar',
dataIndex: 'numero',
width: 120,
render: (num: string, row: PedidoSummary) => (
<Link to="/pedidos/$id" params={{ id: row.id }}>
{num}
</Link>
),
render: (_: number, row: PedidoSummary) => {
const label = row.numero ? String(row.numero) : row.numPedSar || row.id;
return row.fonte === 'erp' ? (
<span style={{ fontVariantNumeric: 'tabular-nums' }}>{label}</span>
) : (
<Link to="/pedidos/$id" params={{ id: row.id }}>
{label}
</Link>
);
},
},
{
title: 'Status',
dataIndex: 'situa',
width: 150,
render: (s: number) => (
<Badge
status={
(SITUA_COLOR[s] ?? 'default') as
| 'default'
| 'warning'
| 'processing'
| 'success'
| 'error'
}
text={<Tag color={SITUA_COLOR[s] ?? 'default'}>{SITUA_LABEL[s] ?? String(s)}</Tag>}
/>
),
render: (s: number, row: PedidoSummary) => {
const label = row.statusDescr ?? SITUA_LABEL[s] ?? String(s);
return (
<Badge
status={
(SITUA_COLOR[s] ?? 'default') as
| 'default'
| 'warning'
| 'processing'
| 'success'
| 'error'
}
text={<Tag color={SITUA_COLOR[s] ?? 'default'}>{label}</Tag>}
/>
);
},
},
{
title: 'Total',

View File

@@ -10,11 +10,11 @@ import { AuthTokenResponseSchema } from '@sar/api-interface';
type DevUser = { userId: string; role: string; label: string };
// userId = cod_vendedor como string; idEmpresa = empresa no ERP (dev default = 1)
// Em dev, o backend força DEV_REP_CODE=29 independente do userId enviado.
const DEV_USERS: DevUser[] = [
{ userId: '101', role: 'rep', label: 'Rafael — Rep (cod 101)' },
{ userId: '102', role: 'rep', label: 'Rep 2 (cod 102)' },
{ userId: '201', role: 'supervisor', label: 'Sandra — Supervisora (cod 201)' },
{ userId: '301', role: 'manager', label: 'Gerente (cod 301)' },
{ userId: '29', role: 'rep', label: 'PAVEI COMERCIO (cod 29)' },
{ userId: '29', role: 'supervisor', label: 'PAVEI — Supervisor (cod 29)' },
{ userId: '29', role: 'manager', label: 'PAVEI — Gerente (cod 29)' },
];
export function DevLogin({ onLogin }: { onLogin: () => void }) {

View File

@@ -24,8 +24,7 @@ export function useOrderList(params: Partial<PedidoListQuery> = {}) {
queryKey: ['orders', params],
queryFn: async () => {
const res = await apiFetch(`/orders${qs ? `?${qs}` : ''}`);
if (!res.ok) throw new Error(`orders list error ${res.status}`);
return PedidoListResponseSchema.parse(await res.json());
return PedidoListResponseSchema.parse(res);
},
});
}
@@ -36,8 +35,7 @@ export function useOrderDetail(id: string | undefined) {
enabled: !!id,
queryFn: async () => {
const res = await apiFetch(`/orders/${id}`);
if (!res.ok) throw new Error(`order detail error ${res.status}`);
return PedidoDetailSchema.parse(await res.json());
return PedidoDetailSchema.parse(res);
},
});
}
@@ -48,8 +46,7 @@ export function useClientOrders(idCliente: number | undefined) {
enabled: idCliente != null,
queryFn: async () => {
const res = await apiFetch(`/orders?idCliente=${idCliente}&limit=10`);
if (!res.ok) throw new Error(`client orders error ${res.status}`);
const data = PedidoListResponseSchema.parse(await res.json());
const data = PedidoListResponseSchema.parse(res);
return data.data;
},
});