import { z } from 'zod'; // Contratos canônicos de C2 — Consulta de Clientes. // Consumidos pela API (output tipado) e pela Web (TanStack Query + parse). // ADR 0006 revogado: id UUID → idCliente Int (sig.corrent.id_corrent) // ─── Enums ──────────────────────────────────────────────────────────────────── export const ActivityStatusSchema = z.enum(['active', 'alert', 'inactive']); export type ActivityStatus = z.infer; // ─── Client Summary (lista) ─────────────────────────────────────────────────── export const ClientSummarySchema = z.object({ idCliente: z.number().int(), idEmpresa: z.number().int(), nome: z.string(), razao: z.string().nullable(), cgcpf: z.string().nullable(), email: z.string().nullable(), telefone: z.string().nullable(), codVendedor: z.number().int(), nomeVendedor: z.string().nullable().optional(), limiteCreditoStr: z.string().nullable(), activityStatus: ActivityStatusSchema, dtUltimaCompra: z.iso.datetime().nullable(), }); export type ClientSummary = z.infer; // ─── Client Detail (ficha) ─────────────────────────────────────────────────── export const ClientDetailSchema = ClientSummarySchema.extend({ ativo: z.number().int(), pessoa: z.number().int().nullable(), inscricaoEstadual: z.string().nullable(), endereco: z.string().nullable(), numEndereco: z.string().nullable(), bairro: z.string().nullable(), cep: z.string().nullable(), ddd: z.string().nullable(), obs: z.string().nullable(), codPauta: z.number().int().nullable(), dtCadastro: z.string().nullable(), dtAtual: z.string().nullable(), }); export type ClientDetail = z.infer; // ─── List query + response ──────────────────────────────────────────────────── export const ClientListQuerySchema = z.object({ q: z.string().optional(), status: ActivityStatusSchema.optional(), page: z.coerce.number().int().positive().default(1), limit: z.coerce.number().int().min(1).max(200).default(50), }); export type ClientListQuery = z.infer; export const ClientListResponseSchema = z.object({ data: z.array(ClientSummarySchema), total: z.number().int().nonnegative(), page: z.number().int().positive(), limit: z.number().int().positive(), }); export type ClientListResponse = z.infer; // ─── Contato ───────────────────────────────────────────────────────────────── export const ContatoSchema = z.object({ idContato: z.number().int(), idEmpresa: z.number().int(), idCorrent: z.number().int(), idChatwoot: z.number().int().nullable(), nome: z.string(), empresa: z.string().nullable(), cargo: z.string().nullable(), departamento: z.string().nullable(), dtAniversario: z.string().nullable(), telefone: z.string().nullable(), ramal: z.string().nullable(), celular: z.string().nullable(), whatsapp: z.string().nullable(), email: z.string().nullable(), ativo: z.number().int(), anotacoes: z.string().nullable(), nomeCliente: z.string().nullable(), razaoCliente: z.string().nullable(), codVendedor: z.number().int().nullable(), }); export type Contato = z.infer; export const CreateContatoSchema = z.object({ nome: z.string().min(1).max(100), empresa: z.string().max(100).optional(), cargo: z.string().max(100).optional(), departamento: z.string().max(100).optional(), dtAniversario: z .string() .regex(/^\d{4}-\d{2}-\d{2}$/, 'Data deve ser YYYY-MM-DD') .optional(), telefone: z.string().max(20).optional(), ramal: z.string().max(10).optional(), celular: z.string().max(20).optional(), whatsapp: z.string().max(20).optional(), email: z.string().max(150).optional(), anotacoes: z.string().optional(), }); export type CreateContato = z.infer; export const ContatoResultSchema = z.object({ id: z.string().uuid(), idContatoErp: z.number().int().nullable(), sincronizado: z.boolean(), erroSync: z.string().nullable(), }); export type ContatoResult = z.infer; // ─── Produtos mais comprados por cliente ───────────────────────────────────── export const TopProdutoSchema = z.object({ idProduto: z.number().int(), codProduto: z.string(), descricao: z.string(), unidade: z.string().nullable(), qtdTotal: z.number(), numPedidos: z.number().int(), ultimaCompra: z.string(), ultimoPreco: z.number(), }); export type TopProduto = z.infer; // ─── Contas a Receber (resumo por cliente) ─────────────────────────────────── export const CtrSummarySchema = z.object({ qtdAberto: z.number().int(), totalAberto: z.number(), qtdVencido: z.number().int(), totalVencido: z.number(), maiorAtrasoDias: z.number().int(), }); export type CtrSummary = z.infer; // ─── Contas a Receber (lista de títulos em aberto) ──────────────────────────── export const CtrTituloSchema = z.object({ idCtr: z.number().int(), numero: z.string(), prefixo: z.string(), dtEmissao: z.string(), dtVencimento: z.string(), saldo: z.number(), }); export type CtrTitulo = z.infer; // ─── Notas Fiscais por cliente ─────────────────────────────────────────────── export const NotaFiscalSchema = z.object({ idNf: z.number().int(), numero: z.number().int(), serie: z.string(), dtEmissao: z.string(), vlNf: z.number(), chaveAcessoNfe: z.string().nullable(), }); export type NotaFiscal = z.infer; // ─── Municipio ─────────────────────────────────────────────────────────────── export const MunicipioSchema = z.object({ idMunicipio: z.number().int(), nome: z.string(), uf: z.string(), codigoIbge: z.number().int().nullable(), }); export type Municipio = z.infer; // ─── Criar Cliente Novo ─────────────────────────────────────────────────────── // pesso: 0=PJ (CNPJ), 1=PF (CPF) — campo do ERP, não renomear // indicadorIe: 1=contribuinte, 2=isento, 9=não contribuinte export const CreateClientNovoSchema = z.object({ pesso: z.union([z.literal(0), z.literal(1)]), consfinal: z.union([z.literal(0), z.literal(1)]).default(0), nome: z.string().min(1).max(40), razao: z.string().min(1).max(65), cgcpf: z.string().max(18).optional(), sufCgcpf: z.string().max(3).default(''), inscr: z.string().max(18).default(''), indicadorIe: z.union([z.literal(1), z.literal(2), z.literal(9)]).optional(), endereco: z.string().max(60).default(''), numEndereco: z.string().max(10).default(''), bairro: z.string().max(60).default(''), idMunicipio: z.number().int().positive(), cep: z.string().max(9).default(''), ddd: z.string().max(4).default(''), telefone: z.string().max(35).default(''), email: z.string().max(80).default(''), limiteCredito: z.number().nonnegative().default(0), codFormapag: z.number().int().optional(), codPauta: z.number().int().optional(), }); export type CreateClientNovo = z.infer; export const ClientNovoResultSchema = z.object({ id: z.string().uuid(), idCorrentErp: z.number().int().nullable(), sincronizado: z.boolean(), erroSync: z.string().nullable(), }); export type ClientNovoResult = z.infer;