# Auditoría Completa — KleeMesa Help Desk SaaS

> Fecha: 2026-03-09  
> Versión del análisis: 1.0  
> Objetivo: Identificar gaps para lanzar un MVP real de Help Desk

> Actualización de avance (implementación): 2026-03-09

---

## 1. Diagnóstico General

### 1.1 Lo que existe y funciona

| Área | Estado | Profundidad |
|------|--------|-------------|
| **Tickets (CRUD + conversación)** | ✅ Funcional | ~3,800 líneas de modelo, 1,300+ de controlador, 8 vistas |
| **SLA (definición + cálculo)** | ⚠️ Lógica escrita | Políticas por prioridad/categoría/tipo, cálculo de deadlines, umbrales de alerta |
| **Autenticación** | ✅ Funcional | Login DB + LDAP fallback, rate limiting, sesiones aisladas por tenant |
| **RBAC (Roles + Permisos)** | ✅ Funcional | 3 niveles (Ninguno/Todo/Propio), permisos por módulo/acción en JSON |
| **Usuarios** | ✅ Funcional | CRUD completo, fotos, contraseñas, asignación de roles |
| **Alertas + Email** | ⚠️ Parcial | Cola de escritura funciona, plantillas de email existen, envío SMTP via PHPMailer |
| **Multi-tenancy** | ✅ Funcional | Filtrado automático por TenantId en queries, branding, aislamiento de sesión |
| **Auditoría** | ✅ Funcional | 4 tablas de log (acceso, acciones, módulos, URLs) |
| **Dashboard de tickets** | ✅ Funcional | 7 KPIs, 6 gráficas (ApexCharts), tendencias |
| **Estadísticas** | ✅ Funcional | Métricas de respuesta, resolución, cumplimiento SLA |

### 1.2 Inventario de controladores

| Controller | Estado | Tipo |
|-----------|--------|------|
| HomeController | ✅ Real | Dashboard técnico |
| TicketsController | ✅ Real | 18+ acciones, módulo principal |
| RolesController | ✅ Real | CRUD completo |
| UsuariosController | ✅ Real | CRUD + foto + password |
| AlertasController | ✅ Real | Generación de alertas |
| AlertasEmailController | ✅ Real | Cola de email + plantillas |
| ConfiguracionesController | ✅ Real | Settings (branding + sistema) |
| PermisosController | ✅ Real | Asignación de permisos |
| LoginController | ✅ Real | Autenticación |
| **ReportesController** | ✅ Real | Listado operativo con filtros + exportación CSV |
| **GraficasController** | 🟡 Legacy | Consolidado funcionalmente en `tickets/stats` |
| **SincronizacionController** | 🔴 Stub | Sin implementación |
| **ApiController** | 🟡 Minimal | Solo quickSearch + main |
| AjaxController | ⚠️ Minimal | Utilidades AJAX |
| TestController | 🔧 Dev | Herramienta de desarrollo |

### 1.3 Esquema de base de datos

#### Tablas core (Migración 1: 2026_02_15_000001)

```
├── roles
├── usuarios
├── sedes
├── permisos
├── alertas
├── alertas_email
├── configuraciones (key-value store)
├── log_acceso
├── log_acciones
├── log_modules
└── log_urls
```

#### Tablas helpdesk (Migración 2: 2026_03_05_000002)

```
CATÁLOGOS
├── tickets_estados (Id, Nombre, Orden, PermiteCierre, Estado)
├── tickets_subestados (Id, EstadoId, Nombre, Orden, Estado)
├── tickets_prioridades (Id, Nombre, Nivel, Color, Estado)
├── tickets_categorias (Id, Nombre, Descripcion, Orden, Estado)
├── tickets_subcategorias (Id, CategoriaId, Nombre, Orden, Estado)
├── tickets_etiquetas (Id, Nombre, Color, Estado)
├── tickets_sla_politicas (Id, PrioridadId, TipoTicket, CategoriaId,
│   MinutosPrimeraRespuesta, MinutosResolucion, UmbralAlerta, Estado)
├── tickets_grupos (Id, Nombre, Descripcion, Orden, Estado)
├── tickets_respuestas_predefinidas (Id, Titulo, Contenido, GrupoId, Orden, Estado)
└── tickets_autoasignacion_estado (GrupoId, UltimoUsuarioId, ActualizadoEn)

TICKET PRINCIPAL
└── tickets (33 campos)
    ├── Identificación: Id, NumeroCaso(UNIQUE), TipoTicket, Asunto, Descripcion
    ├── Solicitante: SolicitanteUsuarioId, SolicitanteNombre, CorreoPrincipal, CorreosCC
    ├── Clasificación: EstadoId, SubEstadoId, PrioridadId, CategoriaId, SubcategoriaId
   ├── Asignación: AgenteAsignadoId, GrupoId, EtiquetasCache
    ├── SLA: PrimeraRespuestaLimite, ResolucionLimite, PrimeraRespuestaEn,
    │        ResueltoEn, CerradoEn, ReabiertoCount,
    │        SlaPrimeraRespuestaIncumplido, SlaResolucionIncumplido,
    │        SlaPrimeraRespuestaAlerta, SlaResolucionAlerta
    ├── Actividad: UltimaActividadEn
    └── Auditoría: FechaRegistro, UsuarioRegistro, FechaModificacion, UsuarioModificacion, Estado

RELACIONES
├── tickets_rel_etiquetas (TicketId ↔ EtiquetaId)
├── tickets_cc (TicketId ↔ Correo)
├── tickets_watchers (TicketId ↔ UsuarioId, Fuente: manual|auto)
└── tickets_rel_grupos_usuarios (GrupoId ↔ UsuarioId)

COMUNICACIÓN
├── tickets_mensajes (TicketId, TipoMensaje, EsPublico, Contenido, TieneMencion)
├── tickets_adjuntos (TicketId, MensajeId, NombreOriginal, Ruta, MimeType, Tamano, EsImagen)
├── tickets_menciones (TicketId, MensajeId, UsuarioMencionadoId, AgregadoComoWatcher)
└── tickets_eventos (TicketId, EventoTipo, Descripcion, Datos JSON, ActorUsuarioId)

PORTAL
└── tickets_portal_tokens (TicketId, AccessToken, UltimoUsoEn)

BORRADORES
└── tickets_borradores (20 campos — auto-save cada 15s)
```

---

## 2. Huecos Funcionales Detectados

### 2.1 Módulo de Tickets

| Funcionalidad | Estado | Nota |
|---------------|--------|------|
| Creación | ✅ | Auto-save borradores, editor enriquecido, inline images |
| Seguimiento | ✅ | Vista detalle con timeline de eventos |
| Asignación | 🟡 Parcial | Manual + autoasignación round-robin opcional por grupo |
| Estados + Sub-estados | ✅ | Catálogo configurable con flag PermiteCierre |
| SLA | 🟡 Parcial | Políticas definidas, cálculo y CLI scheduler (`bin/check-sla`) implementados; validado en dry-run con datos reales |
| Conversación | ✅ | 3 tipos: público / respuesta solicitante / nota interna |
| Historial | ✅ | 14 tipos de evento en tickets_eventos |
| Adjuntos | ✅ | Upload con MIME detection, vinculado a mensajes |
| Menciones | ✅ | Parsing @usuario, auto-agrega como watcher |
| Watchers | ✅ | Fuentes: manual + auto (solicitante, agente, mencionados) |
| Búsqueda avanzada | ⚠️ Parcial | No hay full-text en contenido de mensajes |
| Filtros persistentes | ⚠️ Parcial | Backend disponible, despriorizado en UI por ahora |
| Reportes | ✅ Funcional | Filtros operativos + exportación CSV |
| Operaciones masivas | ✅ | Checkboxes + operaciones bulk (cerrar, asignar, prioridad) |
| Respuestas predefinidas | ✅ | Catálogo configurable + selector en formulario de respuesta |
| Merge de tickets | ❌ | No se pueden fusionar duplicados |
| Ticket hijo/relacionado | ❌ | No hay relaciones padre-hijo |
| Exportación | ❌ | No hay export CSV/Excel |
| Impresión | ❌ | No hay vista de impresión |

### 2.2 Configuración del Sistema

| Existe | Falta |
|--------|-------|
| Branding (nombre, logo, color) | ~~**Horario de soporte** (business hours) — crítico para SLA~~ ✅ Implementado |
| IP whitelist | ~~**Plantillas de email por evento** (ticket creado, asignado, resuelto, etc.)~~ ✅ Implementado |
| API token | ~~**Reglas de asignación automática**~~ ✅ Implementado (round-robin por grupo) |
| Catálogos de tickets (estados, prioridades, categorías, etiquetas, SLA, grupos y respuestas predefinidas) | **Reglas de escalamiento** |
| | **Configuración de canales** (email entrante, portal público) |
| | **Firma de agente** |
| | **Respuestas automáticas** (auto-reply al crear ticket) |
| | **Campos personalizados** en tickets |

### 2.3 Administración de Agentes

| Existe | Falta |
|--------|-------|
| Usuarios con roles | ~~**Grupos de agentes** (Soporte N1, N2, Infra, etc.)~~ ✅ Implementado |
| Permisos por módulo/acción | **Colas de tickets** por grupo |
| Asignación manual | ~~**Asignación automática** (round-robin, least-loaded)~~ ✅ Implementada (round-robin básico) |
| | **Estado de disponibilidad** (online/offline/ausente) |
| | **Horario de turno** por agente |
| | **Carga de trabajo visible** (tickets por agente) |

### 2.4 Automatizaciones

| Existe | No existe |
|--------|-----------|
| Cálculo de deadline SLA al crear ticket | **Motor de reglas** (if-then por evento) |
| Auto-add watcher por mención | ~~**Asignación automática** por categoría/prioridad~~ ✅ Implementada (grupo por defecto configurable) |
| Logging de eventos | **Escalamiento automático** (SLA al 80% → notificar supervisor) |
| | **Auto-close** de tickets inactivos |
| | **Auto-reply** al crear ticket |
| | **Triggers por cambio de estado** |
| | ~~**Cron/scheduler** para SLA y cola de emails~~ ✅ CLI implementados (`bin/check-sla`, `bin/process-mail-queue`) |

### 2.5 Canales de Entrada

| Canal | Estado |
|-------|--------|
| Interfaz web (agente) | ✅ Funcional |
| Portal público / cliente | ✅ Implementado (minimo por NumeroCaso + token) |
| Email entrante (crear/reply por email) | ❌ No existe |
| API REST | 🟡 Solo stubs |
| Formulario embebible (widget) | ❌ No existe |
| Webhook entrante | ❌ No existe |

### 2.6 Gestión de Clientes/Contactos

| Existe | No existe |
|--------|-----------|
| SolicitanteNombre + CorreoPrincipal en ticket | **Empresas/organizaciones** separadas |
| ~~**Tabla de contactos/clientes**~~ ✅ Implementada (`contactos`) | **Vinculación usuario ↔ empresa** |
| ~~**Perfil de cliente**~~ ✅ Implementado (nombre/email/teléfono/empresa) | Consolidación multi-contacto por empresa |
| ~~**Historial unificado**~~ ✅ Implementado (historial por contacto en detalle de ticket) | |
| CCs por ticket | |

### 2.7 Base de Conocimiento

✅ Implementada base funcional en modulo dedicado:
- Catalogo de categorias de conocimiento (`kb_categorias`).
- Articulos con resumen, contenido, palabras clave y visibilidad para portal (`kb_articulos`).
- Busqueda por texto y filtro por categoria en interfaz de agentes.
- Vinculacion articulo ↔ ticket (`tickets_rel_kb_articulos`) desde detalle del caso.

### 2.8 Reportes y Analítica

| Métrica | Disponible | Ubicación |
|---------|------------|-----------|
| Tickets creados vs cerrados | ✅ | stats dashboard |
| Distribución por estado | ✅ | stats dashboard |
| Distribución por prioridad | ✅ | stats dashboard |
| Top categorías | ✅ | stats dashboard |
| Top agentes | ✅ | stats dashboard |
| Tiempo promedio 1ra respuesta | ✅ | KPI card |
| Tiempo promedio resolución | ✅ | KPI card |
| % Cumplimiento SLA | ✅ | KPI card |
| Backlog abierto | ✅ | KPI card |
| Reportes exportables | ✅ | Export CSV operativo con filtros |
| SLA por agente | ❌ | |
| SLA por categoría | ❌ | |
| Tiempo en cada estado | ❌ | |
| First contact resolution rate | ❌ | |
| Reaperturas | ⚠️ | ReabiertoCount existe pero no se reporta |
| CSAT / Satisfacción | ❌ | |

### 2.9 Experiencia del Agente

| Existe | No existe |
|--------|-----------|
| Vista bandeja con filtros | Atajos de teclado |
| Cola de pendientes | Vista split-pane (lista + preview) |
| Búsqueda global | Vistas guardadas / filtros persistentes (despriorizado en UI) |
| 8 filtros rápidos predefinidos | ~~Respuestas rápidas (canned responses)~~ ✅ Implementadas |
| KPI counters en dashboard | Timer de SLA visible en cada ticket |
| Borrador auto-save | Indicador de colisión (otro agente mismo ticket) |
| | Notificaciones en tiempo real |
| | Contador de tickets sin leer |

### 2.10 Configuración Multi-Empresa

| Existe | No existe |
|--------|-----------|
| Multi-tenancy por host | Panel de administración de tenants |
| Filtrado automático por TenantId | Sedes conectadas a tickets |
| Branding por tenant | Equipos de soporte por sede/empresa |
| Sesiones aisladas | Reportes filtrados por sede/tenant |

---

## 3. Módulos que Faltan para un MVP

> Estado de avance: los ítems #1, #2, #3, #4, #5, #6, #7, #8 y #9 de esta lista ya están implementados en código. Se mantienen aquí como referencia del diagnóstico original.

| # | Módulo | Criticidad | Justificación |
|---|--------|------------|---------------|
| 1 | **Procesador de cola de emails** (`bin/process-mail-queue`) | 🔴 BLOQUEANTE | Sin esto, las notificaciones por email no se envían nunca |
| 2 | **Scheduler de SLA** (`bin/check-sla` o cron) | 🔴 BLOQUEANTE | Sin esto, las alertas y breaches de SLA no se computan |
| 3 | **Plantillas de email por evento** | 🔴 BLOQUEANTE | El sistema necesita emails transaccionales (creado, asignado, respondido, resuelto) |
| 4 | **Portal de cliente** | 🟠 ALTO | Los solicitantes no tienen forma de ver/responder sus tickets |
| 5 | ~~**Contactos/Clientes**~~ ✅ Implementado | 🟠 ALTO | Ya se puede rastrear historial por contacto y ver perfil en ticket |
| 6 | ~~**Grupos de agentes**~~ ✅ Implementado | 🟠 ALTO | Organización de equipos de soporte habilitada |
| 7 | ~~**Asignación automática**~~ ✅ Implementado (round-robin básico) | 🟡 MEDIO | Reduce triage manual y acelera asignación inicial |
| 8 | ~~**Reportes funcionales**~~ ✅ Implementado | 🟡 MEDIO | Reportes operativos con filtros y exportación CSV |
| 9 | ~~**Respuestas predefinidas**~~ ✅ Implementado | 🟡 MEDIO | Productividad del agente mejorada en conversación |
| 10 | ~~**Base de conocimiento**~~ ✅ Implementado | 🔵 BAJO | Modulo operativo con categorias, articulos y vinculacion a tickets |
| 11 | **Email entrante** (pipe/IMAP) — **Fase 2** | 🔵 BAJO | Activar cuando el canal principal sea correo o aumente el volumen de solicitudes externas |

---

## 4. Funcionalidades Mínimas para MVP Funcional

### 4.1 Must-Have (Día 1)

- [x] Crear ticket desde interfaz de agente
- [x] Asignar ticket a un agente
- [x] Cambiar estado, prioridad, categoría
- [x] Conversación pública + notas internas
- [x] Adjuntar archivos
- [x] Historial de cambios
- [x] Definir políticas SLA
- [x] **SLA se computa y alerta en tiempo real** (CLI `bin/check-sla` implementado y validado en dry-run)
- [x] **Emails transaccionales se envían** (CLI `bin/process-mail-queue` implementado)
- [x] **Email al solicitante cuando se crea ticket**
- [x] **Email al agente cuando se le asigna un ticket**
- [x] **Email al solicitante cuando hay respuesta**
- [x] **Email al agente cuando el solicitante responde**
- [x] **Portal mínimo para que el solicitante vea su ticket y responda**
- [x] Dashboard con métricas básicas
- [x] Roles y permisos por módulo
- [x] **Horario de soporte** (para SLA en horas hábiles)

### 4.2 Should-Have (Semana 2-4)

- [x] Grupos de agentes
- [x] Asignación automática básica (round-robin)
- [x] Respuestas predefinidas
- [x] Reportes exportables (CSV)
- [ ] Vistas guardadas / filtros persistentes
- [x] Operaciones masivas (bulk close, bulk assign)
- [x] Tabla de contactos con historial

### 4.3 Nice-to-Have (Mes 2+)

- [ ] Email entrante (crear ticket por email) — Fase 2 (activar con alto volumen por correo)
- [x] Base de conocimiento
- [ ] API REST completa — Fase 2 (activar cuando se necesiten integraciones externas)
- [ ] Webhooks salientes
- [ ] CSAT / encuestas post-resolución
- [ ] Reglas de escalamiento automático
- [ ] Campos personalizados
- [ ] Detección de colisión entre agentes

---

## 5. Roadmap Recomendado

### PRIORIDAD ALTA — Imprescindible para funcionar

| # | Tarea | Esfuerzo | Impacto | Estado |
|---|-------|----------|---------|--------|
| 1 | **Crear `bin/process-mail-queue`** — CLI que lee `mail_queue.jsonl`, envía con `MailService::send()`, y mueve a procesados | Bajo | Sin esto no hay emails | ✅ Implementado |
| 2 | **Crear `bin/check-sla`** — CLI que llama `TicketsModel::refreshSlaIndicators()` para todos los tickets abiertos | Bajo | Sin esto SLA es decorativo | ✅ Implementado (validado en `--dry-run`) |
| 3 | **Plantillas de email transaccional** — 5 plantillas core: ticket_created, ticket_assigned, ticket_replied, ticket_resolved, sla_breach. Integrar con `MailService::queue()` en eventos del controlador | Medio | Sin esto los stakeholders no se enteran | ✅ Implementado (seeder ejecutado: 5 plantillas) |
| 4 | **Horario de soporte** — Configuración en `configuraciones` con días/horas hábiles. Modificar cálculo SLA para horas laborales | Medio | SLA incorrecto sin esto | ✅ Implementado |
| 5 | **Portal mínimo de cliente** — Vista pública (layout `metronicPublic`) para que el solicitante vea su ticket por NumeroCaso + token y pueda responder | Medio-Alto | Sin esto el solicitante no interactúa | ✅ Implementado |

### PRIORIDAD MEDIA — Importantes pero no bloqueantes

| # | Tarea | Esfuerzo | Impacto | Estado |
|---|-------|----------|---------|--------|
| 6 | **Grupos de agentes** — Tabla `tickets_grupos`, relación N:M con usuarios, columna GrupoId en tickets | Medio | Organización de equipos | ✅ Implementado |
| 7 | **Asignación automática** — Round-robin por grupo, configurable en settings | Medio | Reduce carga manual de triage | ✅ Implementado (versión básica) |
| 8 | **Respuestas predefinidas** — Tabla `tickets_respuestas_predefinidas`, selector en reply form | Bajo | Productividad del agente | ✅ Implementado |
| 9 | **Tabla de contactos** — Tabla `contactos` con nombre, email, teléfono, empresa. Vincular con SolicitanteUsuarioId | Medio | Contexto del cliente | ✅ Implementado |
| 10 | **Reportes exportables** — Implementar queries en ReportesModel, export CSV | Medio | Análisis operativo | ✅ Implementado |
| 11 | **Vistas guardadas** — Tabla `tickets_vistas_guardadas` con filtros serializados por usuario | Bajo | UX del agente | Pendiente (despriorizado en UI) |
| 12 | **Operaciones masivas** — Checkboxes en lista + acciones: cerrar, asignar, cambiar prioridad | Medio | Eficiencia operativa | ✅ Implementado (menú dedicado) |

### PRIORIDAD BAJA — Futuras

| # | Tarea | Esfuerzo | Impacto |
|---|-------|----------|---------|
| 13 | **Email entrante** (IMAP polling o pipe) — **Fase 2** | Alto | Canal adicional cuando soporte por correo sea relevante |
| 14 | **API REST completa** — CRUD tickets, contactos, catálogos con auth por token — **Fase 2** | Alto | Integraciones externas |
| 15 | **Base de conocimiento** — Artículos, categorías, búsqueda, vinculación a tickets | Alto | Self-service (✅ Implementado) |
| 16 | **Motor de reglas** — Tabla de reglas: condición + acción, evaluación en EventDispatcher | Alto | Workflows avanzados |
| 17 | **CSAT/Encuestas** — Link en email de resolución → formulario → registro | Medio | Calidad de servicio |
| 18 | **Webhooks salientes** — Notificar URLs externas en eventos de ticket | Medio | Ecosistema |
| 19 | **Campos personalizados** — Definiciones + valores por ticket, metadata flexible | Alto | Personalización |
| 20 | **Detección de colisión** — Polling/WebSocket para detectar agentes en mismo ticket | Medio | UX avanzada |

> Criterio recomendado para activar el #13 (Fase 2):
> 1. El correo se convierte en canal frecuente de atención (alto porcentaje de solicitudes por email).
> 2. Se necesita crear o responder tickets desde email sin pasar por el portal.

---

## 6. Sugerencias de Arquitectura y Usabilidad

### 6.1 Simplificar para lanzar rápido

1. **Eliminar módulos dummy**: Mantener ocultos `graficas`, `sincronizacion` y `test` en `Modules.php` mientras no aporten flujo funcional al MVP.

2. **Unificar analítica en un solo flujo**: Mantener indicadores y gráficas en `tickets/stats`; usar `reportes` para exportables operativos.

3. **Portal de cliente con link mágico**: En lugar de auth completa para clientes, generar token único por ticket y enviarlo por email. Acceso via `?token=xxx`. Ahorra un módulo de gestión de cuentas.

4. **Cron simple = 2 scripts**: Todo lo que se necesita para background processing:
   ```
   */5  * * * * php /path/bin/process-mail-queue
   */10 * * * * php /path/bin/check-sla
   ```
   No se necesita Redis/RabbitMQ para el MVP.

### 6.2 Mejoras de arquitectura

5. **Separar `TicketsModel` (3,800+ líneas)**:
   - `TicketSlaService` — Cálculos de SLA
   - `TicketNotificationService` — Lógica de notificaciones y plantillas
   - `TicketAnalyticsService` — Queries de dashboard/stats
   - Mantener `TicketsModel` solo para CRUD y relaciones

6. **Usar `EventDispatcher` existente**: El core ya lo tiene pero no se usa en tickets. Conectar eventos (crear, asignar, resolver, breach SLA) al dispatcher para desacoplar notificaciones y futura automatización.

7. **Indexar para rendimiento**:
   ```sql
   CREATE INDEX idx_tickets_agent_status ON tickets(AgenteAsignadoId, EstadoId, Estado);
   CREATE INDEX idx_tickets_solicitante ON tickets(CorreoPrincipal, Estado);
   CREATE INDEX idx_tickets_fecha ON tickets(FechaRegistro, EstadoId);
   ```

### 6.3 Quick wins de UX

8. **Badge de SLA en cada fila**: Mostrar rojo/amarillo/verde usando PrimeraRespuestaLimite y ResolucionLimite.

9. **Contador de tickets sin respuesta en el menú**: Badge numérico en "Tickets Pendientes".

10. **Copiar número de caso**: Botón 1-click para copiar NumeroCaso al portapapeles.

---

## Resumen Ejecutivo

**El sistema tiene ~60-65% del MVP construido.**

La base técnica (framework, auth, multi-tenancy, RBAC, auditoría) es sólida. El módulo de tickets tiene funcionalidad real y profunda.

Los gaps críticos restantes están en capacidades de operación y escala avanzada (automatización, canales adicionales e integraciones).

Los **5 items de prioridad alta** ya quedaron implementados y cubren el delta mínimo para un MVP lanzable:

1. `bin/process-mail-queue`
2. `bin/check-sla`
3. Plantillas de email transaccional
4. Horario de soporte (business hours)
5. Portal mínimo de cliente

Los módulos con menor madurez (gráficas standalone, sincronización y test) deben permanecer ocultos hasta implementarse.
