- Firma Cliente (Venta) renombrada a Alta Enkontrol (mismo redirect a alta cliente)
- Campo 'Usuario Enkontrol' añadido en Datos Generales del alta cliente
- Unidad se bloquea (APARTADA) al pasar cliente a etapa Aparto
- Backend y frontend actualizados
- 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
- El alta (directa y progresiva) llena el Apartado con telefono, correo,
curp, Precio Final, Enganche, Fecha Compra, Vendedor (el capturista
con Monday vinculado) y Forma de Pago; el path webhook/cron hereda
contacto, precio y asesor de la oportunidad.
- Bidireccional: Mis clientes en /hoy muestra el estado actual del
Apartado leyendolo de Monday (si lo mueven en Monday, la app lo
refleja en el siguiente refresh).
- getApartados con la correccion value-null al leer Estado.
- Test del mapa de Tipo propuesta del cotizador (los 502 del log eran
de un proceso previo al fix 4f31d1c; queda cubierto).
- POST /api/leads crea UN solo item en Oportunidades (Estado Afluencia)
con todo el perfil (desarrollo, modelo, estado civil, credito, etc.)
en las columnas del board; dedup por telefono contra Oportunidades;
asignacion al capturista via columna Asesor o round-robin del equipo.
- Round-robin, escalado e inactividad operan sobre Oportunidades (solo
etapa Afluencia sin asesor entra al reparto).
- Acciones del vendedor (contactado/cita/descartar) escriben directo en
la oportunidad; descarte = Perdido + Motivo No Compra.
- Mi dia y reportes leen Oportunidades; el funnel de /dash arranca en
Afluencia; misOportunidades.porEtapa ya es real (columna Asesor).
- El picker del alta busca en Leads (historico) Y Oportunidades, con
insignia de origen; moverAAparto tolera ambos ids.
- Lectura de status con value null = vacio (quirk del default Monday).
- Script de migracion del historial de agosto Leads -> Oportunidades.
- 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.
- Al avanzar cada paso del wizard: upsert silencioso del borrador local
+ sync a Monday (iniciar → Contacto en PROSPECTO; pasos siguientes →
PATCH con los campos mapeables: datos generales, dirección armada,
actividad económica)
- Al completar: Contacto pasa a CLIENTE + Apartado + funnel (dedup)
- progresoId viaja con el borrador (se restaura solo); fallos de sync
no bloquean el avance (aviso ámbar no bloqueante); submit final con
fallback al endpoint legado si nunca hubo sync
- API: POST /clientes/progreso/iniciar, PATCH /clientes/progreso/:id,
POST /clientes/progreso/:id/completar; POST /clientes legado intacto
- Tests: API 338 (+16), alta-clientes 112 (+4); smoke en vivo
verificado (PROSPECTO → patch → CLIENTE + Apartado) y limpiado
- Captura rápida crea lead + oportunidad en etapa Afluencia (vinculadas
por nueva tabla LeadOportunidad); también aplica a leads creados
directo en Monday vía webhook
- Transiciones automáticas: AGENDA CITA → Agendo Cita, descarte →
Perdido (+ dropdown Motivo No Compra), cotización con mismo teléfono
ACTUALIZA la oportunidad (no duplica) → Cotizador, alta de cliente
con leadMondayId → Aparto (dedup previo para no duplicar Apartado)
- Columna Desarrollo agregada al board Oportunidades (color_mm6sa20t)
- Migración lead_oportunidad aplicada con migrate diff + resolve (la DB
tiene drift histórico por db push; migrate dev pedía reset)
- Tests: 322 verdes; smoke en vivo verificado y limpiado
- API: viviendaCredito.ubicacion ahora opcional (la app web no la exigía;
el desfase causaba 400 que la app mostraba como fallo de red)
- App: crearAltaCliente distingue conexion/validacion; el 400 muestra
banner rojo con el detalle de los issues en vez del banner ámbar
- Tests: api 160, alta-clientes 66
- 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
- api-gateway: servicio Monday (retry 429/complejidad, paginacion cursor,
column IDs por titulo), endpoints unidades/cotizaciones/clientes/planes,
webhook con handshake challenge, Prisma SQLite dev, 55 tests
- cotizador: inventario desde /api/unidades con fallback a seed
- alta-clientes: POST /api/clientes + upload multipart de documentos
- cobranza: persistencia via API con respaldo offline en localStorage
- .env.example con board IDs del workspace Frasa-CAS