# NOVASIS CRM 360 — Especificación Funcional, Técnica y de Diseño

> **Fuente**: `Novasis_CRM360_Analisis_Spec_v1.5.pdf` (v1.5 — Octubre 2026).
> Este markdown es la transcripción de ese PDF para que sea legible desde el repo y
> referenciable por los tickets de `plan-crm-360.md`. **El PDF sigue siendo la fuente
> de verdad funcional**; si difieren, gana el PDF.
>
> ⚠️ Varios nombres de servicios, tablas y columnas que la spec menciona **no coinciden
> con el código real**. Están verificados y corregidos en `src/crm/CLAUDE.md`
> (sección "Correcciones verificadas contra el código"). Leé esa sección antes de
> implementar cualquier ticket.

| Campo | Detalle |
|---|---|
| Para | Equipo de Desarrollo — Code100 SA / Blue Dragon SRL |
| Responsable | Marcelo Palumbo — Transformación Digital, Procesos e IA |
| Versión | v1.5 — Octubre 2026 |
| Estado | Borrador para revisión funcional y comercial |
| Módulos nuevos | M90 – M102 (CRM) |
| Depende de | Clientes, Presupuestos (M36–M43), Órdenes de Venta, Facturación SIFEN, Cobranzas/Créditos, Bancard, IA Dashboard, Suscripciones |

---

## Resumen Ejecutivo

NOVASIS ya resuelve muy bien lo que pasa **desde que existe una venta**: facturación SIFEN,
stock, cobranzas, tesorería y contabilidad. Lo que hoy no tiene es lo que pasa **antes**
(captar, seguir y ganar oportunidades) y **después** (atender al cliente y facturar servicios
en forma recurrente).

**Propuesta de valor:** el único CRM del mercado paraguayo que, al ganar una venta, genera
automáticamente la factura electrónica SIFEN (única, en cuotas o recurrente), la cobra por
Bancard y la asienta en contabilidad — sin conectores ni doble carga.

### Decisiones de partida (confirmadas)

| Tema | Decisión |
|---|---|
| Usuario del CRM | Las PyMEs clientes de NOVASIS. Blue Dragon puede usarlo como primer piloto |
| Canales | WhatsApp, Email, Instagram/Facebook Messenger y Portal/Web chat |
| Comercialización | Add-on con niveles: CRM Esencial (ventas) y CRM Pro (ventas + omnicanal + recurrente + IA) |
| Proveedor WhatsApp | Evolution API o Meta Cloud API (Twilio descartado para WhatsApp; solo SMS). Capa de abstracción con ambos — ver §6.6.1 |
| Facturas recurrentes | Siempre requieren aprobación antes de emitirse a SIFEN — ver §6.10 |
| Pilotos | DOBASA → CRM Pro · AGOGO → CRM Esencial — ver §13.4 |

### Esfuerzo estimado

~23 semanas con 2 desarrolladores, en 5 fases. La Fase 1 (MVP: pipeline + cierre → factura
única) está lista para vender en ~7 semanas. Hay prerrequisitos pendientes en el ERP (§13.2).

---

## 1. Alcance y Contexto del Módulo

### 1.1 Qué tiene hoy NOVASIS y qué falta

| Etapa | Hoy en NOVASIS | Brecha que cubre el CRM |
|---|---|---|
| Captar (marketing → lead) | No existe. Leads llegan por WhatsApp/Instagram y se manejan en el teléfono del vendedor | Captura multicanal, deduplicación, asignación automática, origen/campaña |
| Calificar y seguir | Clientes y Contactos (Pro/Enterprise). Sin etapas ni actividades | Pipeline kanban, actividades, recordatorios, secuencias, scoring |
| Cotizar | Presupuestos M36–M43 (portal, tracking de apertura, versiones, aprobación) | Presupuesto nace desde la oportunidad y actualiza su etapa automáticamente |
| Cerrar y facturar | Órdenes de Venta (facturar: **pendiente**), Pedidos mayoristas (`convertirAFactura`: **pendiente**), SIFEN (ok) | Asistente de cierre que genera los datos completos de facturación única, en cuotas o recurrente |
| Facturación recurrente | Solo existe para el propio SaaS NOVASIS (tabla `suscripciones`). Los clientes no pueden facturar abonos | Contratos recurrentes con emisión automática, cobro y dunning |
| Atender / posventa | No existe (reclamos por WhatsApp sin registro). Twilio solo para notificaciones/SMS | Bandeja omnicanal, tickets, SLA, base de conocimiento, CSAT |
| Cobrar | Cobranzas, mora, scoring crediticio, hoja de ruta cobrador | El CRM muestra saldo/mora y dispara cobranza conversacional por WhatsApp |
| Analizar | IA Dashboard (resumen, alertas, predicciones, chat) | Forecast, conversión por etapa/canal, MRR/churn, SLA, desempeño de vendedores |

### 1.2 Objetivos

1. Centralizar leads y conversaciones de todos los canales en una ficha 360 del cliente.
2. Gestionar oportunidades en un pipeline visual con valor, probabilidad, forecast y motivos de pérdida.
3. Convertir una oportunidad ganada en documentos del ERP **sin volver a cargar datos**.
4. Generar los datos de facturación: única (contado/crédito/cuotas) o recurrente.
5. Atender al cliente con tickets, SLA, base de conocimiento y portal de autoservicio.
6. Automatizar seguimientos y aplicar IA sobre datos reales.
7. Medir: pipeline, conversión, MRR, churn, tiempos de respuesta y satisfacción.

### 1.3 Fuera de alcance (v1)

- Email marketing masivo y landing pages (v2).
- Telefonía/call center con grabación (v2; se deja preparado el registro manual de llamadas).
- CPQ complejo con configuradores de producto.

> **Nomenclatura — evitar colisión.** NOVASIS ya usa `suscripciones` / `suscripcion_pagos` /
> `plan_modulos` para facturar su propio SaaS. Para los abonos que el cliente de NOVASIS
> factura a SUS clientes se usa **Contrato recurrente** y el prefijo `crm_`.

---

## 2. Benchmark de Mercado (resumen)

Se relevaron 10 CRM: Salesforce, HubSpot, Zoho, Pipedrive, Odoo, Kommo, Clientify, Zendesk,
Freshworks y Bitrix24. Qué se adopta de cada uno:

| CRM | Precio ref. 2026 (USD/usuario/mes) | Qué adoptamos |
|---|---|---|
| Salesforce | 25 / 100 / 175 / 350 | Modelo Lead→Cuenta→Oportunidad, forecast por categoría, ruteo omnicanal |
| HubSpot | 20 / 90 / 150; IA ~0,45 por resolución | Timeline unificado, secuencias, tickets+KB+CSAT, IA cobrada por uso |
| Zoho CRM | 14 / 23 / 40 / 52 | Etapas con campos obligatorios (tipo Blueprint), portal de cliente |
| Pipedrive | 14 / 39 / 49 / 79 | Kanban como vista principal, alertas de estancamiento, actividad siguiente obligatoria |
| Odoo CRM + Subscriptions | ~25–31 / ~49–61 | Quote-to-cash y motor de contratos recurrentes |
| Kommo | 25 / 35 / 45 | Bandeja conversacional integrada al pipeline; bots por etapa |
| Clientify | desde EUR 39 | Chatbots sin código, propuestas desde el CRM, foco PyME hispana |
| Zendesk | 55 / 115; IA ~1–2 por resolución | Políticas SLA, macros, help center |
| Freshworks | 19 / 55 / 79 | Portal de tickets, múltiples SLA por tipo de cliente |
| Bitrix24 | gratis o ~61/mes por empresa | Tareas colaborativas ligadas a la oportunidad |

### 2.2 Tendencias 2026 que impactan el diseño

- **WhatsApp es el canal comercial #1 en LATAM.**
- **WhatsApp API oficial cobra por mensaje desde julio 2025**, y **desde el 01/10/2026
  también cobra las respuestas dentro de la ventana de 24 h** y las plantillas de utilidad
  dentro de esa ventana. Siguen gratis los mensajes entrantes y la ventana de 72 h posterior
  a anuncios Click-to-WhatsApp. El CRM debe estimar y mostrar el costo por conversación.
- **IA cobrada por resultado** en la competencia. NOVASIS usa BYOK: puede ofrecer más barato.
- **Quote-to-cash integrado**: ventaja estructural, el CRM vive en la misma base que SIFEN.
- **Ingresos recurrentes en PyMEs de servicios** (mantenimiento, alquileres, colegios,
  gimnasios, software, seguridad, internet, clínicas): hoy lo resuelven con planillas.

---

## 3. Funcionalidades Priorizadas

Fase: 1 = MVP, 2–4 = siguientes. Nivel: E = Esencial, P = Pro.

| # | Funcionalidad | Fase | Nivel |
|---|---|---|---|
| 1 | Pipelines múltiples con etapas, probabilidad y kanban drag & drop | 1 | E |
| 2 | Leads con captura web, WhatsApp, Meta Lead Ads, Novasis Shop, TURNE e importación Excel | 1–4 | E |
| 3 | Deduplicación por RUC, teléfono y email + fusión | 1 | E |
| 4 | Asignación automática (round-robin, zona, rubro, monto) | 2 | P |
| 5 | Ficha 360: timeline unificado | 1 | E |
| 6 | Actividades: tareas, llamadas, visitas con geolocalización, agenda | 1 | E |
| 7 | Alerta de oportunidad estancada (deal rotting) | 1 | E |
| 8 | Campos obligatorios por etapa | 1 | E |
| 9 | Valor único + valor recurrente (MRR); forecast ponderado | 1 | E |
| 10 | Motivos de pérdida y competidor | 1 | E |
| 11 | Presupuesto desde la oportunidad (M36–M43) y sincronía de etapa | 1 | E |
| 12 | Asistente "Cerrar venta" → facturación única / cuotas / recurrente | 1 | E |
| 13 | Contratos recurrentes con emisión automática, renovación, prorrateo | 3 | P |
| 14 | Cobro recurrente: débito Bancard / link de pago por WhatsApp | 3 | P |
| 15 | Dunning: recordatorios, mora, suspensión y baja | 3 | P |
| 16 | Bandeja omnicanal | 2–4 | E (WhatsApp 1 número) / P (omnicanal) |
| 17 | Control de ventana 24 h, categoría de plantilla y costo estimado | 2 | P |
| 18 | Tickets con SLA, prioridades, categorías y escalamiento | 2 | P |
| 19 | Ticket vinculado a factura/producto → NC SIFEN en un clic | 2 | P |
| 20 | Base de conocimiento y respuestas guardadas | 4 | P |
| 21 | Portal del cliente: facturas/KuDE, pagar, tickets, contratos | 3 | P |
| 22 | Encuestas CSAT/NPS automáticas | 2 | P |
| 23 | Automatizaciones evento → condición → acción | 2 | E (básicas) / P |
| 24 | Secuencias de seguimiento con salida al responder | 4 | P |
| 25 | IA: lead scoring, resumen, respuesta sugerida, próximo paso | 4 | P |
| 26 | Agente IA WhatsApp con derivación a humano | 4 | P |
| 27 | Predicción de churn y riesgo de cobro | 4 | P |
| 28 | Comisiones sobre ventas ganadas **y cobradas** | 3 | E |
| 29 | Dashboards | 1–4 | E / P |
| 30 | App móvil/PWA del vendedor (offline) con check-in | 3 | E |
| 31 | Fechas especiales y recompra (cumpleaños, Día de la Madre, Navidad) | 2 | E |
| 32 | Venta por WhatsApp de punta a punta | 2 | E |

---

## 4. Integración con los Módulos de NOVASIS

**Principio rector:** el CRM **no duplica datos maestros**. Los referencia por FK. Todas las
tablas nuevas llevan `empresa_id`, auditoría vía AuditInterceptor y permisos vía
`@RequirePermission`.

| Módulo | El CRM consume | El CRM escribe / dispara | Punto de integración |
|---|---|---|---|
| Clientes / Contactos | Datos fiscales, lista de precios, condición de pago | Alta de cliente al convertir lead | `ClientesService.create/update`; FK `crm_*.cliente_id` |
| Productos, Presentaciones, Lista de Precios, Ofertas | Catálogo, IVA, precio por lista/cliente | Ítems de oportunidad y contrato (no crea productos) | `ListaPreciosService` (regla: nunca hardcodear precios) |
| Stock / Depósitos | Disponibilidad por depósito | Reserva al cerrar venta | Métodos de reserva de `PedidosService`; `movimientos_inventario` |
| Presupuestos (M36–M43) | Estado SENT/VIEWED/ACCEPTED/REJECTED, versiones | Crea presupuesto desde la oportunidad; recibe aceptación | `presupuestos.oportunidad_id` + evento `presupuesto.aceptado` |
| Órdenes de Venta / Pedidos | Estado de la orden | Crea orden al cerrar (si hay entrega/aprobación) | `PedidosService.crearOrden/confirmarOrden`; `pedidos.oportunidad_id` |
| Facturación SIFEN + NC | Estado del DE, KuDE | Factura única o recurrente; NC desde ticket | `FacturasService.createFactura` con payload de §7; cola de lotes SIFEN |
| Planes de cuotas / Créditos | Planes, tasa, límite y saldo, scoring | Factura a crédito en cuotas; solicitud si excede | `planes_cuotas`; `verificarCredito()` |
| Cobranzas / CxC / Mora | Saldo pendiente, días de mora, promesas | Tareas de cobranza, recordatorios | `cobros`, `config_mora`, `promesas_pago` |
| Tesorería / Bancard | Confirmación de pago (webhook) | Link de pago, débito automático | `pago_link`, `pago_bancard`, `IPaymentGateway` |
| Contabilidad | — | Asientos vía facturación/cobro (el CRM no asienta directo) | `ContabilidadIntegracionService` |
| Vendedores / Comisiones / RRHH | Vendedores, metas, estructura | Venta ganada y cobrada → base de comisión | `vendedores_cobradores`; `plan-integracion-comisiones-rrhh` |
| IA Dashboard | Proveedor IA, API key cifrada, métricas de tokens | Scoring, resúmenes, agente IA | Infraestructura de IA existente (ver corrección en CLAUDE.md) |
| Notificaciones | Credenciales por empresa, `empresas_correo` | Mensajes WhatsApp/SMS/email | `IWhatsAppProvider`; Twilio solo SMS; nodemailer |
| Novasis Shop | Carritos abandonados, pedidos web | Leads y tareas de recuperación | Webhooks del Shop → `crm_leads` |
| TURNE APP | Turnos agendados / no-shows | Leads, actividades y tickets | Endpoint externo TURNE existente |
| Suscripciones SaaS | Módulos habilitados | Gating de menús, endpoints y límites | Guard de módulo existente + navegación |

---

## 5. Flujo Maestro Lead → Cash y Máquinas de Estado

### 5.1 Flujo de punta a punta

```
 CANALES              CRM                          ERP NOVASIS
 WhatsApp ─┐
 IG / FB  ─┤
 Email    ─┼──► [Lead] ─calificar─► [Oportunidad]
 Web/Shop ─┤   (dedupe, asignación)   │ pipeline / actividades
 TURNE    ─┘                          ▼
                              [Presupuesto M36] ──► portal / tracking
                                      │ ACEPTADO
                                      ▼
                   ┌── ASISTENTE "CERRAR VENTA" (M98) ──┐
                   │ valida cliente fiscal, crédito,    │
                   │ stock, define tipo de facturación  │
                   └──────┬──────────────┬──────────────┘
                   ÚNICA  │              │  RECURRENTE
                          ▼              ▼
          [Orden de Venta]* / [Factura]   [Contrato crm_contratos]
          contado | crédito | cuotas      ciclo mensual/anual/consumo
                          │              │ job diario
                          ▼              ▼
                  SIFEN (DE aprobado) ◄── factura por ciclo
                          │
          KuDE por email/WhatsApp + link Bancard / débito automático
                          ▼
          Cobranzas ─► Tesorería ─► Contabilidad (asientos)
                          │
          Posventa: Tickets / SLA / CSAT / renovación / upsell

 * Orden de venta solo si hay entrega, aprobación o anticipo.
```

### 5.2 Estados del Lead

| Estado | Significado | Transición |
|---|---|---|
| NUEVO | Ingresó por un canal, sin contacto | → CONTACTADO |
| CONTACTADO | Hubo interacción | → CALIFICADO / DESCARTADO |
| CALIFICADO | Tiene necesidad, presupuesto y decisor | → CONVERTIDO (crea cliente + oportunidad) |
| CONVERTIDO | Pasó a oportunidad | Final |
| DESCARTADO | Sin interés / spam / duplicado (motivo obligatorio) | Final (reabrible) |

### 5.3 Etapas de Oportunidad (pipeline por defecto, configurable)

| Etapa | Prob. % | Campos obligatorios para avanzar | Automatismo sugerido |
|---|---|---|---|
| Calificación | 10 | Cliente/lead, origen, vendedor | Tarea "primer contacto" a 1 h |
| Necesidad / Demo | 30 | Productos de interés, valor estimado | Recordatorio si 3 días sin actividad |
| Propuesta enviada | 50 | Presupuesto vinculado (estado SENT) | Pasa sola al enviar presupuesto |
| Negociación | 70 | Condición de pago, fecha estimada de cierre | Alerta si el presupuesto vence en 48 h |
| Ganada | 100 | Asistente de cierre completado | Genera factura/contrato; CSAT de venta |
| Perdida | 0 | Motivo de pérdida (+ competidor) | Secuencia de reactivación a 90 días |

### 5.4 Estados del Ticket

`NUEVO → ABIERTO → EN_ESPERA_CLIENTE / EN_ESPERA_INTERNO → RESUELTO → CERRADO`
(REABIERTO si el cliente responde dentro de 7 días). El reloj de SLA se pausa en
`EN_ESPERA_CLIENTE`.

### 5.5 Estados del Contrato recurrente

| Estado | Significado |
|---|---|
| BORRADOR | Creado desde el cierre de venta; editable |
| ACTIVO | Factura por ciclo automáticamente |
| EN_MORA | Facturas vencidas más allá de la gracia; sigue facturando, se notifica |
| SUSPENDIDO | Superó el umbral de mora: no se emiten nuevos ciclos; servicio suspendido |
| POR_RENOVAR | A N días del fin de vigencia; tarea al vendedor y aviso al cliente |
| FINALIZADO / CANCELADO | Fin de vigencia o baja (motivo de churn obligatorio). Puede generar NC por prorrateo |

---

## 6. Especificación de Módulos Funcionales — M90 a M102

### 6.1 M90 — Parámetros del CRM

| Parámetro | Descripción | Default |
|---|---|---|
| Pipelines y etapas | N pipelines por empresa. Etapa: nombre, orden, probabilidad, campos obligatorios, días para "estancada" | 1 pipeline, 6 etapas (§5.3) |
| Motivos de pérdida / descarte / churn | Catálogos editables | Precio, competencia, sin respuesta, sin presupuesto… |
| Orígenes y campañas | WhatsApp, IG, FB, web, Shop, TURNE, referido, visita, feria, Meta Ads (con UTM) | Lista base |
| Reglas de asignación | Round-robin, por zona/sucursal, rubro, monto, idioma; horario laboral | Round-robin por sucursal |
| Horario de atención y feriados | Usado para SLA y mensajes fuera de horario | L–V 08–18, Sáb 08–12 |
| Políticas SLA | Primera respuesta y resolución por prioridad y tipo de cliente | Alta 1 h / 8 h; Media 4 h / 24 h; Baja 8 h / 72 h |
| Canales | Proveedor WhatsApp y credenciales, IMAP/SMTP, Meta Page/IG, widget web | — |
| Facturación recurrente | Día de emisión, días de anticipación del borrador, aprobador, días de gracia, política de suspensión, envío automático de KuDE. **La aprobación previa es obligatoria (no desactivable)** | Día 1, borrador 3 días antes, gracia 10 días |

### 6.2 M91 — Leads y Captura Multicanal

- **Fuentes**: formulario web embebible (JS snippet), Meta Lead Ads (webhook), mensaje
  entrante de WhatsApp/IG/FB/web chat de un número desconocido, carrito abandonado del Shop,
  cliente nuevo de TURNE, importación Excel/CSV con mapeo de columnas, alta manual.
- **Deduplicación al ingresar**: coincidencia exacta de RUC; normalización de teléfono a
  E.164 (+595…); email en minúsculas. **Si coincide con un cliente existente, la conversación
  se asocia al cliente y no se crea lead.**
- **Asignación** automática según reglas M90; notificación push/WebSocket al vendedor; SLA de
  primer contacto.
- **Conversión**: crea (o vincula) cliente en Clientes con datos fiscales y abre oportunidad
  en el pipeline elegido, manteniendo origen y campaña para medir ROI.

### 6.3 M92 — Cuentas y Contactos 360

Extiende la ficha de cliente existente con una **pestaña CRM** (no una entidad paralela).
Timeline unificado ordenado por fecha:

| Bloque | Fuente | Visible para |
|---|---|---|
| Conversaciones (WA, email, IG/FB, chat) | `crm_mensajes` | Vendedor asignado, atención, supervisor |
| Actividades y notas | `crm_actividades` | Todos con `CRM_VER` |
| Oportunidades y presupuestos | `crm_oportunidades`, presupuestos | Ventas |
| Facturas, NC y KuDE | `factura_cab`, nota de crédito | Ventas, atención |
| Saldo, mora, límite de crédito, scoring | Cobranzas / Créditos | Ventas (solo lectura); oculto según permiso |
| Contratos recurrentes y MRR | `crm_contratos` | Ventas, atención |
| Tickets y CSAT | `crm_tickets` | Atención, ventas |

**Indicadores de cabecera**: LTV, facturación últimos 12 meses, MRR activo, saldo vencido,
último contacto, NPS, etiquetas y segmento.

### 6.4 M93 — Oportunidades y Pipeline

- **Vistas**: kanban por etapa (drag & drop con validación de campos obligatorios), lista con
  filtros guardados, calendario por fecha de cierre, mapa.
- **Ítems**: productos del catálogo con precio de la lista del cliente, presentaciones y
  ofertas vigentes; cada ítem se marca **ÚNICO** o **RECURRENTE** (con frecuencia).
  Totales: valor único, MRR, valor total contrato (TCV).
- **Moneda**: PYG o USD; cotización informativa del día. **Se congela recién al facturar.**
- **Forecast**: ponderado (valor × probabilidad) y por categoría (Pipeline / Mejor caso /
  Comprometido) por vendedor, mes y pipeline.
- **Estancamiento**: si supera los días configurados sin actividad, la tarjeta se marca en
  rojo y se notifica.
- **Ganar**: abre obligatoriamente el asistente M98. **Perder**: exige motivo.

### 6.5 M94 — Actividades, Agenda y Visitas

- Tipos: tarea, llamada, reunión, visita, WhatsApp, email, demo. **Resultado obligatorio al
  completar.**
- Regla "siempre una próxima actividad": al completar una actividad en una oportunidad
  abierta se sugiere agendar la siguiente.
- Visitas con check-in/out geolocalizado (reutiliza la lógica de hoja de ruta del cobrador);
  funciona offline en la PWA.
- Sincronización con Google Calendar / Outlook (Fase 4).

### 6.6 M95 — Bandeja Omnicanal

| Canal | Tecnología | Notas |
|---|---|---|
| WhatsApp | Adaptador `IWhatsAppProvider` con dos conectores: Meta Cloud API directa o Evolution API — ver §6.6.1 | Con API oficial: plantillas aprobadas, ventana de 24 h y costo por mensaje (incluidas respuestas en ventana desde 01/10/2026) |
| Email | IMAP (entrada) + SMTP/nodemailer (salida) por buzón compartido; `empresas_correo` | Hilos por Message-ID; firma por usuario |
| Instagram / Facebook Messenger | Meta Graph API (webhooks de Page e IG profesional) | Comentarios → lead (Fase 4) |
| Web chat | Widget JS propio (WebSocket, reutiliza infraestructura PosGateway) | Embebible en web del cliente y Novasis Shop |

**Funciones**: colas por equipo, asignación manual/automática, estados (abierta, pendiente,
cerrada), notas internas y menciones, respuestas rápidas con variables (`{nombre}`, `{saldo}`,
`{link_pago}`), adjuntos, enviar presupuesto/KuDE/link de pago desde la conversación,
convertir conversación en lead/oportunidad/ticket, indicador de cliente con deuda vencida.

#### 6.6.1 Proveedor de WhatsApp (decisión v1.1)

Se descarta Twilio para WhatsApp. El CRM define `IWhatsAppProvider` (`enviarTexto`,
`enviarPlantilla`, `enviarAdjunto`, `recibirWebhook`, `estadoEntrega`, `estadoSesion`) con
implementaciones intercambiables por empresa desde M90:

| Conector | Cómo funciona | Costo | Riesgo | Uso recomendado |
|---|---|---|---|---|
| **Meta Cloud API** (directa) | API oficial. Número verificado, plantillas aprobadas, webhooks firmados | Por mensaje según categoría y país | Requiere verificación de la empresa y aprobación de plantillas; sin riesgo de bloqueo | **Producción**: facturas recurrentes, KuDE, dunning, campañas, agente IA |
| Evolution API — modo Cloud | Evolution self-hosted como gateway hacia la API oficial | Igual que Meta + servidor | Una pieza más que operar | Gateway único multi-cliente |
| Evolution API — modo Baileys | Vincula el número por QR, protocolo **no oficial** | Sin costo por mensaje | **Viola los términos de Meta; riesgo alto de bloqueo permanente del número**; sin plantillas; puede romperse | Solo demos y pruebas. **Nunca para envíos masivos ni facturación** |

> **Recomendación**: desarrollar el adaptador con ambos conectores desde F2, con Meta Cloud
> API como default de producción. Cambiar de conector es configuración, no código.
>
> **Regla de negocio**: los envíos **automáticos** (KuDE recurrente, dunning, campañas,
> agente IA) se **bloquean** si la empresa usa el modo Baileys, para proteger su número.

### 6.7 M96 — Atención: Tickets, SLA y Base de Conocimiento

- **Origen**: cualquier conversación, portal del cliente, email a soporte@, formulario web o manual.
- **Campos**: cliente, contacto, categoría (consulta, reclamo, garantía, devolución, técnico,
  facturación), prioridad, producto, **factura vinculada**, contrato vinculado, responsable, equipo.
- **SLA**: reloj de primera respuesta y resolución según política M90 y contrato; alertas al
  75% y al vencer; escalamiento a supervisor.
- **Acciones ERP desde el ticket**: emitir NC SIFEN (con reingreso de stock vía flujo NC
  existente), reemitir KuDE, generar link de pago, crear orden de servicio/reposición.
- **CSAT** automático al resolver (1–5 + comentario); NPS trimestral opcional.
- **Base de conocimiento**: artículos internos y públicos, categorías, búsqueda; fuente del agente IA.

### 6.8 M97 — Portal del Cliente

Extiende el portal público de presupuestos (token) a un portal con acceso por **OTP vía
WhatsApp o email** (sin contraseña). Secciones: Mis facturas (KuDE PDF/XML), Estado de cuenta
y pago con Bancard, Mis contratos (plan, próximo cobro, cambiar medio de pago, solicitar baja),
Mis tickets, Presupuestos pendientes (aceptar/rechazar), Base de conocimiento.

### 6.9 M98 — Asistente "Cerrar Venta" y Generación de Datos de Facturación

Es el corazón del módulo. Se abre al mover a **Ganada** o al aceptar el presupuesto en el portal.

**Pasos del asistente**

1. **Validar cliente fiscal**: RUC + DV (o CI / sin documento para consumidor final), razón
   social, naturaleza del receptor, tipo de operación (B2B, B2C, B2G, B2F), dirección y email
   para KuDE. Si el cliente es nuevo se completa aquí.
2. **Confirmar ítems y precios**: se recalculan desde la lista de precios vigente del cliente,
   con IVA 10/5/exento por producto y descuentos autorizados.
3. **Elegir tipo de facturación**: ÚNICA, RECURRENTE o MIXTA (ej. instalación única + abono mensual).
4. **Condición comercial**: contado / crédito a plazo / crédito en cuotas (`planes_cuotas`).
   Si es crédito: verificación de límite, saldo y mora; si excede, se ofrece solicitud de
   crédito u **override con PIN de supervisor**.
5. **Logística**: depósito de salida y reserva de stock; si requiere entrega, aprobación o
   anticipo se crea Orden de Venta; si no, factura directa.
6. **Recurrencia** (si aplica): frecuencia, fecha de inicio, día de emisión, vigencia,
   renovación automática, ajuste de precio, prorrateo del primer período y medio de cobro.
7. **Resumen y confirmación**: vista previa de la factura (o de las primeras 3 facturas del
   contrato) con totales por tasa de IVA.
8. **Generación**: crea en una transacción la Orden de Venta o la Factura (vía
   `FacturasService` → cola SIFEN), y/o el Contrato ACTIVO; vincula todo a la oportunidad;
   dispara envío de KuDE + link de pago; registra comisión pendiente.

> **Regla de oro**: el CRM **nunca** arma el XML SIFEN ni toca stock o asientos directamente.
> Produce un **payload de facturación** validado y lo entrega a los servicios existentes
> (`FacturasService`, `PedidosService`, `movimientos_inventario`,
> `ContabilidadIntegracionService`).

### 6.10 M99 — Contratos y Facturación Recurrente

**Modelo de recurrencia soportado**

| Concepto | Opciones |
|---|---|
| Frecuencia | Semanal, quincenal, mensual, bimestral, trimestral, semestral, anual; o cada N meses |
| Momento de facturación | Anticipado (inicio del período) o vencido (al final, típico de consumo) |
| Día de emisión | Fijo del mes (1–28) o aniversario de la fecha de inicio |
| Tipo de línea | Fija (abono), Variable por consumo, Única (cargo de alta), Descuento temporal (N ciclos) |
| Vigencia | Indefinida o con fecha fin; renovación automática por igual período |
| Ajuste de precio | Manual, % fijo anual, o índice (IPC) en aniversario, con aviso previo |
| Moneda | PYG o USD; en USD se factura con la cotización **del día de emisión** |
| Cambios | Upgrade/downgrade a mitad de ciclo con prorrateo (factura complementaria o NC) |
| Agrupación | Una factura por contrato o consolidada por cliente |

**Ciclo de facturación automático (job diario 05:00)**

1. Selecciona contratos ACTIVO/EN_MORA con `proxima_emision ≤ hoy + días de anticipación` (default 3).
2. Calcula líneas del período: fijas + consumo registrado + descuentos vigentes + prorrateos.
3. Crea el ciclo en **PENDIENTE_APROBACION** con la factura en BORRADOR (sin número ni envío
   a SIFEN) y notifica al Supervisor. **Nunca emite sin aprobación.**
4. Registra el ciclo en `crm_contrato_ciclos` (**idempotente por contrato + período**).
5. **Al aprobar**: emite vía `FacturasService` (timbrado y numeración de la sucursal del
   contrato), encola a SIFEN con los reintentos existentes y envía KuDE + link de pago.
6. Si hay débito automático: intenta cobro Bancard; si rechaza, reintenta según política
   (ej. +3 y +7 días).
7. Avanza `proxima_emision` y actualiza métricas MRR.

**Flujo de aprobación (obligatorio)**

```
 job diario (N días antes) ──► PENDIENTE_APROBACION
   ├─ editar líneas / consumo / precio (auditado)
   ├─ omitir período (motivo) ──► OMITIDO
   └─ aprobar ──► APROBADO ──► EMITIDO (SIFEN) ──► COBRADO
                                   └─ rechazo SIFEN ──► RECHAZADO_SIFEN
```

| Aspecto | Definición |
|---|---|
| Pantalla | "Facturas recurrentes por aprobar": lista por fecha, cliente, contrato, monto y **diferencias vs ciclo anterior resaltadas** |
| Acciones | Aprobar individual o en lote, editar líneas antes de aprobar, omitir el período con motivo, posponer |
| Quién aprueba | El **Supervisor** (`CRM_CONTRATOS_APROBAR`). Una sola aprobación; fallback Administrador |
| Fecha de emisión | **La factura se emite con la fecha de aprobación** (SIFEN no admite fecha futura) |
| Cobro automático | El débito Bancard se dispara **solo después** de que el DE quede aprobado por SIFEN |
| Sin aprobar a tiempo | Recordatorio el día de emisión y escalamiento a supervisor a las 48 h; el ciclo no se pierde ni se duplica |
| Dunning | Corre sobre facturas **emitidas**; un ciclo pendiente de aprobación **no genera mora** |
| Auditoría | `aprobado_por`, `aprobado_at`, cambios previos (old/new) vía AuditInterceptor |

**Dunning**

| Día vs vencimiento | Acción por defecto (configurable) |
|---|---|
| −3 | Recordatorio por WhatsApp (plantilla de utilidad) con link de pago |
| 0 | Aviso de vencimiento |
| +3 | Reintento de débito / segundo aviso; tarea al cobrador |
| +10 (gracia) | Contrato pasa a EN_MORA; se aplica interés de `config_mora` |
| +30 | SUSPENDIDO: no se emiten nuevos ciclos; ticket a atención |
| +60 | Propuesta de baja / cobranza judicial; motivo de churn |

**Métricas**: MRR y ARR (por moneda y en PYG), MRR nuevo / expansión / contracción / churn,
tasa de churn de clientes y de ingresos, LTV, cohortes por mes de alta, facturación proyectada
próximos 12 meses.

### 6.11 M100 — Automatizaciones y Playbooks

| Disparador | Condición (ejemplos) | Acción (ejemplos) |
|---|---|---|
| Lead creado | origen = Meta Ads; fuera de horario | Enviar WhatsApp de bienvenida; asignar; tarea 1 h |
| Etapa cambiada | a "Propuesta enviada" | Recordatorio a 3 días si presupuesto no visto |
| Presupuesto visto / aceptado | — | Notificar vendedor; mover etapa; abrir asistente de cierre |
| Oportunidad estancada | días sin actividad > N | Notificar vendedor y supervisor |
| Factura vencida | cliente con contrato | Secuencia de dunning |
| Ticket SLA en riesgo | 75% del tiempo consumido | Escalar; cambiar prioridad |
| Contrato por renovar | 30 días antes | Crear oportunidad de renovación/upsell |
| CSAT bajo | puntaje ≤ 2 | Crear ticket a supervisor |

Motor: eventos de dominio → cola Redis (BullMQ) → ejecutor de reglas. Límite de reglas activas
según nivel (Esencial 10, Pro ilimitadas). Cada ejecución queda en `crm_automatizacion_log`.

### 6.12 M101 — IA Comercial y de Atención

**Decisión v1.5**: la IA del CRM usa **siempre la API key del propio cliente (BYOK)**; el
consumo de tokens lo paga el cliente a su proveedor y NOVASIS no revende IA.

| Capacidad | Cómo funciona | Salvaguarda |
|---|---|---|
| Lead / deal scoring | Reglas + IA sobre origen, interacción, fit e historial | Sugerencia, no bloquea |
| Resumen de conversación / ticket | Resumen y próximos pasos al abrir la ficha | Solo datos de la empresa (`empresa_id`) |
| Respuesta sugerida (copiloto) | Borrador usando KB, precios y stock | **El humano envía** |
| Agente IA WhatsApp / web chat | FAQ, precio de lista, stock por sucursal, estado de pedido, saldo, link de pago; deriva a humano | **Herramientas de solo lectura**; nunca descuentos |
| Predicción de churn y riesgo | Uso, tickets, CSAT, mora y scoring crediticio | Alerta + tarea de retención |
| Análisis conversacional | Preguntas al chat IA existente sobre datos CRM | Mismo motor del IA Dashboard |

### 6.13 M102 — Reportes y Dashboards

- **Ventas**: pipeline por etapa, valor ponderado, conversión por etapa y canal/origen, ciclo
  de venta promedio, motivos de pérdida, ranking de vendedores, forecast vs meta.
- **Actividad**: actividades por vendedor/tipo, visitas en mapa, tiempo de primera respuesta.
- **Atención**: tickets por estado/categoría, cumplimiento de SLA, tiempos, CSAT/NPS, volumen por canal.
- **Recurrente**: MRR, churn, cohortes, facturación proyectada, contratos en mora.
- **Marketing**: leads y ventas por campaña/origen (ROI de Meta Ads).
- Exportación Excel/PDF y widgets en el Dashboard principal y en el IA Dashboard.

---

## 7. Datos Generados para la Facturación

> **Validación pendiente**: los nombres de campo SIFEN son **referenciales** y deben validarse
> contra la versión vigente del Manual Técnico SIFEN (DNIT) que ya usa el servicio de
> facturación de NOVASIS antes de implementar.

### 7.1 Mapeo de datos

| Grupo | Dato | Origen en NOVASIS / CRM | Campo SIFEN (ref.) |
|---|---|---|---|
| Documento | Tipo de DE = Factura electrónica | Fijo | `iTiDE = 1` |
| Documento | Timbrado, establecimiento, punto de expedición, número | Numeración de la sucursal | `gTimb` |
| Operación | Tipo de transacción (mercadería / servicios / mixto) | Derivado de los ítems | `iTipTra` |
| Operación | Moneda y tipo de cambio | Oportunidad + cotización al emitir | `cMoneOpe`, `dTiCam` |
| Receptor | Naturaleza del receptor | Cliente | `iNatRec` |
| Receptor | Tipo de operación B2B / B2C / B2G / B2F | Cliente | `iTiOpe` |
| Receptor | RUC, DV, razón social / documento de identidad | Cliente validado en paso 1 | `dRucRec`, `dDVRec`, `dNomRec` / `iTipIDRec`, `dNumIDRec` |
| Receptor | Email para KuDE, dirección | Contacto principal / cliente | `dEmailRec`, `dDirRec` |
| Condición | Contado o crédito | Paso 4 | `iCondOpe` (1 contado, 2 crédito) |
| Condición | Crédito a plazo o en cuotas; plazo; nº de cuotas; vencimientos | `planes_cuotas` / condiciones de pago | `iCondCred`, `dPlazoCre`, `dCuotas`, `gCuotas` |
| Condición | Forma de pago (contado) | Medio elegido | `gPaConEIni` / `iTiPago` |
| Ítems | Código, descripción, cantidad, unidad, precio unitario, descuento | Ítems recalculados con la lista de precios | `dCodInt`, `dDesProSer`, `dCantProSer`, `cUniMed`, `dPUniProSer`, `dDescItem` |
| Ítems | Afectación y tasa de IVA | Producto (motor IVA Ley 125/91) | `iAfecIVA`, `dTasaIVA` (10 / 5 / exento) |
| Info adicional | Período facturado, nº de contrato, referencia de oportunidad | Contrato / ciclo | `dInfAdic` |
| Trazabilidad interna | `oportunidad_id`, `presupuesto_id`, `pedido_id`, `contrato_id`, `ciclo_id`, `vendedor_id` | CRM | Columnas nuevas en `factura_cab` (**no van a SIFEN**) |

### 7.2 Ejemplo A — Venta única a crédito en cuotas

```
Oportunidad OPP-000124 · Cliente: Ferretería Central SA (RUC 80012345-6) · Ganada
Ítems: 10 x Taladro X200 (IVA 10%) + 1 x Instalación (servicio, IVA 10%)
Condición: Crédito 3 cuotas ("3 cuotas sin interés"), depósito Central
→ Orden de Venta OV-0000312 (aprobada, stock reservado)
→ Factura 001-001-0004521 · iTipTra=3 (mixto) · iCondOpe=2 · iCondCred=2 · dCuotas=3
→ gCuotas: 3 vencimientos a 30/60/90 días → Cuentas por cobrar
→ KuDE por email + WhatsApp · comisión pendiente al vendedor
```

### 7.3 Ejemplo B — Venta mixta: alta única + abono mensual

```
Oportunidad OPP-000131 · Colegio San José · Servicio de monitoreo de alarmas
Ítems ÚNICOS:      Kit de instalación Gs. 2.500.000 (IVA 10%)
Ítems RECURRENTES: Monitoreo mensual Gs. 350.000 (IVA 10%) · día 5 · 12 meses · renovación auto.
→ Factura única 001-002-0000890 (contado, link Bancard)
→ Contrato CTR-000045 ACTIVO · primer ciclo prorrateado (inicio 18/10: 14 días)
→ Débito automático Bancard registrado · borrador del ciclo 02/11 → aprobación → emisión y débito
→ MRR +350.000 · TCV 6.700.000
```

---

## 8. Modelo de Base de Datos — PostgreSQL

Convenciones: prefijo `crm_`, PK UUID (`gen_random_uuid()`), `empresa_id UUID NOT NULL` en
todas las tablas operativas, `created_at` / `updated_at` / `created_by`, migraciones
idempotentes (`IF NOT EXISTS`), índices por `(empresa_id, estado)`.

### 8.1 Tablas principales

**`crm_oportunidades`**

| Columna | Tipo | Descripción |
|---|---|---|
| `id` / `empresa_id` / `sucursal_id` | UUID | Multi-empresa y sucursal |
| `numero` | VARCHAR(20) | `OPP-0000001` (secuencial por empresa) |
| `titulo` | VARCHAR(200) | Nombre de la oportunidad |
| `cliente_id` / `lead_id` / `contacto_id` | UUID FK | Cliente existente o lead aún no convertido |
| `pipeline_id` / `etapa_id` | UUID FK | `crm_pipelines` / `crm_etapas` |
| `vendedor_id` | UUID FK | `vendedores_cobradores` |
| `estado` | ENUM | `abierta \| ganada \| perdida` |
| `moneda_id` | UUID FK | PYG / USD |
| `valor_unico` / `valor_mrr` / `valor_tcv` | NUMERIC(19,4) | Totales calculados desde ítems |
| `probabilidad` | SMALLINT | Hereda de la etapa, editable |
| `fecha_cierre_estimada` / `fecha_cierre_real` | DATE | Forecast |
| `origen_id` / `campana` | UUID / VARCHAR | Atribución de marketing |
| `motivo_perdida_id` / `competidor` | UUID / VARCHAR | Obligatorio si perdida |
| `ultima_actividad_at` / `proxima_actividad_at` | TIMESTAMPTZ | Estancamiento y disciplina |
| `score_ia` / `score_explicacion` | SMALLINT / TEXT | M101 |
| `presupuesto_id` / `pedido_id` / `contrato_id` | UUID FK | Trazabilidad del cierre |

**`crm_oportunidad_items`**: `oportunidad_id`, `producto_id`, `presentacion_id`, `descripcion`,
`cantidad`, `precio_unitario`, `descuento_pct`, `iva_tasa`, **`tipo_cobro`** (`unico \| recurrente`),
**`frecuencia`** (`mensual, trimestral, anual, cada_n_meses`), **`n_meses`**, `subtotal`, `orden`.

**`crm_contratos`**

| Columna | Tipo | Descripción |
|---|---|---|
| `id` / `empresa_id` / `sucursal_id` | UUID | La sucursal define timbrado y numeración |
| `numero` | VARCHAR(20) | `CTR-0000001` |
| `cliente_id` / `contacto_facturacion_id` | UUID FK | Receptor y destinatario del KuDE |
| `oportunidad_id` / `vendedor_id` | UUID FK | Origen y comisión |
| `estado` | ENUM | `borrador \| activo \| en_mora \| suspendido \| por_renovar \| finalizado \| cancelado` |
| `frecuencia` / `n_meses` / `modo_facturacion` | ENUM / SMALLINT / ENUM | `anticipado \| vencido` |
| `dia_emision` / `proxima_emision` | SMALLINT / DATE | Motor de ciclos |
| `fecha_inicio` / `fecha_fin` / `renovacion_automatica` | DATE / DATE / BOOL | Vigencia |
| `moneda_id` | UUID FK | Cotización al emitir |
| `condicion_pago_id` | UUID FK | Contado / crédito a N días |
| `medio_cobro` / `token_cobro_id` | ENUM / UUID FK | `debito_auto \| link_pago \| manual` |
| `ajuste_tipo` / `ajuste_valor` / `ajuste_fecha` | ENUM / NUMERIC / DATE | `ninguno \| pct_anual \| indice` |
| `agrupar_factura` | BOOL | Consolidar por cliente |
| `aprobador_id` / `umbral_doble_aprobacion` | UUID FK / NUMERIC | La aprobación es siempre obligatoria |
| `mrr_actual` | NUMERIC(19,4) | Desnormalizado para reportes |
| `motivo_baja_id` / `fecha_baja` | UUID / DATE | Churn |

- **`crm_contrato_lineas`**: `contrato_id`, `producto_id`, `descripcion`, `tipo_linea`
  (`fija \| consumo \| unica \| descuento`), `cantidad`, `precio_unitario`, `iva_tasa`,
  `ciclos_restantes`, `fecha_desde`, `fecha_hasta`.
- **`crm_contrato_consumos`**: `contrato_linea_id`, `periodo`, `cantidad`, `origen`
  (`manual \| importacion \| api`).
- **`crm_contrato_ciclos`**: `contrato_id`, `periodo_desde`, `periodo_hasta`, `factura_id`,
  `monto`, `estado` (`pendiente_aprobacion \| aprobado \| omitido \| emitido \| rechazado_sifen \| cobrado \| cobro_fallido`),
  `aprobado_por`, `aprobado_at`, `motivo_omision`, `intentos_cobro`, `error`.
  **`UNIQUE (contrato_id, periodo_desde)`** para garantizar idempotencia.

### 8.2 Resto de tablas

| Tabla | Propósito / columnas clave |
|---|---|
| `crm_pipelines`, `crm_etapas` | Configuración de embudos; etapa: `orden`, `probabilidad`, `campos_obligatorios` JSONB, `dias_estancamiento` |
| `crm_origenes`, `crm_motivos` | Catálogos (`tipo`: `perdida \| descarte \| churn`) |
| `crm_leads` | `nombre`, `empresa_nombre`, `ruc`, `telefono_e164`, `email`, `origen_id`, `campana`, `utm` JSONB, `estado`, `asignado_a`, `cliente_id`, `datos_extra` JSONB |
| `crm_actividades` | `tipo`, `asunto`, `fecha_programada`, `fecha_realizada`, `resultado`, `oportunidad_id` / `cliente_id` / `ticket_id`, `usuario_id`, `geo_lat`, `geo_lng` |
| `crm_canales` | `tipo` (`whatsapp \| email \| instagram \| facebook \| webchat`), `proveedor` (`meta_cloud \| evolution_cloud \| evolution_baileys`), credenciales cifradas (AES), número/cuenta, equipo por defecto |
| `crm_conversaciones` | `canal_id`, `cliente_id` / `lead_id`, `asignado_a`, `equipo_id`, `estado`, `ventana_24h_hasta`, `ultimo_mensaje_at`, `no_leidos` |
| `crm_mensajes` | `conversacion_id`, `direccion` (`in \| out`), `autor`, `tipo` (`texto \| plantilla \| adjunto \| nota_interna`), `contenido`, `plantilla_id`, `categoria_plantilla`, `id_externo`, `estado_entrega` |
| `crm_plantillas` | `canal`, `nombre`, categoría Meta, `idioma`, cuerpo con variables, estado de aprobación |
| `crm_tickets` | `numero` `TCK-`, `cliente_id`, `contacto_id`, `categoria_id`, `prioridad`, `estado`, `factura_id`, `producto_id`, `contrato_id`, `sla_politica_id`, `vence_primera_resp`, `vence_resolucion`, `csat` |
| `crm_sla_politicas` | `prioridad`, `tipo_cliente` / contrato, `min_primera_respuesta`, `min_resolucion`, `calendario_id` |
| `crm_kb_articulos` | `titulo`, `cuerpo`, `categoria`, `publico` (bool), `embedding` (pgvector, Fase 4) |
| `crm_tokens_cobro` | `cliente_id`, `pasarela` (bancard), alias / token cifrado, últimos 4 dígitos, vencimiento, estado |
| `crm_automatizaciones`, `crm_automatizacion_log` | `evento`, `condiciones` JSONB, `acciones` JSONB, `activa`; log de ejecución |
| `crm_encuestas` | `tipo` (`csat \| nps`), referencia (ticket \| oportunidad), `puntaje`, `comentario` |

### 8.3 Cambios a tablas existentes

> ⚠️ **El SQL original de la spec usa dos nombres de tabla que no existen.** Ver la corrección
> verificada en `src/crm/CLAUDE.md`. Los nombres reales son `presupuesto_cab` y `nota_credito_cab`.

```sql
ALTER TABLE factura_cab      ADD COLUMN IF NOT EXISTS oportunidad_id UUID,
                             ADD COLUMN IF NOT EXISTS contrato_id UUID,
                             ADD COLUMN IF NOT EXISTS contrato_ciclo_id UUID;
ALTER TABLE presupuesto_cab  ADD COLUMN IF NOT EXISTS oportunidad_id UUID;   -- spec decía "presupuestos"
ALTER TABLE pedidos          ADD COLUMN IF NOT EXISTS oportunidad_id UUID;
ALTER TABLE clientes         ADD COLUMN IF NOT EXISTS lead_origen_id UUID,
                             ADD COLUMN IF NOT EXISTS telefono_e164 VARCHAR(20),
                             ADD COLUMN IF NOT EXISTS etiquetas TEXT[],
                             ADD COLUMN IF NOT EXISTS segmento VARCHAR(50);
ALTER TABLE nota_credito_cab ADD COLUMN IF NOT EXISTS ticket_id UUID;        -- spec decía "nota_credito"
-- índices (empresa_id, oportunidad_id) / (empresa_id, contrato_id) en cada tabla alterada
```

---

## 9. API REST — Endpoints Principales

Prefijo `/api/v1/crm`. JWT Bearer, `empresa_id` desde `@GetEmpresa()`, respuesta
`{data, meta, errors}`. Webhooks entrantes sin JWT, con verificación de firma.

| Método y ruta | Descripción | Permiso |
|---|---|---|
| `GET/POST /leads` · `PATCH /leads/:id` | CRUD de leads | `CRM_LEADS` |
| `POST /leads/:id/convertir` | Crea/vincula cliente y oportunidad | `CRM_LEADS` |
| `POST /leads/importar` | Importación Excel/CSV | `CRM_LEADS_IMPORTAR` |
| `GET /pipelines/:id/kanban` | Oportunidades agrupadas por etapa | `CRM_OPORTUNIDADES` |
| `GET/POST /oportunidades` · `PATCH /:id` | CRUD | `CRM_OPORTUNIDADES` |
| `PATCH /oportunidades/:id/etapa` | Mover de etapa (valida obligatorios) | `CRM_OPORTUNIDADES` |
| `POST /oportunidades/:id/presupuesto` | Genera presupuesto M36 desde ítems | `PRESUPUESTOS_CREAR` |
| `POST /oportunidades/:id/cierre/preview` | Simula payload y primeras facturas | `CRM_CERRAR_VENTA` |
| `POST /oportunidades/:id/cierre` | Ejecuta el cierre (transacción) | `CRM_CERRAR_VENTA` |
| `POST /oportunidades/:id/perder` | Marca perdida con motivo | `CRM_OPORTUNIDADES` |
| `GET/POST /actividades` | Agenda y registro | `CRM_ACTIVIDADES` |
| `GET /clientes/:id/timeline` | Timeline 360 paginado | `CRM_VER` |
| `GET /conversaciones` · `POST /conversaciones/:id/mensajes` | Bandeja y envío | `CRM_BANDEJA` |
| `POST /conversaciones/:id/asignar` · `/convertir` | Asignar; convertir en lead/oportunidad/ticket | `CRM_BANDEJA` |
| `GET/POST /tickets` · `PATCH /tickets/:id` | Gestión de tickets | `CRM_TICKETS` |
| `POST /tickets/:id/nota-credito` | Inicia NC SIFEN vinculada | `NOTAS_CREDITO_CREAR` |
| `GET/POST /contratos` · `PATCH /contratos/:id` | Contratos recurrentes | `CRM_CONTRATOS` |
| `POST /contratos/:id/consumos` | Carga de consumo del período | `CRM_CONTRATOS` |
| `GET /contratos/ciclos/pendientes` | Bandeja de recurrentes por aprobar | `CRM_CONTRATOS_APROBAR` |
| `POST /contratos/ciclos/aprobar` | Aprobación individual o en lote → emisión SIFEN | `CRM_CONTRATOS_APROBAR` |
| `PATCH /contratos/ciclos/:id` · `POST /:id/omitir` | Editar borrador / omitir período | `CRM_CONTRATOS_APROBAR` |
| `POST /contratos/:id/facturar-ahora` | Genera ciclo fuera de calendario (queda pendiente) | `CRM_CONTRATOS_FACTURAR` |
| `POST /contratos/:id/cambio-plan` | Upgrade/downgrade con prorrateo | `CRM_CONTRATOS` |
| `POST /contratos/:id/cancelar` | Baja con motivo | `CRM_CONTRATOS_CANCELAR` |
| `GET /reportes/{pipeline\|forecast\|sla\|mrr\|churn}` | Reportes | `CRM_REPORTES` |
| `POST /webhooks/whatsapp` · `/meta` · `/email` · `/leads-form` | Entrantes (firma verificada) | Público |
| `GET/POST /portal/*` (OTP) | Portal del cliente | Token cliente |

---

## 10. Permisos, Módulos de Suscripción y Jobs

> ⚠️ **Esta sección NO se implementa como está escrita.** La spec propone módulos de
> suscripción (`CRM_ESENCIAL`, `CRM_PRO`…) y una lista plana de 19 permisos. El repo usa
> `modulos` → `submodulos` → `privilegios`, y empaqueta los niveles comerciales en
> `plan_submodulos` / `plan_submodulos_addon`. El mapeo real está en `src/crm/CLAUDE.md`,
> sección "Permisos — modelo de 3 niveles".

### 10.1 Módulos de gating comercial

| Código | Habilita | Nivel |
|---|---|---|
| `CRM_ESENCIAL` | Leads, pipeline, oportunidades, actividades, ficha 360, cierre → factura única/cuotas, **bandeja WhatsApp básica (1 número, sin campañas masivas ni agente IA)**, fechas especiales, automatizaciones básicas, reportes de ventas, PWA vendedor | Esencial |
| `CRM_OMNICANAL` | Múltiples números WhatsApp, Email, IG/FB, Web chat, colas por equipo, campañas | Pro |
| `CRM_ATENCION` | Tickets, SLA, KB, CSAT/NPS, portal del cliente | Pro |
| `CRM_RECURRENTE` | Contratos, ciclos automáticos, débito, dunning, MRR | Pro |
| `CRM_IA` | Scoring, copiloto, agente IA, churn | Pro (consumo aparte) |

### 10.2 Permisos (seed idempotente en `seed.service.ts`)

`CRM_VER` · `CRM_LEADS` · `CRM_LEADS_IMPORTAR` · `CRM_OPORTUNIDADES` ·
`CRM_OPORTUNIDADES_TODAS` · `CRM_CERRAR_VENTA` · `CRM_ACTIVIDADES` · `CRM_BANDEJA` ·
`CRM_BANDEJA_TODAS` · `CRM_TICKETS` · `CRM_TICKETS_ADMIN` · `CRM_CONTRATOS` ·
`CRM_CONTRATOS_FACTURAR` · `CRM_CONTRATOS_APROBAR` · `CRM_CONTRATOS_CANCELAR` ·
`CRM_AUTOMATIZACIONES` · `CRM_REPORTES` · `CRM_CONFIG` · `CRM_VER_SALDO_CLIENTE`

| Rol | Permisos |
|---|---|
| Vendedor | `CRM_VER`, `LEADS`, `OPORTUNIDADES` (propias), `CERRAR_VENTA`, `ACTIVIDADES`, `BANDEJA` (asignadas), `VER_SALDO_CLIENTE` |
| Agente de atención | `CRM_VER`, `BANDEJA`, `TICKETS` |
| **Supervisor** | Todo lo anterior + `*_TODAS`, `REPORTES`, `AUTOMATIZACIONES`, **`CONTRATOS_APROBAR`** |
| Administración / Facturación | `CONTRATOS`, `CONTRATOS_FACTURAR`, `CONTRATOS_CANCELAR`, `REPORTES` (**no aprueba**) |
| Administrador | `CRM_CONFIG` + todos |

### 10.3 Tareas programadas

| Job | Frecuencia | Función |
|---|---|---|
| `crm.facturacion-recurrente` | Diario 05:00 | Genera borradores de ciclos pendientes de aprobación |
| `crm.recordatorio-aprobacion` | Diario 08:00 | Recuerda y escala ciclos sin aprobar |
| `crm.cobro-debito` | Diario 07:00 | Débitos automáticos y reintentos |
| `crm.dunning` | Diario 09:00 | Recordatorios, estados de mora y suspensión |
| `crm.renovaciones` | Diario | POR_RENOVAR, renovación automática, ajustes de precio |
| `crm.sla` | Cada 5 min | Alertas y escalamiento de tickets |
| `crm.estancadas` | Diario | Marca oportunidades estancadas |
| `crm.metricas` | Diario 02:00 | Snapshot de pipeline y MRR |
| `crm.ia-scoring` | Nocturno | Recalcula scoring y churn |

Implementación: `@nestjs/schedule` + BullMQ sobre el Redis existente, **con lock por empresa**
para evitar ejecuciones duplicadas en múltiples instancias PM2.

---

## 11. Seguridad y Cumplimiento

- **Ley 6534/2020** de protección de datos crediticios: consentimiento de contacto por
  WhatsApp (opt-in) registrado por cliente; opt-out con palabra clave ("BAJA").
- Credenciales de canales y tokens de cobro **cifrados con AES**. **Nunca se guarda el número
  completo de tarjeta**: solo el token de la pasarela.
- Webhooks con verificación de firma (`X-Hub-Signature-256` de Meta; API key de instancia en
  Evolution) y rate limiting. Servidor Evolution en red privada, con TLS y sin exponer el panel.
- Portal con OTP de un solo uso (expiración 10 min) y tokens de sesión cortos.
- Agente IA con herramientas de **solo lectura** y filtros por `empresa_id`.
- Auditoría completa vía AuditInterceptor; **documentos fiscales nunca se borran**.

---

## 12. Niveles Comerciales y Precio Sugerido

| Nivel | Precio sugerido | Cliente ideal |
|---|---|---|
| CRM Esencial | Gs. 69.000 / usuario / mes (mín. 2 usuarios) | Comercios que venden por WhatsApp y mostrador, distribuidoras, ferreterías |
| CRM Pro | Gs. 149.000 / usuario / mes (mín. 3 usuarios) | Servicios, colegios, gimnasios, clínicas, seguridad, software, internet |
| Add-on Agente IA | Incluido en Pro; consumo BYOK lo paga el cliente | Alto volumen de consultas |
| Mensajes WhatsApp | Costo Meta trasladado + 15% de gestión | Todos |
| Contratos recurrentes extra | Gs. 300.000 por bloque de 300 (más de 300 activos) | Empresas de abonados |
| Período de prueba | Gratis, días configurables por plan o por cliente | Clientes nuevos del add-on |

**Período de prueba del add-on**: el módulo se agrega a `suscripcion_modulos` con
`fecha_fin_prueba`; la duración se define en el plan y puede sobrescribirse por cliente.
Avisos a 7, 3 y 1 día. Al vencer sin contratar: **solo lectura 30 días** (los datos se
conservan) y luego bloqueo. Las facturas SIFEN ya emitidas no se ven afectadas.

---

## 13. Plan de Implementación

### 13.1 Fases (2 desarrolladores + supervisor)

| Fase | Alcance | Semanas | Entregable vendible |
|---|---|---|---|
| F0 — Fundaciones | Migraciones `crm_*`, permisos, módulos de suscripción, eventos de dominio, BullMQ, navegación | 2 | — |
| F1 — MVP Ventas | M90, M91, M92, M93, M94, M98 (única/cuotas), M102 básico, PWA vendedor | 5 | **CRM Esencial** |
| F2 — Omnicanal y Atención | M95 WhatsApp + Email, fechas especiales, plantillas y ventana 24 h, M96 tickets/SLA/CSAT, NC desde ticket, M100 automatizaciones | 6 | CRM Pro (parcial) |
| F3 — Recurrente y Portal | M99 contratos, ciclos, prorrateo, débito Bancard, dunning, MRR; M97 portal con OTP; comisiones | 5 | **CRM Pro** |
| F4 — IA y canales Meta | M101 scoring, copiloto, agente IA, churn; IG/FB; web chat; KB; secuencias; calendario | 5 | Add-on Agente IA |
| | **Total** | **23** | |

### 13.2 Prerrequisitos en el ERP (bloqueantes)

| # | Pendiente | Por qué bloquea | Necesario para |
|---|---|---|---|
| 1 | Órdenes de Venta: `POST /ordenes-venta/:id/facturar` (2B) y `PedidosService.convertirAFactura()` | El cierre con entrega necesita facturar desde la orden | F1 |
| 2 | Control de crédito de clientes (`limite_credito`, `saldo_pendiente`, `verificarCredito()`) | Validación de crédito en el paso 4 del cierre | F1 |
| 3 | Bancard real (hoy MOCK) + Débito Automático/tokenización | Cobro recurrente automático | F3 |
| 4 | Cuenta WhatsApp Business verificada por Meta + servidor Evolution para demos | Plantillas y bandeja | F2 |
| 5 | Migración `orden_tipo_facturacion` pendiente de aplicar | Facturación parcial desde orden | F1 |

### 13.3 Criterios de aceptación clave

- Un mensaje entrante de WhatsApp de un número nuevo crea un lead asignado y notificado en < 5 s.
- Mover una oportunidad a Ganada sin completar el asistente es **imposible**; la factura
  emitida coincide al 100% con la vista previa.
- El job recurrente es **idempotente** y **ninguna factura recurrente llega a SIFEN sin
  aprobación registrada** (test automatizado).
- Con el conector Baileys activo, los envíos automáticos quedan bloqueados.
- Un contrato en USD factura con la cotización del día de emisión y queda trazado en el ciclo.
- Una NC emitida desde un ticket reingresa stock al depósito original y queda vinculada al ticket.
- **Ninguna consulta del CRM se ejecuta sin filtro `empresa_id`** (test automatizado).

### 13.4 Plan de pilotos

| Aspecto | DOBASA — CRM Pro | AGOGO — CRM Esencial |
|---|---|---|
| Perfil | Importador y distribuidor a supermercados; usa todos los módulos | Tienda de regalos; vende por WhatsApp y en el local; ya usa NOVASIS |
| Alcance | Pipeline mayorista, ficha 360 con saldo y mora, bandeja WhatsApp + email, tickets de reclamos (faltantes, vencidos, devoluciones → NC SIFEN), contratos recurrentes si hay acuerdos periódicos | Bandeja WhatsApp (1 número) con venta punta a punta: consulta → pedido → link Bancard → factura SIFEN → "listo para retirar". **Sin envíos.** Cliente identificado por teléfono también en el POS. Fechas especiales y campañas de temporada |
| Fase | F1 y luego F2–F3 | F1 + F2 (el valor real llega con F2) |
| Usuarios | Equipo comercial + administración; el Supervisor aprueba recurrentes | 2 usuarios compartiendo el mismo número |
| WhatsApp | Meta Cloud API (número verificado) | **Meta Cloud API en producción** — no puede arriesgar el número con Baileys |
| Condición previa | **Cerrar los pendientes del ERP** (errores SIFEN, proveedores invisibles si ya son clientes, egresos de Tesorería que no descuentan saldo, reportes de ventas) | Completar teléfono E.164 en clientes, fotos de productos, verificación del número en Meta |
| Flujo de retiro | — | Pedido → reserva → pago por link o en el local → "Listo para retirar" → entregado. Si paga en el local se cobra desde el POS (**requiere botón "Cobrar Pedido"**, pendiente) |
| Métricas (60 días) | Reclamos dentro del SLA ≥ 90%; tiempo de respuesta; trazabilidad punta a punta | % de ventas por WhatsApp facturadas desde el CRM; respuesta < 15 min; conversión consulta → venta; recompra en fechas especiales |
| Seguimiento | Marcelo Palumbo + Derlis / Kevin | Marcelo Palumbo |

---

## 14. Riesgos y Decisiones

### 14.1 Riesgos

| Riesgo | Impacto | Mitigación |
|---|---|---|
| Verificación de WhatsApp lenta | Retrasa F2 | Iniciar verificación con Meta durante F0; desarrollar con Evolution |
| Costo de mensajes (desde 01/10/2026 también respuestas en ventana) | Margen del cliente | Mostrar costo estimado, consolidar mensajes, usar email para KuDE; trasladar con margen |
| Bloqueo de número con Evolution/Baileys | Pérdida del canal del cliente | Solo demos o riesgo aceptado por escrito; automatismos bloqueados |
| Aprobaciones atrasadas de recurrentes | Se demora facturación y cobro | Borrador 3 días antes, aprobación en lote, recordatorio y escalamiento |
| Rechazos SIFEN en emisión masiva | Facturas no emitidas el día | Cola existente con reintentos + reporte de ciclos fallidos |
| Alcance de Bancard débito automático por API | F3 manual | Plan B: link de pago recurrente por WhatsApp |
| Adopción por vendedores | CRM vacío | PWA simple, WhatsApp dentro del CRM, metas y comisiones ligadas al CRM |
| **Capacidad del equipo (2 devs con TURNE en deploy)** | Plazos | **Arrancar F1 al liberar TURNE**; F2–F4 condicionadas a ventas de F1 |

### 14.2 Decisiones tomadas (v1.1 – v1.5)

| # | Tema | Decisión |
|---|---|---|
| 1 | Proveedor WhatsApp | Adaptador con ambos conectores; Meta Cloud API como default de producción. Twilio solo SMS |
| 2 | Facturas recurrentes | Requieren aprobación siempre; emisión y débito recién después de aprobar |
| 3 | Pilotos | DOBASA con CRM Pro y AGOGO con CRM Esencial |
| 4 | Período de prueba | Gratuito con días configurables por plan o cliente |
| 5 | IA | Siempre BYOK; NOVASIS no cobra por conversación |
| 6 | Aprobación de recurrentes | Aprueba el Supervisor (una sola aprobación) |

> **Ajuste de empaquetado (v1.3)**: como el canal principal de AGOGO es WhatsApp, **CRM
> Esencial incluye una bandeja WhatsApp básica de 1 número**. Es lo que ofrecen Kommo y
> Clientify en su nivel de entrada.

### 14.3 Decisiones aún abiertas

1. ¿Contratos con facturación por consumo en v1 o solo abonos fijos? (propuesta: consumo en F3, carga manual/Excel).
2. ¿Precios definitivos de los niveles y bundles con el plan NOVASIS actual?

---

## 15. KPIs de Éxito

| KPI | Meta a 6 meses del lanzamiento |
|---|---|
| Clientes NOVASIS con CRM activo | ≥ 25% de la base activa |
| Tiempo de primera respuesta a leads (pilotos) | < 15 min en horario laboral |
| Conversión lead → venta (piloto) | +20% vs línea base |
| Facturas emitidas desde el CRM sin corrección | ≥ 98% |
| Mora de contratos recurrentes a 30 días | < 8% |
| Cumplimiento de SLA de tickets | ≥ 90% |
| Ingreso incremental por add-on CRM | Definir con ventas |

---

*Transcripción de `Novasis_CRM360_Analisis_Spec_v1.5.pdf` — Code100 SA / Blue Dragon SRL.*
