feat(reportes): rango salarial en buckets + script de importacion de afluencia
- bucketSalario: el texto libre del rango salarial ('$80k', '4,500 DLLS',
'50-80 MIL') se agrupa en rangos por moneda para que la grafica sea
legible; valores sin monto se omiten.
- scripts/importar-afluencia-agosto.py: importa el historial de
afluencia al tablero Leads con normalizacion de catalogos, dedup por
telefono y desregistro temporal del webhook create_item (para no
disparar round-robin ni oportunidades con datos historicos).
This commit is contained in:
@@ -230,7 +230,7 @@ describe('construirResumen', () => {
|
||||
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 })
|
||||
expect(r.leads.perfil.porRangoSalarial).toEqual({ 'Hasta $30k MXN': 1 }) // '20-30 mil' → 25k
|
||||
// Dimensiones sin ningún dato van como objeto vacío
|
||||
expect(r.leads.perfil.porModelo).toEqual({})
|
||||
expect(r.leads.perfil.porTipoEmpleo).toEqual({})
|
||||
@@ -239,6 +239,35 @@ describe('construirResumen', () => {
|
||||
expect(r.leads.perfil.porLoQuierePara).toEqual({})
|
||||
})
|
||||
|
||||
it('perfil: rango salarial de texto libre se agrupa en buckets por moneda', () => {
|
||||
const r = construirResumen(
|
||||
{
|
||||
...DATOS_BASE,
|
||||
leads: [
|
||||
lead('1', { rangoSalarial: '16000' }), // Hasta $30k MXN
|
||||
lead('2', { rangoSalarial: '$45K' }), // $30k–$60k MXN
|
||||
lead('3', { rangoSalarial: '85,000.00 PESOS' }), // $60k–$100k MXN
|
||||
lead('4', { rangoSalarial: '100,000.00-120,000.00' }), // Más de $100k MXN (promedio 110k)
|
||||
lead('5', { rangoSalarial: '$2,5K dlls' }), // Hasta $3k USD (2,500)
|
||||
lead('6', { rangoSalarial: '4,500 DLLS' }), // $3k–$5k USD
|
||||
lead('7', { rangoSalarial: '8,000.000 DLLS' }), // Más de $5k USD (8,000)
|
||||
lead('8', { rangoSalarial: 'NO QUISO DECIR' }), // sin monto: se salta
|
||||
lead('9', { rangoSalarial: '' }), // vacío: se salta
|
||||
],
|
||||
},
|
||||
AHORA,
|
||||
)
|
||||
expect(r.leads.perfil.porRangoSalarial).toEqual({
|
||||
'Hasta $30k MXN': 1,
|
||||
'$30k–$60k MXN': 1,
|
||||
'$60k–$100k MXN': 1,
|
||||
'Más de $100k MXN': 1,
|
||||
'Hasta $3k USD': 1,
|
||||
'$3k–$5k USD': 1,
|
||||
'Más de $5k USD': 1,
|
||||
})
|
||||
})
|
||||
|
||||
it('perfil: buckets de edad y salto de edad null', () => {
|
||||
const r = construirResumen(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user