Files
whatsapp/DOCUMENTACION_LAB.md

25 KiB

Documentación del Sistema de Laboratorio

Sistema: Laboratorio Clínico — Módulos de Agendamiento y Formularios
Última actualización: 27/03/2026


Tabla de contenidos

  1. Módulo de Agendamiento (Domicilios)
  2. Módulo de Formularios

1. Módulo de Agendamiento (Domicilios)

¿Qué es?

El módulo de agendamiento gestiona los servicios de toma de muestras a domicilio. Permite crear, asignar, seguir y completar visitas médicas domiciliarias. Los administradores gestionan la agenda desde lab_domicilios.php; los enfermeros gestionan su propia agenda desde enfermero_portal.php.


Archivos involucrados

Archivo Descripción
lab_domicilios.php Vista principal del admin — tabla con filtros, detalle del domicilio, formularios recibidos, exportar CSV
enfermero_portal.php Portal exclusivo del enfermero — su agenda personal del día, ordenada por hora, con tarjetas colapsables
lab_enfermeras.php CRUD del personal de enfermería
classes/lab/Domicilio.php Clase ORM — crear, editar, cambiar estado, estadísticas
classes/lab/Enfermera.php Clase ORM — CRUD, agenda por enfermero, carga de trabajo
classes/lab/Asignacion.php Clase ORM — asignar / reasignar / liberar enfermero a domicilio
api/lab/get_domicilios.php GET — lista de domicilios con filtros y estadísticas del día
api/lab/save_domicilio.php POST — crear, actualizar o cambiar estado
api/lab/update_domicilio_enfermero.php POST — el enfermero avanza el estado desde su portal
api/lab/my_agenda.php GET — agenda del enfermero actualmente autenticado
api/lab/save_asignacion.php POST — asignar o reasignar enfermero
api/lab/get_asignaciones.php GET — asignaciones por fecha
api/lab/registrar_pago.php POST — registrar pago de un domicilio
api/lab/save_servicio_extra.php POST — agregar servicio realizado durante la visita
api/lab/get_notas_domicilio.php GET — notas clínicas y libres del domicilio
api/lab/upload_nota_imagen.php POST — subir imagen adjunta a una nota
api/lab/crear_desde_whatsapp.php GET/POST — crear paciente u orden desde una conversación de WhatsApp activa

Base de datos

Tabla lab_domicilios

Tabla principal. Cada fila es un servicio a domicilio.

Campo Tipo Descripción
id INT PK Identificador único
paciente_id INT FK Paciente al que se le realiza el servicio
orden_id INT FK NULL Orden médica adjunta (opcional)
direccion TEXT Dirección completa de la visita
ciudad VARCHAR(100) Ciudad
barrio VARCHAR(100) Barrio
indicaciones_dir TEXT Referencias o indicaciones adicionales ("apto 302, tocar campanilla")
fecha_programada DATE Fecha de la visita
hora_programada TIME Hora de la visita
tipo_servicio VARCHAR(100) Tipo de servicio (toma de muestra, etc.)
tipo_cliente ENUM particular / seguro / eps
examenes_solicitados TEXT Lista de exámenes (cuando no hay orden médica)
seguro_nombre VARCHAR Nombre del seguro o EPS
autorizacion VARCHAR Número de autorización
valor_domicilio DECIMAL Valor del servicio
valor_copago DECIMAL Copago a cargo del cliente
copago_laboratorio DECIMAL Copago al laboratorio
pago_estado ENUM pending / pagado / exento
pago_modo ENUM efectivo / transferencia / otro
pago_monto DECIMAL Monto pagado
pago_fecha DATETIME Fecha del pago
pago_notas TEXT Notas sobre el pago
estado ENUM Ver Flujo de estados
motivo_cancelacion TEXT Motivo si fue cancelado (obligatorio)
fecha_reprogramada DATE Nueva fecha si fue reprogramado
hora_llegada TIME Registrada automáticamente al iniciar la visita
hora_salida TIME Registrada automáticamente al completar
observaciones TEXT Observaciones del resultado de la visita
muestras_tomadas TEXT Lista de muestras obtenidas
notas_admin TEXT Notas internas del equipo administrativo
creado_por INT FK Usuario que creó el registro

Tabla lab_enfermeras

Personal de enfermería disponible para asignación.

Campos: id, numero_documento, tipo_documento (CC/CE/TI/PA), nombre_completo, telefono, telefono_alt, email, zona, notas, is_active.

Tabla lab_asignaciones

Asignación de enfermero a domicilio. Máximo un enfermero activo por domicilio (UNIQUE KEY en domicilio_id).

Campos: id, domicilio_id, enfermera_id, asignada_por, estado (asignada / confirmada / liberada / completada), notas.

Tabla lab_servicios_extra

Servicios realizados por el enfermero durante la visita, adicionales a la orden original.

Tipos disponibles: inyeccion, cura, nebulizacion, toma_muestra, tension_arterial, glucometria, otro.

Campos: id, domicilio_id, descripcion, tipo, notas, requiere_pago, valor, realizado_por.

Tabla lab_domicilio_notas

Notas registradas por el enfermero durante la visita.

Dos tipos:

  • clinica: datos de la ficha clínica — antecedentes, medicamentos, acudiente (si el paciente es menor de edad).
  • libre: nota libre con título, cuerpo de texto enriquecido e imagen adjunta.

Campos: id, domicilio_id, enfermera_id, tipo, antecedentes, medicamentos, acudiente_nombre, acudiente_documento, titulo, cuerpo, imagen_path.


Roles y permisos

Rol Acceso
Admin Crear, editar y ver todos los domicilios. Asignar/reasignar enfermeros. Registrar pagos. Exportar Excel. Ver informe completo con notas. Ver agenda de cualquier enfermero usando ?eid=X.
Enfermero Solo ve su propia agenda (enfermero_portal.php). Avanza el estado de sus domicilios asignados. Agrega servicios extra. Registra notas clínicas y libres. Visualiza órdenes médicas adjuntas.

Redirección automática: si el usuario autenticado tiene rol enfermero, lab_domicilios.php lo redirige inmediatamente a enfermero_portal.php.

Los roles se definen en admin_users.role (ENUM admin / enfermero) y admin_users.enfermera_id (FK a lab_enfermeras).


Flujo de estados

[programado]
     │
     │  El enfermero confirma que realizará la visita
     ▼
[confirmado]
     │
     │  El enfermero sale hacia el domicilio
     ▼
[en_camino]
     │
     │  El enfermero llega → hora_llegada se registra automáticamente
     ▼
[en_domicilio]
     │
     │  El enfermero finaliza → hora_salida se registra automáticamente
     ▼
[completado]

Desde cualquier estado:
  → [cancelado]    (requiere motivo_cancelacion como campo obligatorio)
  → [reprogramado] (requiere fecha_reprogramada)

Transiciones permitidas al enfermero (validadas en update_domicilio_enfermero.php):

Estado actual Estados posibles
programado confirmado
confirmado en_camino, cancelado
en_camino en_domicilio, cancelado
en_domicilio completado, cancelado

El admin puede cambiar a cualquier estado directamente, incluyendo cancelar desde cualquier punto.


Funcionalidades

  • Filtros: por fecha, estado, enfermero asignado. Botón "Hoy" para filtro rápido.
  • Resumen del día: conteo de domicilios por estado en la parte superior.
  • Panel de detalle: al hacer clic en un domicilio se abre el panel lateral con toda la información, notas clínicas, notas libres e informe imprimible.
  • Asignar / Reasignar enfermero: modal con lista del personal disponible.
  • Sin asignar: badge con el conteo de domicilios que aún no tienen enfermero.
  • Registrar pago: modal para marcar el cobro con modalidad y monto.
  • Servicios extra: el enfermero los agrega desde su portal durante la visita.
  • Notas del enfermero: ficha clínica con antecedentes, medicamentos, acudiente (si menor) y notas libres con imagen adjunta.
  • Informe de domicilio: vista imprimible del domicilio con datos del paciente, ficha clínica y notas del enfermero.
  • Exportar CSV (Excel): exporta todos los domicilios filtrados, incluyendo las columnas de notas del enfermero (antecedentes, medicamentos, acudiente, notas libres).
  • Formularios recibidos: pestaña dentro de lab_domicilios.php que muestra formularios enviados con filtro por plantilla y estado.
  • Portal del enfermero: tarjetas colapsables ordenadas por hora, separadas en "Activos" y "Finalizados". Permite avanzar estados, agregar notas y ver órdenes.

API Endpoints

Endpoint Método Descripción
api/lab/get_domicilios.php GET Lista con filtros. ?id=X para uno solo con detalle completo.
api/lab/save_domicilio.php POST Crear, editar o cambiar estado. ?solo_estado=true para solo cambiar estado.
api/lab/update_domicilio_enfermero.php POST El enfermero avanza el estado de su domicilio.
api/lab/my_agenda.php GET Agenda del enfermero autenticado con servicios extra.
api/lab/save_asignacion.php POST Asignar o reasignar enfermero a domicilio.
api/lab/get_asignaciones.php GET Asignaciones por fecha.
api/lab/registrar_pago.php POST Registrar pago con monto y modalidad.
api/lab/save_servicio_extra.php POST Agregar servicio realizado durante la visita.
api/lab/get_notas_domicilio.php GET Notas del domicilio (clínicas y libres).
api/lab/upload_nota_imagen.php POST Subir imagen adjunta a una nota libre.
api/lab/crear_desde_whatsapp.php GET/POST Crear paciente u orden desde una conversación de WhatsApp activa.

2. Módulo de Formularios

¿Qué es?

El módulo de formularios permite crear plantillas de documentos (consentimientos, historias clínicas, autorizaciones, encuestas) mediante un builder visual, enviarlas a los pacientes por WhatsApp y recopilar sus respuestas con firma digital. El documento firmado genera un sello de integridad SHA-256 que puede verificarse públicamente.


Archivos involucrados

Archivo Descripción
lab_formularios.php Vista principal — lista de plantillas y registro de envíos
lab_formulario_builder.php Editor visual drag & drop (ventana separada, solo admin)
form_cliente.php Página pública — el paciente llena y firma sin iniciar sesión
ver_formulario_enviado.php Vista del documento firmado — acceso por ID (admin/enfermero) o token (cliente)
verificar_formulario.php Verificación pública de autenticidad por hash SHA-256
classes/lab/Formulario.php Clase ORM — CRUD de plantillas, crear envíos, guardar respuestas, generar hash
api/lab/get_formularios.php GET — lista plantillas o envíos
api/lab/save_formulario.php POST — crear, editar y eliminar plantillas (solo admin)
api/lab/send_formulario.php POST — crear instancia de envío, devolver URL pública y mensaje WhatsApp
api/lab/submit_formulario.php GET/POST — cargar el formulario por token / guardar la respuesta del cliente
api/lab/firmar_profesional.php POST — guardar firma del profesional (requiere sesión activa)

Base de datos

Tabla lab_formularios

Plantillas de documentos creadas desde el builder.

Campo Tipo Descripción
id INT PK Identificador único
nombre VARCHAR(150) Nombre de la plantilla
descripcion TEXT Descripción visible al cliente
categoria ENUM consentimiento / historia_clinica / autorizacion / encuesta / otro
esquema LONGTEXT JSON con el array de campos del formulario
permite_firma TINYINT(1) El formulario tiene sección de firma global
requiere_firma TINYINT(1) La firma global es obligatoria
firma_modos VARCHAR(50) canvas, foto o canvas,foto (separados por coma)
version SMALLINT Se incrementa automáticamente al editar el esquema
is_active TINYINT(1) Soft-delete
creado_por INT FK Usuario que creó la plantilla
doc_encabezado VARCHAR Override del nombre de empresa en el documento
doc_subtitulo VARCHAR Override del subtítulo en el documento
doc_logo_base64 LONGTEXT Override del logo en el documento
doc_color VARCHAR(20) Override del color del encabezado del documento
doc_pie_pagina TEXT Override del pie de página

Tabla lab_form_envios

Cada fila es una instancia enviada a un paciente.

Campo Tipo Descripción
id INT PK Identificador único
formulario_id INT FK Plantilla enviada
paciente_id INT FK NULL Paciente asociado
domicilio_id INT FK NULL Domicilio asociado (opcional)
token CHAR(64) UNIQUE Token público de 64 caracteres hex (acceso sin sesión)
datos_prefilled LONGTEXT JSON con datos pre-llenados al enviar (incluye __paciente.*)
datos_cliente LONGTEXT JSON con las respuestas completadas por el cliente
firma_svg LONGTEXT Firma del paciente (PNG base64 — canvas o foto)
ip_cliente VARCHAR(45) IP del cliente al enviar el formulario
user_agent VARCHAR(512) Navegador del cliente
estado ENUM pendiente / completado / firmado / expirado
enviado_por INT FK Usuario que generó el enlace
enviado_via ENUM whatsapp / email / link
expira_en DATETIME NULL Siempre NULL — el enlace no expira
completado_en DATETIME Fecha y hora en que el cliente completó el formulario
hash_verificacion CHAR(64) Sello de integridad SHA-256 del documento

Roles y permisos

Rol Acceso
Admin Crear, editar y eliminar plantillas desde el builder. Enviar formularios a cualquier paciente. Ver todos los envíos. Ver y descargar el PDF de cualquier formulario.
Enfermero Enviar formularios existentes a sus pacientes. Ver solo sus propios envíos (enviado_por = su user_id). No puede crear ni editar plantillas. Puede firmar como profesional en los formularios que él mismo envió.
Cliente (público) Accede a form_cliente.php?t=TOKEN sin ninguna autenticación. Llena y firma el formulario. Puede volver al mismo enlace en cualquier momento para ver el documento firmado y descargarlo como PDF.

Flujo completo

1. ADMIN crea la plantilla
   ├─ Abre lab_formulario_builder.php (se abre en ventana nueva)
   ├─ Arrastra campos al canvas y los configura
   ├─ Configura el diseño del documento (logo, color, encabezado, pie de página)
   └─ Guarda → POST api/lab/save_formulario.php → lab_formularios

2. ADMIN o ENFERMERO envía el formulario
   ├─ lab_formularios.php → botón "Enviar" → modal
   ├─ Busca y selecciona el paciente
   ├─ Previsualiza los campos que llegarán pre-llenados
   ├─ Selecciona el canal: WhatsApp o "solo link"
   └─ POST api/lab/send_formulario.php
       ├─ Genera token de 64 hex chars: bin2hex(random_bytes(32))
       ├─ Crea fila en lab_form_envios (estado=pendiente, expira_en=NULL)
       └─ Devuelve URL pública y mensaje preformateado para WhatsApp

3. CLIENTE recibe el enlace (por WhatsApp u otro medio)
   ├─ Abre form_cliente.php?t=TOKEN
   ├─ GET api/lab/submit_formulario.php?t=TOKEN → carga datos del formulario
   └─ Si ya fue firmado antes → muestra pantalla de solo lectura con link al PDF

4. CLIENTE llena el formulario
   ├─ Campos "linked" llegan pre-llenados con datos del paciente (readonly si tienen valor)
   ├─ Campos vacíos linked son editables para que el cliente los complete
   ├─ Campos firma_profesional muestran aviso "uso exclusivo del profesional"
   └─ Dibuja su firma (canvas) o adjunta una foto de firma

5. CLIENTE envía
   ├─ POST api/lab/submit_formulario.php
   ├─ Se genera hash SHA-256 (contenido + firma + ID + token + timestamp)
   ├─ Estado → "firmado" (si hay firma) o "completado" (sin firma)
   └─ Pantalla de éxito con hash visible y botón para descargar el PDF

6. PROFESIONAL firma (si el formulario lo requiere)
   ├─ Admin/Enfermero abre ver_formulario_enviado.php?id=X con sesión activa
   ├─ Aparece canvas de firma en la posición del campo firma_profesional
   ├─ Dibuja su firma y hace clic en "Guardar firma"
   └─ POST api/lab/firmar_profesional.php → guarda campo_id_svg en datos_cliente

7. ADMIN/ENFERMERO revisa el resultado
   ├─ lab_formularios.php → pestaña "Envíos" → icono "Ver respuesta"
   └─ ver_formulario_enviado.php?id=X → documento HTML imprimible

8. VERIFICACIÓN pública de integridad
   └─ verificar_formulario.php?h=HASH_SHA256
       ├─ Busca en lab_form_envios.hash_verificacion
       └─ Muestra: nombre del formulario, paciente, fecha, estado y si el sello es válido

Tipos de campos del Builder

Campos de entrada

Tipo Descripción
texto Campo de texto corto de una sola línea
textarea Área de texto largo (varias líneas)
numero Campo numérico
fecha Selector de fecha
hora Selector de hora
select Lista desplegable con opciones configurables
radio Selección única con opciones configurables
checkbox Selección múltiple con opciones configurables
lista_marcable Lista de ítems numerados con checkboxes

Campos de firma

Tipo Descripción
firma Firma del paciente — visible y editable en form_cliente.php
firma_profesional Firma del profesional — bloqueada para el cliente; solo editable desde el panel admin/enfermero

Campos de contenido

Tipo Descripción
separador Separador visual o título de sección
parrafo Bloque de texto estático (pre-formatado o flujo libre)
parrafo_inline Párrafo con marcadores {nombre_completo}, {telefono}, etc. que se convierten en espacios editables si el valor está vacío

Campos vinculados al paciente (tipo: linked)

Se auto-rellenan con los datos del paciente al momento de enviar. Si el valor existe → campo de solo lectura. Si está vacío → el cliente puede completarlo.

linked_key Dato que extrae
nombre_completo Nombre completo del paciente
numero_documento Número de documento
tipo_documento Tipo de documento
fecha_nacimiento Fecha de nacimiento
telefono Teléfono
email Correo electrónico
eps EPS o aseguradora
direccion Dirección

Firma digital

Modos disponibles (configurados en la plantilla mediante firma_modos):

Modo Funcionamiento
canvas El cliente dibuja su firma con el dedo o el mouse. Se captura con canvas.toDataURL('image/png').
foto El cliente sube una imagen desde su cámara o galería (<input accept="image/*" capture="environment">). Se convierte a base64 con FileReader.

Ambos modos pueden estar activos simultáneamente en la misma plantilla.

Firma global vs. firma por campo:

  • Si el esquema no incluye campos tipo firma, se muestra una sección de firma global al pie del formulario.
  • Si el esquema incluye campos firma, cada uno tiene su propio widget canvas independiente en la posición configurada dentro del formulario.

Enlace público y vigencia

  • URL pública: form_cliente.php?t=TOKEN
  • TOKEN: 64 caracteres hexadecimales generados con bin2hex(random_bytes(32)).
  • Sin sesión: el cliente no necesita crear cuenta ni iniciar sesión.
  • Sin vencimiento: la columna expira_en existe en la tabla pero siempre es NULL. El enlace es permanente.
  • Bloqueo por estado: si el formulario ya fue completado o firmado, el enlace muestra la pantalla de solo lectura. No permite modificar la respuesta.
  • Idempotencia: si el cliente reintenta enviar (por error de red, por ejemplo), el sistema devuelve éxito con los datos ya guardados en lugar de crear un duplicado.

PDF y visualización del documento

No se usa ninguna librería de generación de PDF en el backend. El documento es la página ver_formulario_enviado.php con estilos @media print. El usuario puede imprimirla o guardarla como PDF directamente desde el navegador.

Contenido del documento impreso:

  • Encabezado con logo, nombre, subtítulo, datos de contacto y color corporativo
  • Datos del paciente (nombre, documento, fecha de nacimiento, teléfono, EPS)
  • Respuestas del formulario campo por campo, en el orden del esquema
  • Imagen de la firma del paciente
  • Firma del profesional (si fue completada)
  • Sello SHA-256 con link para verificar autenticidad
  • Pie de página con fecha de generación e ID del documento

Formas de acceder al documento:

URL Quién puede acceder
ver_formulario_enviado.php?id=X Admin (cualquier formulario) o Enfermero (solo los que él envió). Requiere sesión.
ver_formulario_enviado.php?t=TOKEN Cliente u cualquier persona con el enlace. Sin sesión. Solo si el estado es firmado o completado.

Sello de integridad SHA-256

Al guardar la respuesta del cliente, el sistema genera un hash SHA-256 que vincula de forma única el contenido del formulario con la firma y el momento en que se completó.

Construcción del hash (en Formulario::guardarRespuesta()):

SHA-256 de:
  JSON de los datos del cliente
  + firma SVG/PNG del paciente
  + ID interno del envío
  + token del enlace
  + timestamp del momento de registro

¿Para qué sirve? Cualquier persona con el hash puede ir a verificar_formulario.php?h=HASH para confirmar que:

  • El documento existe en la base de datos.
  • El nombre del formulario y del paciente.
  • La fecha en que fue completado.
  • El estado actual (firmado / completado).

Si el documento fue alterado, el hash no coincidirá y la verificación fallará.


Firma del profesional

Algunos formularios requieren que un profesional de salud también firme el documento, además del paciente.

Flujo:

  1. Al diseñar la plantilla en el builder se agrega un campo tipo: firma_profesional en la posición deseada.
  2. Cuando el cliente llena el formulario en form_cliente.php, ese campo muestra solo un aviso: "Uso exclusivo del profesional de salud". El cliente no puede interactuar con él.
  3. Una vez que el cliente ha completado y enviado el formulario, el admin o enfermero abre ver_formulario_enviado.php?id=X con sesión activa y verá el canvas de firma en esa posición.
  4. El profesional dibuja su firma y hace clic en "Guardar firma".
  5. La firma se guarda mediante POST a api/lab/firmar_profesional.php.

Validaciones en el servidor:

  • Requiere sesión activa (isUserLoggedIn()).
  • Si el usuario es enfermero, solo puede firmar en formularios que él mismo envió.
  • Valida que el campo_id corresponde a un campo tipo: firma_profesional en el esquema del formulario.
  • Valida que la imagen enviada sea un data URI de imagen válido.

Si el formulario se accede via ?t=TOKEN (cliente público), el canvas no aparece. En su lugar se muestra un aviso "Pendiente de firma del profesional" (solo visible en pantalla, no en el PDF impreso).


API Endpoints

Endpoint Método Autenticación Descripción
api/lab/get_formularios.php GET Sesión Lista plantillas. ?id=X para una sola. ?envios=1 para lista de envíos.
api/lab/save_formulario.php POST Admin Crear, editar o eliminar una plantilla.
api/lab/send_formulario.php POST Admin / Enfermero Crear instancia de envío. Devuelve URL pública y mensaje para WhatsApp.
api/lab/submit_formulario.php GET Público Cargar el formulario por token (sin sesión).
api/lab/submit_formulario.php POST Público Guardar la respuesta y firma del cliente.
api/lab/firmar_profesional.php POST Sesión Guardar la firma del profesional en un campo firma_profesional.

Documentación generada para uso interno del equipo.