SEGURIDAD (agente IA):
- Conversaciones: GET /ai/conversations/:id y el reanudar chat verifican
propiedad (antes cualquier usuario leia/continuaba la conversacion de otro).
- /ai/documents pasa a solo-admin (antes cualquien podia inyectar o borrar
documentos de la base de conocimiento).
DATOS / CORRUPCION:
- Cotizador: elegir un cliente del maestro en el buscador ya no crea un lead
fantasma "Registro previo (CRM anterior)" en el embudo.
- Afluencia con oportunidadId inexistente: 404 en vez de crear sombra fantasma.
- Cobranza: los 103 planes importados quedaron con vendedor asignado (7 con su
asesor real segun el Excel, el resto al admin) y el motor de recordatorios
cae al admin cuando un plan no tiene vendedor: antes los 411 recordatorios
se registraban 'sin-destinatario' y no los veia nadie.
- Backups: script reescrito para el host real (sqlite .backup + uploads + env
en /root/backups) y cron instalado (antes: script que asumia docker y sin
cron programado = cero respaldos).
REPORTES / METRICAS:
- Mi tablero: el embudo ya excluye cancelaciones reales (Cancelo/Cancelacion
Apartado) y cuenta como vendidos Firma Cliente/Escriturado/Titulado (antes
41 "apartados" donde habia 13 activos y vendidos buscaba una etapa que no
existe); tasa de descarte ya compara el mismo periodo.
- Scoring: etapa real 'Agendo Cita' (antes 'AGENDO' nunca aplicaba) y los
descartados/perdidos ya no reciben score.
- ver_cobranza (IA): ignora planes cancelados y no cuenta como vencido el pago
que vence hoy.
UI / FLUJOS:
- mi-dia: typo CANCO -> CANCELO (los cancelados reaparecen en Escrituracion);
confirmar cita ya no retrocede la etapa de Cotizador/Aparto (boton y kanban).
- alta-clientes: la firma ya no se borra al navegar fuera del paso de firmas;
toast de exito solo cuando el API confirma; prefill de apartado trae
direccion, estado civil y fecha de nacimiento desde el alta.
- Auditoria: el filtro por usuario funciona (el front enviaba 'usuario' y el
API esperaba 'usuarioId') y 'hasta' incluye todo el dia.
- Contactos: paginacion aplicada despues de fusionar fuentes (antes saltaban o
se repetian contactos entre paginas y 'Siguiente' se deshabilitaba antes de
tiempo).
- Buscador global: leads -> /hoy/, contactos -> /; el cotizador entiende
?cotizacion=<id> para retomar desde la liga.
- Export mi-dia: columnas Desarrollo/Origen rellenas y sin duplicados.
- Recibo de cobranza: "Recibio" es FRASA (el cliente paga, no recibe).
- Alta de plan de cobranza: proyecto libre con sugerencias del catalogo real
(antes limitado a 3 proyectos que no cubrian la cartera).
Verificado en vivo: autorizacion IA (3x 403), filtro de auditoria, 404 de
afluencia. Suites: 717 API + 124 alta-clientes + 115 cotizador + 92 cobranza +
89 landing + 32 mi-dia en verde. Backup de hoy generado en /root/backups.
- 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