feat(web+api): contatos vinculados a clientes com sync ERP e base WhatsApp
DB:
- sar.vw_contatos: view sobre gestao.contato com join sig.corrent
(id_entidade CHAR20 = id_corrent; cod_vendedor para filtro por rep)
- sar.contatos_novos: staging com nome, cargo, departamento, telefone,
celular, whatsapp, email, dt_aniversario, anotacoes
- trg_contato_novo: AFTER INSERT → gestao.contato; grava id_contato_erp
API:
- GET /clients/:id/contacts — lista contatos ativos do cliente
- POST /clients/:id/contacts — cria via staging; retorna { idContatoErp, sincronizado }
Web:
- ClientContacts: tabela de contatos no detalhe do cliente
- Links diretos WhatsApp (wa.me) + mailto por contato
- Modal "Novo Contato" com todos os campos; feedback de código ERP no sucesso
- whatsapp é o campo principal para envio futuro via ChatWoot
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,54 @@ export const ClientListResponseSchema = z.object({
|
||||
});
|
||||
export type ClientListResponse = z.infer<typeof ClientListResponseSchema>;
|
||||
|
||||
// ─── 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<typeof ContatoSchema>;
|
||||
|
||||
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().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<typeof CreateContatoSchema>;
|
||||
|
||||
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<typeof ContatoResultSchema>;
|
||||
|
||||
// ─── Municipio ───────────────────────────────────────────────────────────────
|
||||
|
||||
export const MunicipioSchema = z.object({
|
||||
|
||||
Reference in New Issue
Block a user