# 🏥 Sistema Turnero Inteligente

Flujo completo del proceso — Desde la llegada del paciente hasta la toma de muestras
📋 9 Tablas en BD ⚡ 22 APIs REST 🖥️ 9 Vistas 📡 SSE en Tiempo Real 📱 WhatsApp Integration
👥

## Actores del Sistema

Quiénes intervienen
🧑‍🦽

#### Paciente

Llega al laboratorio, usa el kiosko táctil para obtener su turno, firma consentimientos desde su celular vía WhatsApp.

kiosko.php ver_formulario_enviado.php
👩‍💼

#### Recepcionista

Llama turnos, vincula paciente, selecciona exámenes, registra pago, envía consentimientos y pasa al paciente al área de muestras.

recepcion.php display_recepcion.php
🧑‍⚕️

#### Auxiliar de Muestras

Llama turnos de su estación, verifica consentimientos firmados, inicia atención, toma la muestra y finaliza el turno.

lugar.php display (por lugar)
⚙️

#### Administrador

Configura lugares, exámenes, prioridades, plantillas WhatsApp. Monitorea dashboard e historial. Exporta reportes CSV.

configuracion.php dashboard.php historial.php
📺

#### Pantallas TV

Muestran en tiempo real el turno en atención y la cola de espera. Se actualizan vía SSE (Server-Sent Events).

display_global.php display.php
🎫

## Sistema de Prioridades

Motor de cola

El motor de cola ordena los turnos por peso de prioridad (menor = más urgente) y luego por orden de llegada (FIFO). Las prioridades son configurables desde el panel de administración.

Código | Prioridad | Color | Icono | Descripción | Peso
--- | --- | --- | --- | --- | ---
A | Niños | `#ef4444` | 👶 fa-child | Pacientes menores de edad | 1 (mayor prioridad)
B | Embarazadas | `#f97316` | 💗 fa-heart | Mujeres en estado de embarazo | 2
C | Adulto mayor | `#eab308` | 🧓 fa-person-cane | Mayores de 60 años | 3
D | Discapacidad | `#8b5cf6` | ♿ fa-wheelchair | Personas con discapacidad | 4
E | Paciente general | `#3b82f6` | 🧑 fa-user | Atención general | 5
F | Muestra pendiente | `#6b7280` | 🧪 fa-vial | Entrega de muestra tomada previamente | 6 (menor prioridad)

#### 💡 Ejemplo de correlativos independientes y ordenamiento

Cada prioridad tiene su propia secuencia:
A-001 (niño, llegó 8:00) → E-001 (general, llegó 8:05) → A-002 (niño, llegó 8:10) → E-002 (general, llegó 8:15)
El motor de cola ordena por peso de prioridad y luego por número correlativo: primero llama a A-001 (prioridad A, peso 1), luego A-002, después E-001, y finalmente E-002.

🔄

## Máquina de Estados del Turno

Lifecycle

### Estados posibles de un turno

⏳espera
🛎️en_recepcion
🚶en_espera_lugar
🔬en_servicio
✅finalizado
🚫ausente
❌cancelado

### Transiciones permitidas

espera → en_recepcion (recepcionista llama)
en_recepcion → en_espera_lugar (pasa a estación)
en_espera_lugar → en_servicio (⚠️ requiere consentimientos OK)
en_servicio → finalizado (muestra tomada)
en_servicio → en_espera_lugar (regresar a cola)
cualquier estado → ausente / cancelado

#### 🔒 Bloqueo de consentimientos

La transición en_espera_lugar → en_servicio está bloqueada si el turno tiene consentimientos en estado `pendiente`, `enviado` o `visto`. Todos deben estar en `firmado` o `rechazado` antes de poder iniciar la atención. Esto se valida en `cambiar_estado.php`.

📋

## Flujo Completo — Paso a Paso

Proceso end-to-end
1

### 🖥️ Kiosko — El paciente obtiene su turno

El paciente llega al laboratorio y se acerca al kiosko táctil (tablet o pantalla touch). No requiere login — es una pantalla pública siempre activa.

Paso 1
Selecciona su tipo de atención (A-F) tocando el botón correspondiente
Paso 2
Ingresa su número de cédula y opcionalmente su WhatsApp
Paso 3
El sistema genera un código con correlativo independiente por prioridad (ej: "A-001", "A-002", "B-001", "E-001")
Resultado
Turno en estado espera — El paciente se sienta a esperar
📄 kiosko.php ⚡ create_turno.php

#### 🔐 Seguridad del kiosko

El kiosko nunca expone datos de otros pacientes. Solo muestra el código del turno recién creado y su posición en cola. El campo `paciente_nombre` almacena la cédula digitada (no el nombre real). El nombre real se vincula después en recepción.

2

### 🛎️ Recepción — Vinculación y solicitud

El recepcionista ve la cola de turnos en espera en su pantalla. Cuando decide atender un turno, lo llama y se abre la ficha de atención.

Llamar turno
Clic en "Llamar siguiente" o en la campana de un turno específico de la cola
Estado cambia a
en_recepcion — El turno aparece en la pantalla TV de recepción
Buscar paciente
Busca por nombre o documento en la base de datos de pacientes (reutiliza lab_pacientes)
Seleccionar exámenes
Marca los exámenes solicitados de un catálogo agrupado por categoría
Lugar destino
Selecciona a qué estación de toma de muestras enviar al paciente
Registro de pago
Monto + método (efectivo, transferencia, tarjeta, EPS, cortesía)
📄 recepcion.php ⚡ llamar_turno.php ⚡ create_solicitud.php ⚡ get_cola.php

#### 📝 Guardar solicitud

Al hacer clic en "Guardar solicitud", se crea la `turnero_solicitud` con los exámenes (`turnero_examen_items`), el pago y el lugar destino. El sistema calcula automáticamente qué consentimientos informados se requieren basándose en los exámenes seleccionados y el lugar de destino.

3

### 📱 Consentimientos Informados — Firma digital

Una vez guardada la solicitud, aparecen los consentimientos requeridos. El recepcionista puede enviarlos por WhatsApp o hacer que el paciente firme presencialmente en una tablet.

Cálculo automático
El sistema cruza `exam_tipo_consentimientos` + `turnero_lugar_consentimientos` para determinar qué formularios aplica
Token UUID
Cada consentimiento genera un token único (ej: "a3f2-4b1c-...") para acceso seguro sin login
Envío por WhatsApp
Se envía mensaje con template "consentimiento_turno" + enlace de firma al celular del paciente
Firma presencial
Botón "Firmar" abre modal con iframe del formulario — el paciente firma en la tablet del puesto
⚡ send_consentimiento.php ⚡ get_consentimientos.php 📄 ver_formulario_enviado.php

#### 📊 Estados del consentimiento

● pendiente → creado pero no enviado | ● enviado → WhatsApp enviado | ● visto → paciente abrió el enlace | ● firmado → paciente firmó | ● rechazado → paciente rechazó

#### 🔄 Deduplicación inteligente

Si varios exámenes requieren el mismo formulario de consentimiento, el sistema lo detecta y envía un solo enlace de firma. También si el paciente ya firmó ese consentimiento en una visita anterior, se reutiliza el token existente.

4

### ➡️ Pasar a Lugar — El paciente se desplaza

El recepcionista hace clic en "Pasar a lugar". El turno cambia de estado y aparece en la cola de la estación de toma de muestras asignada.

Estado cambia a
en_espera_lugar
Se asigna
`lugar_destino_id` = la estación seleccionada (ej: "Toma de Muestras 1")
Pantalla TV
El display global muestra el anuncio: "A-001, pase a Toma de Muestras 1"
Recepción
La ficha se cierra y el recepcionista puede llamar al siguiente turno
⚡ cambiar_estado.php
5

### 🔬 Toma de Muestras — Proceso completo

El auxiliar de la estación de muestras ve en su pantalla la cola de pacientes asignados a su lugar. Este es el proceso detallado de toma de muestras:

5a

#### Llamar paciente

El auxiliar hace clic en "Llamar siguiente". El motor de cola selecciona el turno con mayor prioridad (menor peso) y mayor tiempo de espera. El turno pasa a estado en_servicio.

⚠️ Bloqueo: Si hay consentimientos sin firmar, el botón "Iniciar atención" está deshabilitado y se muestra un banner rojo indicando cuántos consentimientos faltan.

5b

#### Verificar ficha del paciente

Se abre la ficha con toda la información:

- Datos del paciente: nombre, documento, fecha de nacimiento, celular
- Exámenes solicitados: lista con código y nombre de cada examen
- Consentimientos: estado de cada uno (firmado/rechazado/pendiente)

5c

#### Resolver consentimientos pendientes (si los hay)

Si algún consentimiento aún no está firmado, el auxiliar puede:

- "Firmar aquí": Abre un modal con el formulario — el paciente firma en la tablet del puesto
- "WA": Reenvía el enlace de firma por WhatsApp al celular del paciente
- Polling automático: Cada 5 segundos el sistema verifica si el paciente firmó desde su celular

5d

#### Iniciar atención

Cuando todos los consentimientos están OK (firmados o rechazados), el botón "Iniciar atención" se habilita. El auxiliar hace clic y el estado cambia a en_servicio. Se registra `inicio_lugar_at`.

🧪 En este momento el auxiliar toma la muestra de sangre/orina/etc. al paciente.

5e

#### Finalizar atención

El auxiliar hace clic en "Finalizar". El turno pasa a estado finalizado. Se registra `fin_lugar_at`. La ficha se cierra y el auxiliar puede llamar al siguiente paciente.

⚠️

#### Casos especiales

"Ausente": El paciente no se presentó → estado ausente
"Regresar a cola": El paciente necesita esperar (ej: ayuno insuficiente) → vuelve a en_espera_lugar

📄 lugar.php ⚡ llamar_turno.php ⚡ cambiar_estado.php ⚡ get_consentimientos.php
6

### 📺 Pantallas TV — Información en tiempo real

Durante todo el proceso, las pantallas TV muestran el estado actualizado del sistema. Hay 3 tipos de display:

Display Global
Vista general con todas las áreas: recepción + todas las estaciones de muestras. Tema oscuro. Anuncio animado cuando se llama un turno. Video de fondo configurable.
Display Recepción
Muestra el turno activo en un escritorio de recepción específico + cola de espera. Se actualiza vía SSE.
Display por Lugar
Muestra el turno activo en una estación de muestras específica + cola de ese lugar.
Actualización
SSE (Server-Sent Events) cada 2s si hay cambios + polling de respaldo cada 4s. Beep + voz sintética al llamar turno.
📄 display_global.php 📄 display.php 📄 display_recepcion.php ⚡ sse_turno.php ⚡ get_cola.php ⚡ get_display_global.php
7

### ⚙️ Administración — Monitoreo y configuración

El administrador tiene acceso a vistas de control y configuración del sistema completo.

Dashboard
KPIs del día: total turnos, atendidos, en espera, ausentes, tiempo promedio de espera y servicio. Desglose por prioridad y lugar. Auto-refresh cada 30s.
Historial
Consulta multi-día con filtros por estado, lugar, prioridad y texto libre. Paginación. Detalle expandible con todos los timestamps.
Configuración
CRUD de lugares (recepción/muestras), tipos de examen, prioridades, sesiones, WhatsApp (template Meta), video TV.
Exportar
CSV con todos los turnos, timestamps, exámenes, pagos y estado de consentimientos.
📄 dashboard.php 📄 historial.php 📄 configuracion.php ⚡ get_dashboard.php ⚡ export_csv.php ⚡ get_historial.php ⚡ export_historial.php
📡

## Diagrama de Secuencia — APIs y Datos

Comunicaciones

# | Actor / Vista | → API | Acción en BD | Resultado | Notifica
--- | --- | --- | --- | --- | ---
1 | Kiosko | POST create_turno.php | INSERT turnero_turnos (estado=espera, correlativo por prioridad) | Código "A-001" + posición cola | SSE notify
2 | Recepción | POST llamar_turno.php | UPDATE estado=en_recepcion + timestamps | Turno con datos completos | SSE notify
3 | Recepción | POST create_solicitud.php | INSERT turnero_solicitudes + turnero_examen_items | Solicitud + consentimientos requeridos | SSE notify
4 | Recepción | POST send_consentimiento.php | INSERT/UPDATE turnero_consentimientos + tokens UUID | Estado → enviado | WhatsApp
5 | Paciente (celular) | GET ver_formulario_enviado.php?token=... | UPDATE turnero_consentimientos estado=firmado | Formulario firmado + evidencia | postMessage
6 | Recepción | POST cambiar_estado.php → en_espera_lugar | UPDATE estado + lugar_destino_id | Turno pasa a cola del lugar | SSE notify
7 | Lugar (auxiliar) | POST llamar_turno.php (area=lugar) | UPDATE estado=en_servicio + timestamps | Turno con ficha completa | SSE notify
8 | Lugar (auxiliar) | GET get_consentimientos.php (polling 5s) | SELECT turnero_consentimientos + paciente + exámenes | Verifica si todos están firmados | —
9 | Lugar (auxiliar) | POST cambiar_estado.php → finalizado | UPDATE estado + fin_lugar_at | Turno completado | SSE notify
10 | Pantallas TV | GET sse_turno.php (conexión persistente) | SELECT cola + activo (cada 2s o por cambio) | Render en tiempo real + audio + voz | —

🗄️

## Tablas de Base de Datos

9 tablas del turnero

#### 📋 turnero_turnos

Tabla principal. Cada fila = un turno. Almacena: código, número, prioridad, estado, timestamps de cada fase (creado, llamado recepción, inicio/fin recepción, llamado lugar, inicio/fin lugar), paciente_nombre (cédula del kiosko), paciente_cel.

#### 📅 turnero_sesiones

Una por día. Controla apertura/cierre del sistema. Almacena: fecha, abierto_por, inicio_at, fin_at, sse_ping_at (para notificaciones SSE).

#### 📝 turnero_solicitudes

Vincula un turno con un paciente real, un lugar destino y los datos de pago. Se crea en recepción después de llamar el turno.

#### 🧪 turnero_examen_items

Relación N:M entre solicitud y tipos de examen. Cada fila = un examen solicitado para esa solicitud.

#### ✍️ turnero_consentimientos

Cada consentimiento requerido por turno. Almacena: token UUID, estado (pendiente/enviado/visto/firmado/rechazado), timestamps.

#### 📍 turnero_lugares

Catálogo de estaciones: recepción, toma de muestras 1, 2, etc. Campos: nombre, tipo (recepcion/muestras), descripción, sort_order, activo.

#### 🎫 turnero_prioridades

Código (A-F), nombre, color, icono, descripción, orden_peso. Configurable desde el panel admin.

#### 🧪 exam_tipos

Catálogo de tipos de examen del laboratorio. Código, nombre, categoría. Se usa en la ficha de recepción.

#### 🔗 Tablas de relación

exam_tipo_consentimientos: qué formularios requiere cada tipo de examen.
turnero_lugar_consentimientos: qué formularios requiere cada lugar/servicio.

🗺️

## Resumen Visual del Flujo

Big picture
🖥️
KIOSKO
Paciente obtiene
turno A-001
estado: espera
(correlativo por prioridad)
→
🛎️
RECEPCIÓN
Vincula paciente
exámenes + pago
estado: en_recepcion
→
📱
CONSENTIM.
Envío WhatsApp
firma digital
tokens UUID
→
🚶
TRÁNSITO
Paciente se
desplaza
estado: en_espera_lugar
→
🔬
MUESTRAS
Verifica + toma
muestra
estado: en_servicio
→
✅
FINALIZADO
Muestra tomada
turno completo
estado: finalizado
📡 SSE (Server-Sent Events) — Cada cambio de estado notifica a todas las pantallas TV en tiempo real (beep + voz sintética + animación)