feat: conversión lead→oportunidad (Agendo) y alta ligada a apartado
- Mis leads: botón 'Agendo →' convierte el lead en oportunidad (etapa Agendo Cita, con sus datos, asesor = vendedor del lead o quien convierte), marca el lead Calificado y guarda el mapping LeadOportunidad; 409 si ya fue convertido - Mis oportunidades: se quitan No Asistio y Abandono (redundantes con Descartar); quedan Cotizar, Afluencia, Agendo Cita y Aparto - Mis apartados: 'Firma cliente (venta) →' abre el alta de cliente con TODO lo recolectado prellenado (ficha del apartado + contacto + oportunidad + cotización vinculada vía GET /altas/prefill-apartado/:id) - El alta con apartadoMondayId se LIGA al apartado existente y lo enriquece (curp, teléfono, email, precio final, enganche, forma de pago, unidad) en vez de crear un duplicado - monday.service: actualizarApartado + ApartadoMonday con curp, forma de pago, enganche y monto apartado - Tests: 470 API + 120 alta-clientes + 16 mi-dia, verde
This commit is contained in:
79
apps/alta-clientes/src/lib/apartadoAlta.test.ts
Normal file
79
apps/alta-clientes/src/lib/apartadoAlta.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { apartadoAPrellenado, type PrefillApartado } from './apartadoAlta'
|
||||
|
||||
const base: PrefillApartado = {
|
||||
apartado: {
|
||||
id: 'a1',
|
||||
nombre: 'Ana Demo',
|
||||
telefono: '+52 6641234567',
|
||||
email: 'ana@correo.com',
|
||||
curp: '',
|
||||
unidadCodigo: 'SENDA-409-1-2',
|
||||
precioFinal: 2646000,
|
||||
enganche: 132300,
|
||||
formaPago: 'Cofinavit',
|
||||
},
|
||||
contacto: {
|
||||
nombre: 'Ana Demo',
|
||||
CURP: 'AAXX010101XXXXXXX0',
|
||||
RFC: 'AAXX010101XXX',
|
||||
Dirección: 'Calle 1, Col. Centro, CP 38000',
|
||||
'Estado Civil': 'Casado(a)',
|
||||
'Fecha Nacimiento': '1990-05-12',
|
||||
},
|
||||
oportunidad: { id: 'op-1', desarrollo: 'SENDA', modeloInteres: 'SOHO', credito: 'Cofinavit' },
|
||||
cotizacion: { tipoPropuesta: 'INFONAVIT', acabados: true, precioFinal: 2646000, enganche: 132300 },
|
||||
}
|
||||
|
||||
describe('apartadoAPrellenado (alta desde apartado de Monday)', () => {
|
||||
it('prellena datos generales (contacto manda) y vivienda/crédito (apartado > oportunidad > cotización)', () => {
|
||||
const p = apartadoAPrellenado(base)
|
||||
expect(p.datosGenerales).toMatchObject({
|
||||
nombreCompleto: 'ANA DEMO',
|
||||
email: 'ana@correo.com',
|
||||
celular: '+52 6641234567',
|
||||
curp: 'AAXX010101XXXXXXX0',
|
||||
rfc: 'AAXX010101XXX',
|
||||
direccion: 'CALLE 1, COL. CENTRO, CP 38000',
|
||||
fechaNacimiento: '1990-05-12',
|
||||
estadoCivil: 'CASADO',
|
||||
})
|
||||
expect(p.viviendaCredito).toMatchObject({
|
||||
proyecto: 'SENDA',
|
||||
modelo: 'SOHO',
|
||||
ubicacion: 'SENDA-409-1-2',
|
||||
valorVenta: '2646000',
|
||||
enganche: '132300',
|
||||
tiposCredito: ['COFINAVIT'], // formaPago del apartado manda sobre la cotización
|
||||
equipamientoAdicional: 'COCINA Y CLOSET', // cotización con acabados
|
||||
})
|
||||
expect(p.leadMondayId).toBe('op-1')
|
||||
})
|
||||
|
||||
it('desarrollo desconocido cae en OTRO con el nombre en texto libre', () => {
|
||||
const p = apartadoAPrellenado({ ...base, oportunidad: { id: 'op-1', desarrollo: 'MONTEBELLO' } })
|
||||
expect(p.viviendaCredito.proyecto).toBe('OTRO')
|
||||
expect(p.viviendaCredito.proyectoOtro).toBe('MONTEBELLO')
|
||||
})
|
||||
|
||||
it('sin contacto usa los datos del apartado; sin créditos no prellena tiposCredito', () => {
|
||||
const p = apartadoAPrellenado({
|
||||
...base,
|
||||
contacto: null,
|
||||
apartado: { ...base.apartado, formaPago: '' },
|
||||
oportunidad: { id: 'op-1', desarrollo: 'SENDA' },
|
||||
cotizacion: null,
|
||||
})
|
||||
expect(p.datosGenerales).toMatchObject({ nombreCompleto: 'ANA DEMO', email: 'ana@correo.com', celular: '+52 6641234567' })
|
||||
expect(p.datosGenerales.curp).toBeUndefined()
|
||||
expect(p.datosGenerales.estadoCivil).toBeUndefined()
|
||||
expect(p.viviendaCredito.tiposCredito).toBeUndefined()
|
||||
expect(p.viviendaCredito.equipamientoAdicional).toBeUndefined()
|
||||
expect(p.leadMondayId).toBe('op-1')
|
||||
})
|
||||
|
||||
it('sin oportunidad relacionada el alta queda sin lead ligado', () => {
|
||||
const p = apartadoAPrellenado({ ...base, oportunidad: null })
|
||||
expect(p.leadMondayId).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user