feat(web+api): catálogo com detalhe do produto, preços por pauta e consulta de pedidos ERP

- Catálogo: modal de detalhe centralizado (1100px) com identificação, estoque,
  preços base e lista de preços por pauta do representante (DISTINCT para evitar duplicatas)
- Contrato: loteMulVenda promovido para ProdutoSummarySchema; PautaPrecoSchema adicionado
- Pedido novo: valida lote múltiplo de venda — qtd inicial = lote, step = lote,
  InputNumber em erro quando inválido, alerta e bloqueio do submit
- Consulta ERP: tela OrdersErpPage com listagem de pedidos do ERP (P/E), contrato
  PedidoErpConsulta, endpoint no orders.controller, rota e sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 20:27:19 +00:00
parent 0858e1e941
commit a2bab75bad
15 changed files with 1804 additions and 492 deletions

View File

@@ -20,6 +20,7 @@ export const ProdutoSummarySchema = z.object({
ativo: z.number().int(),
qtdEstoque: z.string().nullable(),
listaParauta: z.number().int().nullable(),
loteMulVenda: z.number().int().nullable(),
});
export const PautaSchema = z.object({
@@ -42,6 +43,14 @@ export type ProdutoSummary = z.infer<typeof ProdutoSummarySchema>;
// ─── Produto Detail ───────────────────────────────────────────────────────────
export const PautaPrecoSchema = z.object({
idPauta: z.number().int(),
codigo: z.number().int(),
descricao: z.string(),
preco: z.string(),
});
export type PautaPreco = z.infer<typeof PautaPrecoSchema>;
export const ProdutoDetailSchema = ProdutoSummarySchema.extend({
referencia: z.string().nullable(),
descricaoDetalhada: z.string().nullable(),
@@ -50,9 +59,9 @@ export const ProdutoDetailSchema = ProdutoSummarySchema.extend({
aliqIpi: z.string().nullable(),
pesoLiquido: z.string().nullable(),
qtdVolume: z.string().nullable(),
loteMulVenda: z.number().int().nullable(),
precoComIpi: z.string().nullable(),
precoPromocional: z.string().nullable(),
pautaPrecos: z.array(PautaPrecoSchema),
});
export type ProdutoDetail = z.infer<typeof ProdutoDetailSchema>;