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:
42
api-gateway/src/controllers/planes.controller.test.ts
Normal file
42
api-gateway/src/controllers/planes.controller.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { notificarEscrituracionSiLiquidado } from './planes.controller.js'
|
||||
|
||||
/** Monday mockeado: registra cambios de columna */
|
||||
function mondayMock() {
|
||||
return {
|
||||
cambios: [] as { boardId: string; itemId: string; columna: string; valor: unknown }[],
|
||||
async cambiarValorColumna(boardId: string, itemId: string, columna: string, valor: string | number | boolean) {
|
||||
this.cambios.push({ boardId, itemId, columna, valor })
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe('notificarEscrituracionSiLiquidado (puente cobranza → postventa)', () => {
|
||||
it('plan LIQUIDADO con mondayItemId: mueve el apartado a "X Escriturar"', async () => {
|
||||
const monday = mondayMock()
|
||||
const ok = await notificarEscrituracionSiLiquidado({ mondayItemId: 'apt-55' }, true, monday)
|
||||
expect(ok).toBe(true)
|
||||
// board 666 = MONDAY_BOARD_APARTADO de test
|
||||
expect(monday.cambios).toEqual([
|
||||
{ boardId: '666', itemId: 'apt-55', columna: 'Estado', valor: 'X Escriturar' },
|
||||
])
|
||||
})
|
||||
|
||||
it('no hace nada si el plan no está liquidado o no tiene item ligado', async () => {
|
||||
const monday = mondayMock()
|
||||
expect(await notificarEscrituracionSiLiquidado({ mondayItemId: 'apt-55' }, false, monday)).toBe(false)
|
||||
expect(await notificarEscrituracionSiLiquidado({ mondayItemId: null }, true, monday)).toBe(false)
|
||||
expect(await notificarEscrituracionSiLiquidado({}, true, monday)).toBe(false)
|
||||
expect(monday.cambios).toEqual([])
|
||||
})
|
||||
|
||||
it('un fallo de Monday no rompe el abono: loguea y devuelve false', async () => {
|
||||
const monday = mondayMock()
|
||||
vi.spyOn(monday, 'cambiarValorColumna').mockRejectedValueOnce(new Error('Monday caído'))
|
||||
const spyError = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const ok = await notificarEscrituracionSiLiquidado({ mondayItemId: 'apt-55' }, true, monday)
|
||||
expect(ok).toBe(false)
|
||||
expect(spyError).toHaveBeenCalled()
|
||||
spyError.mockRestore()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user