feat(afluencia): captura completa de perfil en alta de afluencia

Agrega al formulario ligero y a POST /api/leads: tipo de propiedad,
medio de contacto, edad, estado civil, tipo de empleo, ocupacion,
rango salarial, credito, tipo de economia, califica y lo quiere para.
Selects obligatorios (estado civil, tipo de empleo, tipo de economia,
califica) con las etiquetas sembradas como labels status en el tablero
Leads de Monday.
This commit is contained in:
2026-09-02 01:38:13 +00:00
parent f7070c9c35
commit 52667df041
7 changed files with 388 additions and 27 deletions

View File

@@ -101,6 +101,38 @@ describe('crearLead (POST /api/leads)', () => {
expect(monday.leadsCreados[0]).toMatchObject({ email: 'lead@correo.com', desarrolloLabel: 'SENDA' })
})
it('pasa los campos de calificación al item de Monday (labels listos para el board)', async () => {
const monday = mondayMock()
const r = await crearLead(monday, {
...datosBase,
tipoPropiedad: 'Casa',
medioContacto: 'WhatsApp',
edad: 35,
estadoCivil: 'Casado(a)',
tipoEmpleo: 'Asalariado',
ocupacion: 'Ingeniero',
rangoSalarial: '$20,000 - $30,000',
credito: 'Infonavit',
tipoEconomia: 'Economía mexicana',
califica: 'Sí',
loQuierePara: 'Vivir ahí',
})
expect(r).toEqual({ id: 'lead-nuevo-1', oportunidadId: null })
expect(monday.leadsCreados[0]).toMatchObject({
tipoPropiedadLabel: 'Casa',
medioContacto: 'WhatsApp',
edad: 35,
estadoCivilLabel: 'Casado(a)',
tipoEmpleoLabel: 'Asalariado',
ocupacion: 'Ingeniero',
rangoSalarial: '$20,000 - $30,000',
creditoLabel: 'Infonavit',
tipoEconomiaLabel: 'Economía mexicana',
calificaLabel: 'Sí',
loQuierePara: 'Vivir ahí',
})
})
it('con funnel: asegura la oportunidad de Afluencia con los datos del lead', async () => {
const monday = mondayMock()
const funnel = funnelMock()

View File

@@ -22,6 +22,19 @@ const crearLeadSchema = z.object({
origen: z.string().trim().min(1).optional(),
desarrollo: z.string().trim().min(1).optional(),
notas: z.string().trim().min(1).optional(),
// Campos de calificación de la afluencia (opcionales; los labels fijos del
// front coinciden con los sembrados en Monday, no se validan contra el board)
tipoPropiedad: z.string().trim().min(1).optional(),
medioContacto: z.string().trim().min(1).optional(),
edad: z.coerce.number().int().min(15).max(120).optional(),
estadoCivil: z.string().trim().min(1).optional(),
tipoEmpleo: z.string().trim().min(1).optional(),
ocupacion: z.string().trim().min(1).optional(),
rangoSalarial: z.string().trim().min(1).optional(),
credito: z.string().trim().min(1).optional(),
tipoEconomia: z.string().trim().min(1).optional(),
califica: z.string().trim().min(1).optional(),
loQuierePara: z.string().trim().min(1).optional(),
})
const cambiarEstadoSchema = z.object({
@@ -112,6 +125,17 @@ export async function crearLead(
origenLabel: datos.origen,
desarrolloLabel: datos.desarrollo,
notas: datos.notas,
tipoPropiedadLabel: datos.tipoPropiedad,
medioContacto: datos.medioContacto,
edad: datos.edad,
estadoCivilLabel: datos.estadoCivil,
tipoEmpleoLabel: datos.tipoEmpleo,
ocupacion: datos.ocupacion,
rangoSalarial: datos.rangoSalarial,
creditoLabel: datos.credito,
tipoEconomiaLabel: datos.tipoEconomia,
calificaLabel: datos.califica,
loQuierePara: datos.loQuierePara,
})
let oportunidadId: string | null = null

View File

@@ -882,6 +882,17 @@ export class MondayService {
Origen: datos.origenLabel,
Desarrollo: datos.desarrolloLabel,
Notas: datos.notas,
'Tipo de Propiedad': datos.tipoPropiedadLabel,
'Medio de Contacto': datos.medioContacto,
Edad: datos.edad,
'Estado Civil': datos.estadoCivilLabel,
'Tipo de Empleo': datos.tipoEmpleoLabel,
Ocupación: datos.ocupacion,
'Rango Salarial': datos.rangoSalarial,
Crédito: datos.creditoLabel,
'Tipo de Economía': datos.tipoEconomiaLabel,
Califica: datos.calificaLabel,
'Lo Quiere Para': datos.loQuierePara,
})
return this.crearItem(boardId, datos.nombre, columnValues)
}
@@ -1083,6 +1094,18 @@ export interface DatosLead {
origenLabel?: string | undefined // label real de la columna status 'Origen' del board Leads
desarrolloLabel?: string | undefined // label real de la columna status 'Desarrollo' del board Leads
notas?: string | undefined
// Campos de calificación del interesado (labels reales de las columnas status del board Leads)
tipoPropiedadLabel?: string | undefined
medioContacto?: string | undefined
edad?: number | undefined
estadoCivilLabel?: string | undefined
tipoEmpleoLabel?: string | undefined
ocupacion?: string | undefined
rangoSalarial?: string | undefined
creditoLabel?: string | undefined
tipoEconomiaLabel?: string | undefined
calificaLabel?: string | undefined
loQuierePara?: string | undefined
}
/** Singleton usado por los controllers (los tests instancian el suyo) */