feat(monday): alinear Frasa-CAS con CRM real del cliente (7 mejoras)
- Vocabulario funnel: labels Intento de contacto/Abandono en Leads, etapas completas en Oportunidades (Cotizador, Ganado, Perdido...) - Apartados: pipeline Enkontrol (8 estados) + checkboxes CURP/RFC/Comprobante que la app de alta prende al subir documentos - Motivos No Compra: board catálogo + dropdown + endpoint /oportunidades/:id/perder - Perfil demográfico en Contactos mapeado desde el alta (estado civil, vivienda, propósito, fecha nac., rango de edad calculado) - Desarrollos: catálogo maestro sincronizado (precios, m2, tipo, entrega) - Actividades: board nuevo + creación automática en round-robin e inactividad - Cobranza: plan liquidado mueve el apartado a 'X Escriturar' en Monday - Scripts: setup:crm y sync:desarrollos (idempotentes) - Tests 119/119 verdes
This commit is contained in:
75
api-gateway/src/controllers/clientes.controller.test.ts
Normal file
75
api-gateway/src/controllers/clientes.controller.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
actividadEconomicaLabel,
|
||||
checkboxParaTipoDocumento,
|
||||
perfilDemografico,
|
||||
rangoEdadLabel,
|
||||
} from './clientes.controller.js'
|
||||
|
||||
describe('checkboxParaTipoDocumento (Apartado → checkboxes de documentos)', () => {
|
||||
it('mapea los tipos con checkbox al título de la columna', () => {
|
||||
expect(checkboxParaTipoDocumento('CURP')).toBe('CURP')
|
||||
expect(checkboxParaTipoDocumento('RFC')).toBe('RFC')
|
||||
expect(checkboxParaTipoDocumento('CONSTANCIA_RFC')).toBe('RFC')
|
||||
expect(checkboxParaTipoDocumento('COMPROBANTE')).toBe('Comprobante')
|
||||
expect(checkboxParaTipoDocumento('COMPROBANTE_DOMICILIO')).toBe('Comprobante')
|
||||
})
|
||||
|
||||
it('normaliza mayúsculas y espacios', () => {
|
||||
expect(checkboxParaTipoDocumento(' curp ')).toBe('CURP')
|
||||
expect(checkboxParaTipoDocumento('comprobante_domicilio')).toBe('Comprobante')
|
||||
})
|
||||
|
||||
it('INE y otros tipos no tienen checkbox (null)', () => {
|
||||
expect(checkboxParaTipoDocumento('INE')).toBeNull()
|
||||
expect(checkboxParaTipoDocumento('ACTA_NACIMIENTO')).toBeNull()
|
||||
expect(checkboxParaTipoDocumento('OTRO')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('rangoEdadLabel', () => {
|
||||
const hoy = new Date('2026-08-22T12:00:00')
|
||||
|
||||
it('deriva el rango del CRM a partir de la fecha de nacimiento', () => {
|
||||
expect(rangoEdadLabel('2003-01-01', hoy)).toBe('Menor de 24') // 23 años
|
||||
expect(rangoEdadLabel('2002-08-22', hoy)).toBe('Entre 24 y 40') // cumple 24 hoy
|
||||
expect(rangoEdadLabel('1990-05-10', hoy)).toBe('Entre 24 y 40')
|
||||
expect(rangoEdadLabel('1986-08-21', hoy)).toBe('Entre 24 y 40') // 40 años: límite inclusivo
|
||||
expect(rangoEdadLabel('1985-01-01', hoy)).toBe('Mayor de 40')
|
||||
})
|
||||
|
||||
it('devuelve undefined con fechas inválidas o ausentes', () => {
|
||||
expect(rangoEdadLabel(undefined, hoy)).toBeUndefined()
|
||||
expect(rangoEdadLabel('no-es-fecha', hoy)).toBeUndefined()
|
||||
expect(rangoEdadLabel('2999-01-01', hoy)).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('perfilDemografico (alta → Contacto Monday)', () => {
|
||||
it('mapea los valores del formato a los labels del CRM', () => {
|
||||
const perfil = perfilDemografico({
|
||||
estadoCivil: 'UNION_LIBRE',
|
||||
tipoVivienda: 'FAMILIAR',
|
||||
tipoCompra: 'VIVIR_AHI',
|
||||
fechaNacimiento: '1990-05-10',
|
||||
})
|
||||
expect(perfil.estadoCivilLabel).toBe('Union Libre')
|
||||
expect(perfil.viviendaActualLabel).toBe('Comparte con familia')
|
||||
expect(perfil.propositoCompraLabel).toBe('Habitarla')
|
||||
expect(perfil.rangoEdadLabel).toBe('Entre 24 y 40')
|
||||
expect(perfil.fechaNacimiento).toBe('1990-05-10')
|
||||
})
|
||||
|
||||
it('omite campos vacíos o desconocidos (no inventa datos)', () => {
|
||||
expect(perfilDemografico({})).toEqual({})
|
||||
expect(perfilDemografico({ estadoCivil: '', tipoVivienda: 'OTRA_COSA' })).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe('actividadEconomicaLabel', () => {
|
||||
it('solo ASALARIADO tiene equivalencia inequívoca (Empleado)', () => {
|
||||
expect(actividadEconomicaLabel('ASALARIADO')).toBe('Empleado')
|
||||
expect(actividadEconomicaLabel('INDEPENDIENTE')).toBeUndefined() // ambiguo: no se adivina
|
||||
expect(actividadEconomicaLabel(undefined)).toBeUndefined()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user