feat: mis clientes en Mi dia + perfilamiento de la afluencia en dashboards
- Cliente.capturadoPorId: el alta (directa y progresiva) registra al usuario que la inicio; el panel Mi dia muestra 'Mis clientes' con su estado (En captura / Cliente) sin depender de Monday. - LeadMonday ahora lee las 11 columnas de perfil del tablero Leads (estado civil, edad, rango salarial, tipo de empleo/economia, califica, credito, modelo, etc.). - GET /api/reportes/resumen agrega leads.perfil con conteos por dimension (valores vacios se omiten; edad en buckets). - /dash/ gana la seccion 'Perfilamiento de la afluencia' con mini-graficas de barras por dimension.
This commit is contained in:
@@ -213,6 +213,52 @@ describe('construirResumen', () => {
|
||||
expect(r.cobranza.planesAlCorriente).toBe(0)
|
||||
expect(r.cobranza.planesConVencidos).toBe(2)
|
||||
})
|
||||
|
||||
it('perfil: cuenta solo valores capturados (los vacíos no van a ningún bucket)', () => {
|
||||
const r = construirResumen(
|
||||
{
|
||||
...DATOS_BASE,
|
||||
leads: [
|
||||
lead('1', { estadoCivil: 'Soltero', desarrollo: 'ATELIER', credito: 'Bancario', califica: 'Si' }),
|
||||
lead('2', { estadoCivil: 'Soltero', desarrollo: 'ATELIER', rangoSalarial: '20-30 mil' }),
|
||||
lead('3', { estadoCivil: '', desarrollo: ' ' }), // sin dato: no cuenta en ninguna dimensión
|
||||
],
|
||||
},
|
||||
AHORA,
|
||||
)
|
||||
expect(r.leads.perfil.porEstadoCivil).toEqual({ Soltero: 2 })
|
||||
expect(r.leads.perfil.porDesarrollo).toEqual({ ATELIER: 2 })
|
||||
expect(r.leads.perfil.porCredito).toEqual({ Bancario: 1 })
|
||||
expect(r.leads.perfil.porCalifica).toEqual({ Si: 1 })
|
||||
expect(r.leads.perfil.porRangoSalarial).toEqual({ '20-30 mil': 1 })
|
||||
// Dimensiones sin ningún dato van como objeto vacío
|
||||
expect(r.leads.perfil.porModelo).toEqual({})
|
||||
expect(r.leads.perfil.porTipoEmpleo).toEqual({})
|
||||
expect(r.leads.perfil.porTipoEconomia).toEqual({})
|
||||
expect(r.leads.perfil.porMedioContacto).toEqual({})
|
||||
expect(r.leads.perfil.porLoQuierePara).toEqual({})
|
||||
})
|
||||
|
||||
it('perfil: buckets de edad y salto de edad null', () => {
|
||||
const r = construirResumen(
|
||||
{
|
||||
...DATOS_BASE,
|
||||
leads: [
|
||||
lead('1', { edad: 18 }), // 15–24
|
||||
lead('2', { edad: 24 }), // 15–24
|
||||
lead('3', { edad: 25 }), // 25–34
|
||||
lead('4', { edad: 39 }), // 35–44
|
||||
lead('5', { edad: 50 }), // 45–54
|
||||
lead('6', { edad: 55 }), // 55+
|
||||
lead('7', { edad: 70 }), // 55+
|
||||
lead('8', { edad: null }), // sin dato: se salta
|
||||
lead('9'), // edad undefined: se salta
|
||||
],
|
||||
},
|
||||
AHORA,
|
||||
)
|
||||
expect(r.leads.perfil.porEdad).toEqual({ '15–24': 2, '25–34': 1, '35–44': 1, '45–54': 1, '55+': 2 })
|
||||
})
|
||||
})
|
||||
|
||||
// ---------- ReportesService (cache en memoria) ----------
|
||||
|
||||
Reference in New Issue
Block a user