Arquitectura · Nova IA Assistant

Estado actual · Propuesta objetivo · Roadmap

28 modelos en 7 apps

whatsapp
comercial
proyectos
finanzas
inteligencia
microsoft365
whatsapp (3)
comercial (3)
Oportunidad
contacto→Contacto, proyecto→Proyecto, mensaje_origen→Mensaje, estado, valor
Compromiso
contacto→Contacto, proyecto→Proyecto, palanca→PalancaComercial, categoria, prioridad
PalancaComercial
nombre, estado, valor_estimado, contacto_clave(texto), proyecto_financiero→ProyectoFinanciero
proyectos (3)
Proyecto
nombre, cliente(texto), estado, valor
MiembroEquipo
nombre, rol, email
AsignacionProyecto (sin datos)
proyecto→Proyecto, miembro→MiembroEquipo
finanzas (13)
Tercero
nit, nombre, tipo_tercero, legacy_id
ProyectoFinanciero
tercero→Tercero, cliente_nombre(texto)
EstadoProyecto
codigo, nombre (maestro)
Ingreso
tercero→Tercero, proyecto→ProyectoFinanciero, cliente_nombre(texto)
PagoRecibido
ingreso→Ingreso
Egreso
tercero, proyecto→ProyectoFinanciero, gasto_planificado, obligacion
PagoEmitido
egreso→Egreso
GastoPlanificado
proyecto, tercero
Obligacion / ObligacionDetalle
Deudas periódicas (DIAN, bancos)
IngresoProyecto / EgresoProyecto
Distribución multi-proyecto (%)
PagoProgramado
proyecto, fecha, monto
inteligencia (5)
ConversacionAsistente
session_id, role, content, pending actions
ResumenReunion
subject, meeting_date, attendees(JSON), summary
MejoraAsistente
descripcion, contexto, prioridad
Error500 / AlertaLatencia
service, url, timestamp
microsoft365 (1)
MSToken
access_token, refresh_token (singleton)

Grafo de relaciones actual

Contacto whatsapp Mensaje whatsapp Oportunidad comercial Compromiso comercial PalancaComercial comercial Proyecto proyectos (delivery) cliente = TEXTO ⚠ MiembroEquipo proyectos Tercero finanzas ProyectoFinanciero finanzas Ingreso / Egreso finanzas Gaps: FK faltantes Contacto ≠ Tercero (mismo cliente, 2 tablas) Proyecto ≠ ProyectoFinanciero Palanca ≠ Proyecto FK existe FK débil / indirecta FK faltante (gap)

Hallazgos críticos

🔴Duplicación del concepto "cliente" en 5 lugares
UbicaciónTipoOrigen de datos
ContactoModeloWhatsApp bot + backfill proyectos + manual
TerceroModeloSync Alegra/Siigo
Proyecto.clienteCharFieldAlta manual proyecto
Ingreso.cliente_nombreCharFieldSync facturas venta
PalancaComercial.contacto_claveCharFieldAlta manual palanca

Ej: "Arcopack" existe como Contacto #42, Tercero #7, Proyecto.cliente texto y Ingreso.cliente_nombre con razón social completa. Ninguno sabe del otro.

🔴Duplicación del concepto "proyecto" en 3 modelos
ModeloPropósitoConexión
ProyectoDelivery / equipoNo tiene FK a nada financiero
ProyectoFinancieroContabilidad / facturaciónNo sabe que Proyecto existe
PalancaComercialMeta plan de brechaFK a ProyectoFinanciero (no al de delivery)
🟡FKs que faltan (acoplamientos débiles)
  • Contacto ↔ Tercero — el mismo cliente vive en 2 tablas sin puente
  • Proyecto ↔ ProyectoFinanciero — delivery y finanzas desconectados
  • Proyecto ↔ PalancaComercial — cerrar palanca no crea proyectos
  • Compromiso ↔ ProyectoFinanciero — no se filtra ingresos/egresos por tarea
  • ResumenReunion ↔ Contacto — attendees como JSON, requiere string match
  • MiembroEquipo ↔ Contacto (equipo) — dos tablas paralelas para el team
🟡Código muerto práctico (principal no conectado)
  • process_principal_message() — procesa mensajes entrantes de clientes (no conectado)
  • _handle_forwarded_lead / _handle_new_contact — auto-lead desde reenvío
  • Contacto.tipo='desconocido' — flujo de detección automática muerto
  • AnalisisDiario.mensajes_recibidos/enviados — campos no escritos actualmente
🟡Modelos infrautilizados
  • AsignacionProyecto — ~0 registros
  • GastoPlanificado — existe pero no hay UI ni tool
  • MejoraAsistente — se llena por chat sin vista de consulta

Modelo objetivo unificado

Reducir de 28 modelos a ~20 consolidando conceptos duplicados. Core: una Entidad (cliente/lead/proveedor) y un único Proyecto enlazado a Palanca + Finanzas.

Entidad = Contacto + Tercero (cliente/lead/proveedor/equipo) NIT · nombre · tipo · canales Proyecto = Proyecto + ProyectoFinanciero nombre · estado · valor → entidad (cliente) · palanca Palanca meta · estado · valor_estimado 1 palanca → N proyectos Oportunidad → entidad · palanca Compromiso → entidad · proyecto · palanca ResumenReunion M2M entidades (asistentes) Ingreso / Egreso → entidad · proyecto (FKs verdaderas, no texto) Evento (timeline unificado — futuro) tipo · entidad · proyecto · palanca · data JSON

Beneficios inmediatos

📊 Reportes antes imposibles

"Cuánto facturé a los clientes de palanca ISA en 12m", "clientes con 3+ reuniones y $0 facturado"

🎯 Plan de brecha preciso

Avance por palanca = suma real de proyectos contratados, no valor estimado cacheado

🔄 Automatizaciones

Palanca contratada → proyectos se crean. Cartera vencida → tareas de cobro auto

👁️ Vista 360 real

Timeline cronológico: mensajes, reuniones, oportunidades, proyectos, facturas, pagos

🧹 Menos duplicación

Un Contacto editado se refleja en reportes de finanzas sin scripts fuzzy

🚀 Base para integraciones

Drive (adjuntos), Email (parser leads), Calendly (auto-oportunidad) encajan cleanly

Flujos clave: antes / después

Flujo 1 — Cerrar una palanca

❌ Hoy

1
Palanca.estado = contratado
suma a cerrado del plan
No se crea Proyecto
Miguel tiene que crearlo manual
No se crea ProyectoFinanciero
Equipo no se notifica
Primer compromiso de kick-off: olvidado

✅ Objetivo

1
Palanca.estado = contratado
2
Nova pregunta: "¿Cuántos proyectos abro?" (una palanca → N proyectos)
3
Proyectos creados con FK a palanca + entidad cliente
4
Tercero linkeado o creado (sync Alegra)
5
Kick-off Compromiso auto + asignación equipo
6
Evento registrado en timeline de entidad

Flujo 2 — Cartera vencida

❌ Hoy

1
alerta_cobro detecta cartera vencida >30d
2
Te lista clientes morosos por WhatsApp
No se crean tareas de cobro automáticas
Match cliente↔Contacto no funciona si nombre difiere

✅ Objetivo

1
Ingreso.entidad (FK real) detecta vencidos por cliente
2
Auto-Compromiso "gestión de cobro" categoría=facturacion
3
Aparece en /pendientes/ del cliente en vista 360
4
Completar tarea → registra gestión en timeline Evento

Flujo 3 — Reunión transcrita

❌ Hoy

1
ResumenReunion creado
2
Compromisos con prefijo [Reunión: X]
attendees en JSON, no FK — vista 360 usa fuzzy match lento
Vinculación a Proyecto solo por backfill posterior

✅ Objetivo

1
ResumenReunion.entidades M2M
2
Al crear reunión: resolver emails → Entidad (FK automática)
3
Si nombre reunión matchea proyecto activo → FK directa
4
Compromisos heredan proyecto + entidades sin prefijo

Roadmap priorizado por valor / esfuerzo

Oro · ≤1 día

Quick wins estructurales

  1. FK Proyecto.palanca (1:N)
  2. FK Proyecto.entidad (reemplaza cliente texto)
  3. FK ResumenReunion.entidad principal
  4. Backfill de Proyecto.entidad usando Contactos existentes

No toca finanzas ni rompe integraciones. Habilita vista 360 real.

Plata · 2-3 días

Unificación de modelos

  1. Merge Contacto + TerceroEntidad
  2. Merge Proyecto + ProyectoFinanciero
  3. Hook "cerrar palanca → abrir proyectos"
  4. M2M ResumenReunion.entidades (vs JSON)

Migración graceful: mantener FKs legacy + nuevas en paralelo unos días.

Bronce · >5 días

Sistema integral

  1. Modelo Evento transversal
  2. Vista /expediente/<id>/ con timeline
  3. Motor de automatizaciones (when/then)
  4. Integración Drive para adjuntos
  5. Reporting cross-domain (SQL / vistas)

Transforma Nova en un CRM+ERP liviano orientado al CEO.

Limpieza housekeeping

Dado que el webhook del número principal no está activo, estos handlers son código muerto:

  • process_principal_message()
  • _handle_forwarded_lead(), _handle_new_contact()
  • Campo Mensaje.numero_origen='principal' → dead branch
  • AnalisisDiario.mensajes_* → campos sin escritura

Limpiarlos reduce superficie de mantenimiento sin afectar nada.

Recomendación

Arrancar por el bloque Oro

4 cambios de ~1 día total, sin romper integraciones. Deja el terreno listo para Plata+Bronce según apetito. Todo lo relacionado con "bot comercial recibiendo mensajes" queda fuera de scope porque el canal no está conectado.