feat(politicas): regras de desconto por grupo/subgrupo/rep e condicoes comerciais no catalogo
- Nova tabela sar.regras_desconto (grupo, subgrupo, representante, % e vigencia; campos nulos = todos) com migration idempotente, espelho no sar-erp-schema.sql e GRANT no provision-client - CRUD manager-only em /politicas/regras + aba "Regras de Desconto" na tela de Politicas Comerciais (selects com nomes de rep/grupo/subgrupo via /politicas/grupos-produto) - GET /politicas/regras/vigentes (rep ve so as que o alcancam) e GET /politicas/promocoes/vigentes para o catalogo - Regra vigente pre-aplica o desconto no carrinho do novo pedido - Selos "Promocao"/"Cond. especial" na busca de produto, catalogo do pedido e pagina de catalogo; secao "Condicoes Comerciais" no modal de detalhe do produto (descricao, % e validade) - Empty imageStyle deprecado -> styles.image no carrinho Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,3 +53,92 @@ export const UpdatePromocaoBodySchema = CreatePromocaoBodySchema.partial().exten
|
||||
ativa: z.boolean().optional(),
|
||||
});
|
||||
export type UpdatePromocaoBody = z.infer<typeof UpdatePromocaoBodySchema>;
|
||||
|
||||
// ─── Regras de Desconto ───────────────────────────────────────────────────────
|
||||
// Regra criada pelo Gerente: % de desconto liberado por grupo e/ou subgrupo de
|
||||
// produto e/ou representante, com vigência. Campos nulos = "todos".
|
||||
|
||||
export const RegraDescontoSchema = z.object({
|
||||
id: z.number().int(),
|
||||
descricao: z.string(),
|
||||
codGrupo: z.number().int().nullable(),
|
||||
grupo: z.string().nullable(),
|
||||
codSubgrupo: z.number().int().nullable(),
|
||||
subgrupo: z.string().nullable(),
|
||||
codVendedor: z.number().int().nullable(),
|
||||
nomeVendedor: z.string().nullable(),
|
||||
descPct: z.number(),
|
||||
dataInicio: z.string(),
|
||||
dataFim: z.string(),
|
||||
ativa: z.boolean(),
|
||||
createdAt: z.string(),
|
||||
createdBy: z.string(),
|
||||
});
|
||||
export type RegraDesconto = z.infer<typeof RegraDescontoSchema>;
|
||||
|
||||
export const RegrasDescontoResponseSchema = z.object({
|
||||
regras: z.array(RegraDescontoSchema),
|
||||
});
|
||||
export type RegrasDescontoResponse = z.infer<typeof RegrasDescontoResponseSchema>;
|
||||
|
||||
export const CreateRegraDescontoBodySchema = z.object({
|
||||
descricao: z.string().min(1).max(200),
|
||||
codGrupo: z.number().int().nullable().optional(),
|
||||
codSubgrupo: z.number().int().nullable().optional(),
|
||||
codVendedor: z.number().int().nullable().optional(),
|
||||
descPct: z.number().min(0).max(100),
|
||||
dataInicio: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
||||
dataFim: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
||||
});
|
||||
export type CreateRegraDescontoBody = z.infer<typeof CreateRegraDescontoBodySchema>;
|
||||
|
||||
export const UpdateRegraDescontoBodySchema = CreateRegraDescontoBodySchema.partial().extend({
|
||||
ativa: z.boolean().optional(),
|
||||
});
|
||||
export type UpdateRegraDescontoBody = z.infer<typeof UpdateRegraDescontoBodySchema>;
|
||||
|
||||
// Promoções vigentes hoje — visíveis ao rep para sinalizar condição no catálogo
|
||||
export const PromocaoVigenteSchema = z.object({
|
||||
id: z.number().int(),
|
||||
descricao: z.string(),
|
||||
codProduto: z.string().nullable(),
|
||||
grpProd: z.string().nullable(),
|
||||
descPct: z.number(),
|
||||
dataFim: z.string(),
|
||||
});
|
||||
export type PromocaoVigente = z.infer<typeof PromocaoVigenteSchema>;
|
||||
|
||||
export const PromocoesVigentesResponseSchema = z.object({
|
||||
promocoes: z.array(PromocaoVigenteSchema),
|
||||
});
|
||||
export type PromocoesVigentesResponse = z.infer<typeof PromocoesVigentesResponseSchema>;
|
||||
|
||||
// Regras vigentes para o representante logado — aplicadas na montagem do pedido
|
||||
export const RegraVigenteSchema = z.object({
|
||||
id: z.number().int(),
|
||||
descricao: z.string(),
|
||||
codGrupo: z.number().int().nullable(),
|
||||
codSubgrupo: z.number().int().nullable(),
|
||||
descPct: z.number(),
|
||||
dataFim: z.string(),
|
||||
});
|
||||
export type RegraVigente = z.infer<typeof RegraVigenteSchema>;
|
||||
|
||||
export const RegrasVigentesResponseSchema = z.object({
|
||||
regras: z.array(RegraVigenteSchema),
|
||||
});
|
||||
export type RegrasVigentesResponse = z.infer<typeof RegrasVigentesResponseSchema>;
|
||||
|
||||
// Grupos/subgrupos de produto (combos do formulário do gerente)
|
||||
export const GrupoProdutoItemSchema = z.object({
|
||||
codGrupo: z.number().int().nullable(),
|
||||
grupo: z.string().nullable(),
|
||||
codSubgrupo: z.number().int().nullable(),
|
||||
subgrupo: z.string().nullable(),
|
||||
});
|
||||
export type GrupoProdutoItem = z.infer<typeof GrupoProdutoItemSchema>;
|
||||
|
||||
export const GruposProdutoResponseSchema = z.object({
|
||||
grupos: z.array(GrupoProdutoItemSchema),
|
||||
});
|
||||
export type GruposProdutoResponse = z.infer<typeof GruposProdutoResponseSchema>;
|
||||
|
||||
Reference in New Issue
Block a user