21 documentos en cuatro secciones, escritos sobre el comportamiento real del sistema —incluidos los casos que costaron diagnosticar esta semana. Manual de usuario (visible para todos): primeros pasos, recepción, toma de muestras, portal del enfermero y administración. Orientado a tareas concretas, no a describir pantallas. Documentación técnica: índice de módulos, turnero, formularios y firma digital, WhatsApp y bot, domicilios, webhook (migrado de WEBHOOK_ENDPOINTS.md) e inventario de endpoints. Arquitectura: visión general, enrutamiento y registro de módulos, roles y permisos, modelo de datos, integración con WhatsApp, y decisiones tomadas con su deuda técnica asociada. Operación: runbook de incidentes ordenado por síntoma, configuraciones críticas —incluido qué vive en Meta y no en la base— y despliegue. Se documentan explícitamente las trampas conocidas: role/role_id que hay que mantener sincronizados, las columnas can_* que el control de acceso no lee, las URL de plantilla que no se cambian desde el código, y las columnas históricas que quedaron en NULL sin forma de recuperarlas. README_DOCS.md apunta al módulo y explica cómo agregar páginas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.8 KiB
Módulo Turnero
El módulo más grande del sistema: 12 vistas y unos 70 endpoints. Gestiona la atención presencial completa.
Vistas
| Vista | Para quién | Qué hace |
|---|---|---|
dashboard |
Admin, supervisor | Métricas del día, facturación, asistente LIA |
historial |
Admin, supervisor | Turnos de varios días, filtros, exportación |
bandeja |
Bacteriólogo, admin | Turnos del día con su detalle completo |
recepcion |
Recepcionista | Atención en el mostrador |
lugar |
Bacteriólogo | Estación de toma de muestras |
kiosko |
Público | El paciente saca su turno |
display_global |
Público | Pantalla de TV de la sala |
verificar_paciente |
Recepción | Consulta rápida de una ficha |
chat |
Recepción | Conversación de WhatsApp del turnero |
configuracion |
Admin | Lugares, dispositivos, plantillas, pantalla de TV |
kiosko y display_global son las únicas rutas públicas del sistema (core/Router.php): no hay quién inicie sesión en un televisor ni en el tótem de la entrada.
Menú dinámico
modules/turnero/module.php no devuelve una lista fija: la arma según el rol y la IP del equipo.
recepcionista → chat, verificar paciente, TV, y su escritorio
bacteriólogo → bandeja y su estación
admin → todo
Si el equipo está en turnero_dispositivos (por IP o por cookie turnero_token), el usuario ve solo su puesto. Si no, los ve todos. Evita que alguien atienda desde el escritorio equivocado.
Modelo de datos
turnero_sesiones un día de operación
└── turnero_turnos código, estado, tiempos, prioridad
├── turnero_solicitudes qué se hace y cuánto se cobró
│ ├── turnero_examen_items
│ └── turnero_muestras
├── turnero_consentimientos
└── turnero_comentarios
Estados
espera → en_recepcion → en_espera_lugar → en_servicio → finalizado
ausente / cancelado
Solo finalizado cuenta como facturación real.
Consentimientos
Se crean automáticamente desde dos fuentes que se acumulan:
| Fuente | Tabla |
|---|---|
| Por examen | exam_tipo_consentimientos |
| Por estación destino | turnero_lugar_consentimientos |
get_consentimientos.php los autocrea si faltan y calcula el estado de cada uno.
En visitas de solo entrega de muestras no aplican los formularios por examen (no hay exámenes), pero sí los de estación. Por eso F-LAB-08 se exige igual.
Tomas prolongadas
El formulario F-LAB-28 cubre exámenes seriados. La lógica está repartida entre ver_formulario_enviado.php (render) y modules/turnero/api/guardar_toma.php (guardado).
- El esquema trae secciones para todos los exámenes posibles; se muestran solo las del examen marcado, mediante la
condicionde cada separador. _tomas_configendatos_respuestasguarda qué ciclos se configuraron para ese paciente.- Cada firma se guarda en su propio campo (
_tm00_f,_tm30_f, …) junto con la hora y la identidad de quien firmó, resuelta en el servidor desde la sesión. - Al firmar, el endpoint calcula cuándo toca la siguiente toma y actualiza
siguiente_toma_at.
La identidad se resuelve en el servidor, no se acepta del cliente: cada toma puede firmarla un profesional distinto y esa es la única fuente confiable. Las firmas anteriores al 3 de agosto de 2026 no tienen ese dato y no es recuperable.
Muestras entre visitas
Una muestra que queda pendiente o rechazada reaparece cuando el paciente vuelve, con la bandera es_pendiente_anterior y los exámenes de la orden original.
Al recibirla, turnero_muestras.recibida_en_turno_id registra en qué turno se completó. Historial y bandeja usan ese dato para enlazar ambos turnos en los dos sentidos.
El turno original no se modifica: sigue finalizado. Solo se agrega la trazabilidad.
LIA
api/ai_chat.php — asistente sobre Gemini Flash.
| Aspecto | Detalle |
|---|---|
| Contexto | Se arma en cada llamada con hasta 60 turnos del día y sus detalles |
| Historial | Los últimos intercambios se envían para que entienda preguntas de seguimiento |
| Tope de salida | maxOutputTokens; si Gemini corta, se avisa con finishReason |
| Presupuesto | lab_config.lia_tokens_usados contra LIA_TOKENS_MAX |
Se contabiliza totalTokenCount, que incluye el contexto de entrada. Como el contexto va completo en cada pregunta, el gasto por consulta es alto aunque la respuesta sea breve.
Endpoints propios
Los del turnero usan api/_helpers.php, que provee db(), inputJson(), jsonOk(), jsonError(), adminId(), requireTurnero() y notificarSSE().
notificarSSE() avisa a las pantallas conectadas para que se refresquen sin recargar.