feat(mvp-rep): formas de pagamento do ERP + suporte offline completo
Formas de pagamento: - Endpoint GET /catalog/payment-methods lendo vw_formas_pagamento filtrado por ativa=1 e integrar_sar=1 - FormaPagamento schema/type no shared api-interface - Hook useFormasPagamento (staleTime 1h) substituindo lista hardcoded Offline (FR-4.2 / NFR-2.1–2.4): - IndexedDB queue: lib/offline/idb.ts + order-queue.ts sem deps externos - NewOrderPage detecta !navigator.onLine → enqueueOrder() → toast + reset - useOfflineSync: auto-sync ao reconectar (POST orders + PATCH transmit) - usePendingOrders: fila reativa via CustomEvents - AppShell: banner offline + useOfflineSync() global - OrdersPage: seção de pedidos pendentes com retry/descartar - sw.js: network-first para API GETs cacheáveis + stale-while-revalidate para assets + app shell navigate fallback Docs: - architecture.md: documento de decisões de arquitetura do SAR MVP Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,31 @@ export const ClienteInativoSchema = z.object({
|
||||
});
|
||||
export type ClienteInativo = z.infer<typeof ClienteInativoSchema>;
|
||||
|
||||
// Dimensão de meta. O ERP (vw_metas.tipo) define como o cliente acompanha metas:
|
||||
// GL = global, GR = por grupo. Motor único; outras dimensões (marca/subgrupo/
|
||||
// produto) entram aqui depois sem mudar a forma.
|
||||
export const MetaDimensaoSchema = z.enum(['global', 'grupo']);
|
||||
export type MetaDimensao = z.infer<typeof MetaDimensaoSchema>;
|
||||
|
||||
// Linha de meta vs realizado por grupo, multi-medida (codigo=null = rollup global).
|
||||
// fator = R$/kg (valor/peso); o ERP guarda vl_fator na meta.
|
||||
export const MetaItemSchema = z.object({
|
||||
codigo: z.number().int().nullable(),
|
||||
rotulo: z.string(),
|
||||
pedidos: z.number().int(), // qtd de pedidos faturados no grupo (realizado)
|
||||
valorMeta: z.number(),
|
||||
valorReal: z.number(),
|
||||
qtdMeta: z.number(),
|
||||
qtdReal: z.number(),
|
||||
pesoMeta: z.number(),
|
||||
pesoReal: z.number(),
|
||||
fatorMeta: z.number(),
|
||||
fatorReal: z.number(),
|
||||
pct: z.number(), // % de valor (real/meta) — base da barra de progresso
|
||||
falta: z.number(), // valor faltante p/ a meta
|
||||
});
|
||||
export type MetaItem = z.infer<typeof MetaItemSchema>;
|
||||
|
||||
export const RepDashboardSchema = z.object({
|
||||
meta: z.object({
|
||||
atingido: z.number(),
|
||||
@@ -18,6 +43,9 @@ export const RepDashboardSchema = z.object({
|
||||
pct: z.number(),
|
||||
falta: z.number(),
|
||||
}),
|
||||
// Dimensão detectada do ERP e detalhamento por grupo (vazio quando global).
|
||||
metaDimensao: MetaDimensaoSchema.default('global'),
|
||||
metasPorGrupo: z.array(MetaItemSchema).default([]),
|
||||
comissao: z.object({
|
||||
fixa: z.number(),
|
||||
flex: z.number(),
|
||||
@@ -32,6 +60,7 @@ export type RepDashboard = z.infer<typeof RepDashboardSchema>;
|
||||
|
||||
export const RepInativosSummarySchema = z.object({
|
||||
codVendedor: z.number().int(),
|
||||
nomeVendedor: z.string().nullable().optional(),
|
||||
inativosCount: z.number().int(),
|
||||
});
|
||||
export type RepInativosSummary = z.infer<typeof RepInativosSummarySchema>;
|
||||
|
||||
Reference in New Issue
Block a user