Files
whatsapp/PLAN_ERP_MULTIMODULO.txt
T
2026-04-16 22:23:33 -05:00

575 lines
30 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
================================================================================
PLAN DE EVOLUCIÓN: BOT WHATSAPP → ERP MULTI-MÓDULO
Proyecto: Panel de Laboratorio + WhatsApp Bot Manager
Fecha: Abril 2026
================================================================================
────────────────────────────────────────────────────────────────────────────────
1. ESTADO ACTUAL — QUÉ TENEMOS
────────────────────────────────────────────────────────────────────────────────
MÓDULOS YA OPERATIVOS:
✔ WhatsApp Bot respuestas automáticas, menús, plantillas Meta
✔ Conversaciones bandeja de entrada, operadores asignados
✔ Mensajes Programados campañas por fecha/hora
✔ Pacientes ficha clínica, historial
✔ Domicilios agenda de servicios a domicilio con flujo de estados
✔ Enfermeras/Personal portal propio, agenda diaria
✔ Órdenes Médicas PDF adjunto, autorización
✔ Formularios builder drag-drop, firma digital, enlace público
✔ Reportes ingresos, rendimiento de enfermeros, pagos
✔ Actividad/Auditoría log de cambios por usuario
✔ Usuarios & Roles RBAC completo (roles + role_modules)
✔ Configuración tarifas, laboratorio, WhatsApp
ARQUITECTURA ACTUAL:
• Todos los archivos PHP en la raíz del proyecto (lab_*.php, index.php…)
• API separada en /api/ y /api/lab/
• Clases en /classes/ y /services/
• Base de datos: 34 tablas, una sola BD "usite_whatsapp_bot"
• RBAC: tabla roles + role_modules + SYSTEM_MODULES en config.php
• Sesiones PHP nativas (login en admin_users)
PROBLEMA PRINCIPAL PARA CRECER:
• Sin sistema de enrutamiento → cada módulo es un archivo suelto en raíz
• SYSTEM_MODULES hardcodeado en config.php (hay que editarlo cada vez)
• No hay separación de carpetas por módulo (todo mezclado)
• Navegación duplicada en cada .php del módulo lab
• Sin un punto de entrada único (todo camino directo al .php)
────────────────────────────────────────────────────────────────────────────────
2. VISIÓN TARGET — ERP MULTI-MÓDULO
────────────────────────────────────────────────────────────────────────────────
CONCEPTO:
Un sistema central con un panel unificado donde cada "módulo" es un paquete
autocontenido. El core gestiona: autenticación, routing, menú lateral,
RBAC, notificaciones y eventos. Los módulos se enchufan al core sin
modificar archivos existentes.
MÓDULOS PLANIFICADOS (oleadas):
OLEADA 0 Ya en producción (refactorizar para que usen la nueva estructura)
- whatsapp_bot → Bot + Conversaciones + Plantillas
- lab_domicilios → Agenda de domicilios
- lab_pacientes → Pacientes y fichas
- lab_formularios → Builder de formularios
- lab_reportes → Reportes e indicadores
- lab_ordenes → Órdenes médicas
- lab_enfermeras → Gestión de personal clínico
- sistema → Usuarios, Roles, Configuración
OLEADA 1 Nuevos módulos solicitados
- turnero → Sistema de turnos presenciales en recepción
OLEADA 2 Módulos futuros probables
- registro_exams → Registro directo de exámenes de laboratorio
(sin domicilio: paciente llega a la sede)
- facturacion → Facturación electrónica / DIAN (Colombia)
- inventario → Reactivos, insumos, stock mínimo
- citas → Agenda de citas con calendario visual
- resultados → Entrega digital de resultados (portal paciente)
- crm_pacientes → Campañas, seguimientos, cohortes
────────────────────────────────────────────────────────────────────────────────
3. NUEVA ESTRUCTURA DE CARPETAS
────────────────────────────────────────────────────────────────────────────────
/
├── core/ ← Núcleo del ERP (NO tocar por módulos)
│ ├── App.php ← Bootstrap, registro de módulos
│ ├── Router.php ← Enrutador simple (mapea URL→módulo/acción)
│ ├── Auth.php ← Login/logout/sesión (extraído de config.php)
│ ├── Rbac.php ← hasModule(), requireModule(), permisos
│ ├── ModuleRegistry.php ← Catálogo dinámico de módulos instalados
│ ├── Layout.php ← Renderiza sidebar, navbar, footer
│ └── Helpers.php ← Funciones globales (esc, jsonOk, etc.)
├── modules/ ← Un subdirectorio por módulo
│ ├── whatsapp_bot/
│ │ ├── module.php ← Descriptor: nombre, slug, icono, permisos
│ │ ├── views/ ← Las páginas (ex lab_*.php migradas)
│ │ └── api/ ← Endpoints REST propios del módulo
│ │
│ ├── domicilios/
│ │ ├── module.php
│ │ ├── views/
│ │ └── api/
│ │
│ ├── turnero/ ← NUEVO ★ (Oleada 1)
│ │ ├── module.php
│ │ ├── views/
│ │ │ ├── dashboard.php ← Pantalla administrador
│ │ │ ├── display.php ← Pantalla TV/recepción (sin login)
│ │ │ └── kiosko.php ← Pantalla táctil toma de turno
│ │ └── api/
│ │ ├── create_turno.php
│ │ ├── llamar_turno.php
│ │ ├── get_estado.php
│ │ └── sse_turno.php ← Server-Sent Events para la pantalla TV
│ │
│ ├── registro_exams/ ← PENDIENTE — Oleada 2
│ │ ├── module.php
│ │ ├── views/
│ │ │ ├── registrar.php
│ │ │ ├── lista.php
│ │ │ └── detalle.php
│ │ └── api/
│ │ ├── save_examen.php
│ │ ├── get_examenes.php
│ │ ├── cambiar_estado.php
│ │ └── imprimir_etiqueta.php
│ │
│ └── sistema/
│ ├── module.php
│ ├── views/
│ │ ├── usuarios.php ← lab_usuarios.php migrado
│ │ └── configuracion.php
│ └── api/
├── shared/ ← Componentes reutilizables entre módulos
│ ├── components/
│ │ ├── sidebar.php ← Menú lateral dinámico (según módulos del rol)
│ │ ├── navbar.php
│ │ ├── page_header.php
│ │ └── modal_confirm.php
│ └── js/
│ ├── erp-core.js ← fetch wrapper, toasts, eventos globales
│ └── erp-table.js ← Tablas con filtro, paginación, export
├── classes/ ← (ya existe, mantener)
├── services/ ← (ya existe, mantener)
├── api/ ← API global (ya existe, mantener para bot)
├── config/
│ └── config.php ← Simplificado: SOLO BD y constantes base
├── public/ ← (opcional futuro) assets compilados
│ └── assets/
└── index.php ← Punto de entrada único → instancia App.php
NOTA SOBRE MIGRACIÓN SIN ROMPER NADA:
Los archivos lab_*.php actuales permanecen en raíz mientras se migran.
Se crea un alias: cada modules/X/views/Y.php incluye el legacy si aún no
se ha reescrito. No hay "big bang rewrite".
────────────────────────────────────────────────────────────────────────────────
4. SISTEMA DE ROLES Y PERMISOS (RBAC EXPANDIDO)
────────────────────────────────────────────────────────────────────────────────
MODELO ACTUAL:
roles (id, name, slug, color, is_system)
└── role_modules (role_id, module_slug) ← solo read/write implícito
MODELO PROPUESTO — RBAC con acciones:
┌─────────────────────────────────────────────────────────────┐
│ roles │
│ id | name | slug | description | color | is_system │
└──────────────────┬──────────────────────────────────────────┘
│ 1:N
┌──────────────────▼──────────────────────────────────────────┐
│ role_permissions (reemplaza role_modules con más granularidad)
│ id | role_id | module_slug | can_view | can_create │
│ can_edit | can_delete | can_export | extra_json │
└─────────────────────────────────────────────────────────────┘
extra_json ejemplos:
turnero → {"puede_llamar": true, "puede_reasignar": false}
reportes → {"rango_max_dias": 90}
whatsapp → {"puede_broadcast": true}
ROLES DEL SISTEMA A DEFINIR:
Slug Nombre Descripción
─────────────────────────────────────────────────────────────────
superadmin Super Admin Acceso total, configura el sistema
admin Administrador Acceso total sin configuración técnica
recepcionista Recepcionista Turnero + Pacientes (Oleada 1)
bacteriologo Bacteriólogo Registro exámenes + Resultados (Oleada 2)
enfermero Enfermero Portal domicilios (ya existe)
supervisor Supervisor Reportes + sin acceso a config
operador_bot Operador WhatsApp Solo bandeja de conversaciones
readonly Solo lectura Ver dashboards sin editar
REGLA: is_system=1 en superadmin y admin → no se pueden borrar.
Los demás roles son personalizables por el cliente.
FLUJO DE VERIFICACIÓN EN UNA VISTA:
1. ¿Está logueado? → sino → login
2. ¿El rol tiene module_slug? → sino → 403 sin módulo
3. ¿La acción requiere can_edit? → verificar permiso específico
4. ¿Hay restricción extra_json? → verificar campo relevante
HELPER PROPUESTO (core/Rbac.php):
hasModule($slug) → bool (ya existe en helpers)
canDo($slug, $action) → bool (nuevo, $action = view/create/edit/delete/export)
requireAction($slug, $action) → lanza 403 si no tiene permiso
────────────────────────────────────────────────────────────────────────────────
5. MÓDULO TURNERO — DISEÑO DETALLADO
────────────────────────────────────────────────────────────────────────────────
CONCEPTO:
Sistema de turnos para pacientes que llegan presencialmente a la sede.
Tres pantallas distintas:
A) Kiosko (tablet/touch en recepción) → el paciente toma su turno
B) TV/Display (pantalla grande) → muestra turno actual + cola
C) Dashboard admin → el operador llama turnos, gestiona
TABLAS BD NUEVAS:
turnero_servicios
id, nombre, prefijo (ej. "A"), color, tiempo_estimado_min, activo
turnero_sesiones
id, fecha, abierto_por INT FK admin_users, cerrado_por, inicio_at, fin_at
(una sesión = un día de atención)
turnero_turnos
id, sesion_id,
numero INT, ← número correlativo de la sesión
codigo VARCHAR(10), ← "A001", "B012"
servicio_id,
paciente_nombre VARCHAR(150),
paciente_cel VARCHAR(20),
estado ENUM(espera, llamado, en_atencion, atendido, ausente, cancelado),
modulo_atencion INT, ← puesto/ventanilla que atiende
llamado_at, inicio_at, fin_at, creado_at
turnero_modulos
id, nombre (ej. "Ventanilla 1"), activo, usuario_actual INT FK admin_users
FLUJO:
1. Recepcionista / kiosko crea turno → estado "espera"
2. Operador en dashboard hace clic "Llamar siguiente"
→ estado "llamado", pantalla TV muestra "A-001 → Ventanilla 2"
→ (opcional) SMS/WhatsApp al paciente con su turno
3. El paciente llega → operador pasa a "en_atención"
4. Al terminar → "atendido"
5. Si no aparece → "ausente" (puede regresar al final de la cola)
PANTALLA TV (display.php):
• Sin login
• Se actualiza por SSE (Server-Sent Events) cada vez que se llama un turno
• Muestra: turno actual por cada ventanilla + próximos 5 en espera
• Diseño visual grande, colores por servicio
INTEGRACIÓN CON WHATSAPP (OPCIONAL):
Cuando se llama el turno → enviar mensaje al paciente si dejó celular
Usar WhatsAppService ya existente.
────────────────────────────────────────────────────────────────────────────────
6. MÓDULO REGISTRO DE EXÁMENES — DISEÑO DETALLADO [OLEADA 2 — pendiente]
────────────────────────────────────────────────────────────────────────────────
CONCEPTO:
Registrar exámenes de análisis clínico cuando el paciente llega a la sede
(a diferencia de lab_domicilios que es a domicilio).
Incluye: recepción de muestra, trazabilidad, estado de procesamiento,
y eventualmente entrega de resultados.
TABLAS BD NUEVAS:
exam_tipos
id, codigo (ej. "HEM", "GLU"), nombre, categoria, precio_base,
requiere_ayunas TINYINT, instrucciones TEXT, activo
exam_ordenes (la "orden de trabajo" del laboratorio)
id, paciente_id FK lab_pacientes,
numero_orden VARCHAR(20) UNIQUE, ← ej. "ORD-2026-00123"
origen ENUM(presencial, domicilio, whatsapp, referido),
medico_remitente VARCHAR(150),
entidad_pagadora VARCHAR(150),
tipo_pago ENUM(particular, eps, convenio),
total_cobrado DECIMAL(10,2),
estado ENUM(pendiente, en_proceso, parcial, completado, entregado, anulado),
observaciones TEXT,
recibido_por INT FK admin_users,
creado_at, actualizado_at
exam_items (los exámenes individuales dentro de una orden)
id, orden_id FK exam_ordenes,
tipo_id FK exam_tipos,
estado ENUM(pendiente, muestra_tomada, en_analisis, resultado_listo, entregado),
muestra_tipo VARCHAR(50), ← sangre, orina, hisopado...
muestra_recibida_at,
resultado TEXT,
resultado_pdf VARCHAR(300),
procesado_por INT FK admin_users,
entregado_at
exam_etiquetas (para imprimir en los tubos)
id, item_id FK exam_items,
codigo_barras VARCHAR(50) UNIQUE,
impreso_at, impreso_por INT FK admin_users
FLUJO:
1. Recepcionista busca/crea paciente (reutiliza lab_pacientes)
2. Crea orden → agrega exámenes de la lista exam_tipos
3. Sistema genera número de orden y código de barras por tubo
4. Se imprime etiqueta (ZPL o PDF)
5. Bacteriólogo cambia estado → en_análisis → resultado_listo
6. Administrador entrega resultados (descarga PDF / enlace portal)
RELACIÓN CON MÓDULOS EXISTENTES:
• Paciente → usa lab_pacientes (ya existe)
• Si viene de un domicilio → exam_ordenes.origen = 'domicilio',
vincular con lab_domicilios (campo opcional domicilio_id)
• Si tiene orden médica adjunta → vincular con lab_ordenes_medicas
────────────────────────────────────────────────────────────────────────────────
7. BASE DE DATOS — PLAN DE MIGRACIONES
────────────────────────────────────────────────────────────────────────────────
REGLA: todas las migraciones son ADITIVAS (ALTER ADD, CREATE TABLE).
NUNCA DROP COLUMN ni RENAME en producción sin respaldo previo.
Migración 001 RBAC expandido
ALTER TABLE role_modules ADD COLUMN can_view TINYINT(1) DEFAULT 1;
ALTER TABLE role_modules ADD COLUMN can_create TINYINT(1) DEFAULT 0;
ALTER TABLE role_modules ADD COLUMN can_edit TINYINT(1) DEFAULT 0;
ALTER TABLE role_modules ADD COLUMN can_delete TINYINT(1) DEFAULT 0;
ALTER TABLE role_modules ADD COLUMN can_export TINYINT(1) DEFAULT 0;
ALTER TABLE role_modules ADD COLUMN extra_json JSON NULL;
RENAME TABLE role_modules TO role_permissions; ← (o alias)
Migración 002 Nuevos roles
INSERT INTO roles (name, slug, description, color, is_system) VALUES
('Super Admin', 'superadmin', 'Acceso total al sistema', '#dc3545', 1),
('Recepcionista', 'recepcionista', 'Turnero y recepción de muestras', '#198754', 0),
('Bacteriólogo', 'bacteriologo', 'Análisis y resultados', '#0dcaf0', 0),
('Supervisor', 'supervisor', 'Solo reportes y consultas', '#fd7e14', 0),
('Operador Bot', 'operador_bot', 'Gestión de conversaciones', '#6f42c1', 0);
Migración 003 Turnero [Oleada 1]
CREATE TABLE turnero_servicios (...)
CREATE TABLE turnero_sesiones (...)
CREATE TABLE turnero_turnos (...)
CREATE TABLE turnero_modulos (...)
Migración 004 SYSTEM_MODULES dinámica (mover de config.php a BD) [Oleada 1]
CREATE TABLE system_modules (
slug VARCHAR(100) PK,
name VARCHAR(150),
icon VARCHAR(50), ← "fas fa-vials"
category VARCHAR(50), ← "lab", "bot", "sistema", "clinico"
route VARCHAR(200), ← URL base del módulo
is_active TINYINT(1),
sort_order INT,
created_at TIMESTAMP
)
Poblar con los módulos actuales + turnero.
registro_exams se agrega en Migración 005 (Oleada 2).
config.php mantiene el array como fallback hasta que la BD esté lista.
Migración 005 Registro de exámenes [Oleada 2]
CREATE TABLE exam_tipos (...)
CREATE TABLE exam_ordenes (...)
CREATE TABLE exam_items (...)
CREATE TABLE exam_etiquetas(...)
────────────────────────────────────────────────────────────────────────────────
8. ROUTER Y PUNTO DE ENTRADA
────────────────────────────────────────────────────────────────────────────────
OPCIÓN RECOMENDADA (sin framework, compatible con estructura actual):
index.php → incluye core/App.php
App.php → lee $_GET['m'] (módulo) y $_GET['v'] (vista)
→ verifica sesión + permisos via Rbac.php
→ incluye modules/{m}/views/{v}.php
→ si no existe → 404 amigable
URLS LIMPIAS con .htaccess:
/turnero/dashboard → ?m=turnero&v=dashboard
/turnero/display → ?m=turnero&v=display (sin login)
/lab/domicilios → ?m=domicilios&v=index
/lab/pacientes → ?m=lab_pacientes&v=index
.htaccess ya existe en el proyecto → solo agregar RewriteRules.
COMPATIBILIDAD:
Los lab_*.php en raíz siguen funcionando directamente.
El router añade una capa adicional, no reemplaza lo existente.
Migración gradual: mover módulos uno a uno al nuevo sistema.
────────────────────────────────────────────────────────────────────────────────
9. LAYOUT Y NAVEGACIÓN UNIFICADA
────────────────────────────────────────────────────────────────────────────────
PROBLEMA ACTUAL:
Cada lab_*.php repite el mismo sidebar a mano (>50 líneas duplicadas).
Si se agrega un módulo hay que editar todos los archivos.
SOLUCIÓN:
shared/components/sidebar.php → se genera dinámicamente desde:
1. La tabla system_modules (activos)
2. Filtrado por los módulos que tiene el rol del usuario logueado
3. Agrupados por "category" (Bot, Laboratorio, Clínico, Sistema)
Cada layout nueva vista incluye:
<?php include APP_ROOT . '/shared/components/sidebar.php'; ?>
El sidebar detecta la URL activa y resalta el elemento correspondiente.
GRUPOS DEL MENÚ LATERAL:
🤖 WhatsApp
Conversaciones | Bot & Menús | Plantillas | Programados
🏥 Laboratorio
Dashboard | Domicilios | Pacientes | Enfermeras | Órdenes
🧪 Clínico (Oleada 2)
Registro Exámenes | Resultados
🎟️ Turnero (Oleada 1)
Dashboard | Configurar Servicios
📊 Reportes
Ingresos | Rendimiento | Exportar
⚙️ Sistema
Usuarios & Roles | Configuración | Actividad
────────────────────────────────────────────────────────────────────────────────
10. PLAN DE IMPLEMENTACIÓN — FASES
────────────────────────────────────────────────────────────────────────────────
── BASE DEL SISTEMA ─────────────────────────────────────────────────────────
FASE 0 Preparación (1-2 días) [SIN impacto en producción] ✅ COMPLETADA
✓ Crear carpetas: core/, modules/, shared/
✓ Extraer Auth.php y Rbac.php desde config.php y _helpers.php
✓ Crear shared/components/sidebar.php unificado
✓ Migración 001: expandir role_permissions (columnas can_*)
✓ Migración 002: insertar nuevos roles
✓ Agregar nuevos slugs a SYSTEM_MODULES en config.php
FASE 1 Core: Router y estructura modular (1 semana) ✅ COMPLETADA
✓ Crear core/Router.php y core/App.php
✓ Crear core/Layout.php, core/Helpers.php (core/Rbac.php ya existía de FASE 0)
✓ Punto de entrada erp.php (coexiste con index.php legacy)
✓ Activar .htaccess con URLs limpias (/modulo/vista → erp.php?m=&v=)
✓ Mover módulos existentes a modules/ (module.php + views/index.php stubs para 11 módulos)
FASE 2 SYSTEM_MODULES dinámica (2 días) ✅ COMPLETADA
✓ Migración 004: tabla system_modules (con INSERT IGNORE, oleada, sort_order)
✓ core/ModuleRegistry.php: lee BD → module.php → SYSTEM_MODULES (fallback en cascada)
✓ Sidebar lee desde ModuleRegistry en lugar de config.php (dinámico por categoría)
✓ Interfaz /erp.php?m=usuarios&v=modulos (toggle activo + sort_order)
── MÓDULOS NUEVOS ────────────────────────────────────────────────────────────
FASE 3 Turnero MVP — Oleada 1 (3-5 días)
□ Migración 003: tablas turnero_*
□ modules/turnero/module.php + views/ + api/
□ Pantalla kiosko (toma turno, sin login)
□ Pantalla display TV (SSE, sin login)
□ Dashboard admin (llamar, gestionar)
□ Registrar slug turnero en system_modules
FASE 4 Oleada 2 (Registro de Exámenes + futuros)
□ Migración 005: tablas exam_*
□ Catálogo de tipos de examen (CRUD admin)
□ Flujo de recepción: buscar paciente → crear orden → agregar ítems
□ Vista bacteriólogo: lista del día, cambiar estados
□ Impresión de etiquetas (PDF A6)
□ Conectar con lab_pacientes (reutilizar buscador existente)
□ Facturación, Inventario, CRM, Portal Paciente…
□ API pública con tokens (para integraciones)
□ App móvil (portal enfermero actual → Progressive Web App)
────────────────────────────────────────────────────────────────────────────────
11. CONVENCIONES TÉCNICAS A SEGUIR
────────────────────────────────────────────────────────────────────────────────
NOMENCLATURA:
• Tablas BD: snake_case, prefijadas por módulo (turnero_, exam_, lab_)
• Archivos PHP: snake_case (save_turno.php, get_examenes.php)
• Clases PHP: PascalCase (TurneroService.php, ExamOrder.php)
• Slugs: siempre lowercase con guiones (turnero, registro-exams)
• API endpoints: REST-ish, verbos en el nombre (get_, save_, delete_)
SEGURIDAD:
• Toda API: requireMethod() + verificar sesión + verificar permiso
• Parámetros: siempre sanitizar y tipificar antes de usar en SQL
• Queries: siempre PDO preparado (ya implementado en Database.php)
• Pantallas sin login (kiosko, display): NUNCA exponer datos sensibles,
solo número de turno y servicio.
• Subida de archivos: misma lógica de /upload.php (validar MIME + ext)
• CSRF: para formularios de mutación, incluir token en sesión
ESTILO DE CÓDIGO:
• Frontend: Bootstrap 5 + Font Awesome 6 (ya en uso, mantener)
• Sin jQuery nuevo; usar fetch() nativo (ya en uso)
• Toasts de notificación: usar patrón ya existente en index.php
• Responsive: mobile-first (portal enfermero se usa desde celular)
API RESPONSE FORMAT (ya establecido, mantener):
Éxito: { "ok": true, "data": {...}, "message": "..." }
Error: { "ok": false, "error": "...", "code": 4XX }
────────────────────────────────────────────────────────────────────────────────
12. DECISIONES CLAVE A CONFIRMAR CON EL CLIENTE
────────────────────────────────────────────────────────────────────────────────
1. ¿El turnero es para UNA sede o múltiples sedes?
(Multi-sede requiere añadir sede_id a las tablas)
2. ¿Facturación electrónica (DIAN) es obligatorio desde el inicio
o puede dejarse para Oleada 2?
3. ¿El portal de entrega de resultados es para los pacientes directamente
(requiere login/token para pacientes) o solo descarga interna?
4. ¿Se quiere app móvil nativa o es suficiente con PWA/responsive?
5. ¿Los exámenes tienen que integrar con algún analizador automático
(interfaz LIS) o el resultado se digita manual?
6. ¿El turno se puede tomar ANTES de llegar (turno virtual por WhatsApp)?
Esto conecta el módulo Turnero con el Bot.
7. ¿El sistema será multi-tenant (varios laboratorios/clientes en el mismo
servidor) o siempre una instalación por cliente?
────────────────────────────────────────────────────────────────────────────────
13. RESUMEN EJECUTIVO
────────────────────────────────────────────────────────────────────────────────
Lo que TENEMOS es una base sólida:
✓ BD bien estructurada con 34 tablas
✓ RBAC funcional (roles + módulos)
✓ API consistente con helpers reutilizables
✓ Autenticación robusta con bcrypt
✓ Integración WhatsApp activa
✓ Módulos de laboratorio maduros
Lo que HAY QUE CONSTRUIR para el ERP:
→ Estructura de carpetas por módulo (core/ + modules/)
→ Router centralizado y sidebar dinámico
→ RBAC con granularidad de acciones (can_view/create/edit/delete/export)
→ Módulo Turnero — Oleada 1 (3-5 días)
→ SYSTEM_MODULES en BD (en lugar de hardcoded en config.php)
→ Módulo Registro de Exámenes — Oleada 2 (5-7 días, pendiente)
Estrategia: EVOLUCIÓN INCREMENTAL, no reescritura.
El sistema sigue funcionando en producción mientras se construyen
los nuevos módulos en paralelo. Solo se migra lo viejo al nuevo
sistema cuando el nuevo está validado y estable.
================================================================================
Documento preparado por GitHub Copilot — Abril 2026
Próxima revisión: tras confirmar decisiones de la sección 12
================================================================================