diff --git a/DOCUMENTACION_LAB.md b/DOCUMENTACION_LAB.md index 1bc59de..800afc1 100644 --- a/DOCUMENTACION_LAB.md +++ b/DOCUMENTACION_LAB.md @@ -1,522 +1,9 @@ -# Documentación del Sistema de Laboratorio +# Obsoleto -> **Sistema**: Laboratorio Clínico — Módulos de Agendamiento y Formularios -> **Última actualización**: 27/03/2026 +Este documento quedó desactualizado y se conserva solo por historial de git. ---- +La documentación vigente está **dentro del sistema**, en el módulo Soporte: -## Tabla de contenidos + /erp.php?m=soporte&v=documentacion -1. [Módulo de Agendamiento (Domicilios)](#1-módulo-de-agendamiento-domicilios) - - [¿Qué es?](#qué-es) - - [Archivos involucrados](#archivos-involucrados) - - [Base de datos](#base-de-datos) - - [Roles y permisos](#roles-y-permisos) - - [Flujo de estados](#flujo-de-estados) - - [Funcionalidades](#funcionalidades) - - [API Endpoints](#api-endpoints) -2. [Módulo de Formularios](#2-módulo-de-formularios) - - [¿Qué es?](#qué-es-1) - - [Archivos involucrados](#archivos-involucrados-1) - - [Base de datos](#base-de-datos-1) - - [Roles y permisos](#roles-y-permisos-1) - - [Flujo completo](#flujo-completo) - - [Tipos de campos del Builder](#tipos-de-campos-del-builder) - - [Firma digital](#firma-digital) - - [Enlace público y vigencia](#enlace-público-y-vigencia) - - [PDF y visualización del documento](#pdf-y-visualización-del-documento) - - [Sello de integridad SHA-256](#sello-de-integridad-sha-256) - - [Firma del profesional](#firma-del-profesional) - - [API Endpoints](#api-endpoints-1) - ---- - -## 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](#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 (``). 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.* +Ver `README_DOCS.md` para saber cómo se organiza y cómo agregar páginas. diff --git a/README_LAB.md b/README_LAB.md index fce6d1b..800afc1 100644 --- a/README_LAB.md +++ b/README_LAB.md @@ -1,129 +1,9 @@ -# Módulo Administrativo — Laboratorio Clínico +# Obsoleto -Módulo add-on para el sistema de chatbot WhatsApp que permite gestionar órdenes médicas recibidas como imágenes, domicilios, enfermeras y pacientes. +Este documento quedó desactualizado y se conserva solo por historial de git. ---- +La documentación vigente está **dentro del sistema**, en el módulo Soporte: -## Instalación + /erp.php?m=soporte&v=documentacion -### 1. Ejecutar migraciones de base de datos - -```bash -php migrations/20260302_lab_run_migrations.php -``` - -Crea 7 tablas nuevas sin modificar las existentes: -- `lab_pacientes` -- `lab_enfermeras` -- `lab_ordenes_medicas` -- `lab_domicilios` -- `lab_asignaciones` -- `lab_autorizaciones` -- `lab_actividad_admin` - -Para deshacer: -```bash -php migrations/20260302_lab_run_migrations.php --rollback -``` - -### 2. Verificar instalación - -Accede desde el navegador (con sesión admin activa): -``` -https://tu-servidor/lab_status.php -``` - -O desde CLI: -```bash -php lab_status.php -``` - ---- - -## Archivos del módulo - -### Vistas PHP -| Archivo | Descripción | -|---|---| -| `lab_dashboard.php` | Panel principal con estadísticas en tiempo real | -| `lab_ordenes.php` | Gestión de órdenes médicas (estados, imágenes, historial) | -| `lab_pacientes.php` | CRUD de pacientes, vinculación con usuarios WhatsApp | -| `lab_domicilios.php` | Agenda de domicilios y asignación de enfermeras | -| `lab_enfermeras.php` | CRUD de enfermeras y visualización de agenda diaria | -| `lab_reportes.php` | Trazabilidad, log de actividad, exportación CSV | -| `lab_status.php` | Verificador de estado del módulo | - -### Clases (models) -Ubicadas en `classes/lab/`: -- `ActividadAdmin.php` — Base de trazabilidad -- `Paciente.php` — Modelo de pacientes -- `Enfermera.php` — Modelo de enfermeras -- `OrdenMedica.php` — Modelo de órdenes médicas con flujo de estados -- `Domicilio.php` — Modelo de domicilios con flujo de estados -- `Asignacion.php` — Modelo de asignaciones enfermera ↔ domicilio - -### API REST -Ubicados en `api/lab/`: -| Endpoint | Método | Descripción | -|---|---|---| -| `get_pacientes.php` | GET | Lista paginada de pacientes | -| `save_paciente.php` | POST | Crear/actualizar paciente | -| `get_ordenes.php` | GET | Lista/detalle de órdenes | -| `save_orden.php` | POST | Crear/actualizar orden | -| `autorizar_orden.php` | POST | Cambiar estado de una orden | -| `get_domicilios.php` | GET | Lista/detalle de domicilios | -| `save_domicilio.php` | POST | Crear/actualizar domicilio | -| `get_enfermeras.php` | GET | Lista de enfermeras + agenda | -| `save_enfermera.php` | POST | Crear/actualizar enfermera | -| `get_asignaciones.php` | GET | Asignaciones por fecha | -| `save_asignacion.php` | POST | Asignar/liberar/completar enfermera | -| `get_actividad.php` | GET | Log de actividad con filtros | -| `get_stats.php` | GET | Estadísticas para dashboard | -| `crear_desde_whatsapp.php` | GET/POST | Crear orden desde conversación activa | - ---- - -## Flujos de estado - -### Órdenes médicas -``` -pendiente → en_revision → autorizada → en_domicilio → completada - ↘ rechazada -``` - -### Domicilios -``` -programado → confirmado → en_camino → en_domicilio → completado - ↘ cancelado - ↘ reprogramado -``` - ---- - -## Integración con el chatbot - -En `conversations.php`, los mensajes de imagen entrantes tienen un botón **** (verde) en las acciones del mensaje. Al hacer click: - -1. Se abre un modal con la imagen adjunta -2. El operador busca o selecciona un paciente (o usa el contacto de la conversación) -3. Completa datos opcionales (médico, exámenes, ayuno) -4. Se crea la orden en estado `pendiente` - ---- - -## Exportaciones CSV - -Disponibles desde `lab_reportes.php`: -- **Órdenes médicas** del período — incluye estado, médico, exámenes -- **Domicilios** del período — incluye enfermera asignada, dirección, estado -- **Pacientes** — catálogo completo con total de órdenes - ---- - -## Requisitos - -- PHP 8.2+ -- MariaDB 10.11+ (o MySQL 8+) -- Bootstrap 5.3 (ya incluido en el sistema) -- Font Awesome 6.4 (ya incluido en el sistema) -- `uploads/media/` con permisos de escritura (755/775) +Ver `README_DOCS.md` para saber cómo se organiza y cómo agregar páginas. diff --git a/WEBHOOK_ENDPOINTS.md b/WEBHOOK_ENDPOINTS.md deleted file mode 100644 index 4e3cf4e..0000000 --- a/WEBHOOK_ENDPOINTS.md +++ /dev/null @@ -1,163 +0,0 @@ -# Webhook WhatsApp — Endpoints y Características - -## Endpoint principal - -``` -URL: /api/webhook.php -``` - ---- - -## GET — Verificación de webhook - -``` -GET /api/webhook.php?hub.mode=subscribe&hub.verify_token=TOKEN&hub.challenge=CHALLENGE -``` - -### Parámetros que envía Meta -| Parámetro | Valor esperado | -|---|---| -| `hub.mode` | `subscribe` | -| `hub.verify_token` | El token configurado en `system_config.webhook_verify_token` | -| `hub.challenge` | Número aleatorio que debe devolverse tal cual | - -### ⚠️ Bug conocido -El código lee `$_GET['hub_verify_token']` (con guión bajo), pero PHP convierte los puntos a guiones bajos automáticamente al parsear `$_GET`, por lo que **funciona correctamente**. - -### Respuesta exitosa -``` -HTTP 200 -Body: {challenge} -``` - -### Respuesta fallida -``` -HTTP 403 -Body: {"error":"Token de verificación inválido"} -``` - ---- - -## POST — Recepción de eventos - -``` -POST /api/webhook.php -Content-Type: application/json -``` - -### Estructura del payload esperado (Meta Cloud API) - -```json -{ - "object": "whatsapp_business_account", - "entry": [{ - "id": "WABA_ID", - "changes": [{ - "field": "messages", - "value": { - "messaging_product": "whatsapp", - "metadata": { - "phone_number_id": "PHONE_NUMBER_ID" - }, - "contacts": [{ - "wa_id": "573001234567", - "profile": { "name": "Nombre Contacto" } - }], - "messages": [{ - "from": "573001234567", - "id": "wamid.XXX", - "timestamp": "1234567890", - "type": "text", - "text": { "body": "Hola" } - }] - } - }] - }] -} -``` - -### Tipos de mensaje soportados -| `type` | Descripción | -|---|---| -| `text` | Texto plano | -| `image` | Imagen (con caption opcional) | -| `audio` | Audio / nota de voz | -| `video` | Video | -| `document` | Documento / PDF | -| `sticker` | Sticker | -| `reaction` | Reacción emoji a otro mensaje | -| `interactive` | Respuesta de lista o botón | - -### El campo `field` del change puede ser -- `messages` → mensajes entrantes y estados -- `conversations` → alias aceptado también - -### Eventos de estado (statuses) -```json -"statuses": [{ - "id": "wamid.XXX", - "status": "sent|delivered|read|failed", - "recipient_id": "573001234567" -}] -``` - -### Respuesta exitosa -``` -HTTP 200 -Body: {"status":"success"} -``` - ---- - -## Configuración necesaria en `system_config` (BD) - -| config_key | Descripción | -|---|---| -| `whatsapp_token` | Access Token de Meta | -| `whatsapp_phone_number_id` | Phone Number ID de la línea | -| `webhook_verify_token` | Token de verificación del webhook | -| `whatsapp_api_url` | `https://graph.facebook.com/v22.0/` | - ---- - -## Variables de entorno equivalentes (`.env`) - -```env -WHATSAPP_TOKEN= -WHATSAPP_PHONE_NUMBER_ID= -WEBHOOK_VERIFY_TOKEN= -WHATSAPP_API_URL=https://graph.facebook.com/v22.0/ -DB_HOST= -DB_PORT=3306 -DB_NAME= -DB_USER= -DB_PASS= -``` - ---- - -## Tablas BD que usa el webhook - -| Tabla | Uso | -|---|---| -| `users` | Crea o busca usuario por `phone_number` | -| `conversations` | Guarda cada mensaje (deduplicado por `message_id`) | -| `webhook_logs` | Registra el payload crudo de cada POST | -| `notifications` | Crea aviso de nuevo mensaje entrante | -| `media_queue` | Encola media que no pudo descargarse en el momento | -| `system_config` | Lee tokens y configuración | - ---- - -## Seguridad — pendiente de implementar - -- No valida la firma `X-Hub-Signature-256` en el POST. -- Se recomienda agregar antes de procesar: -```php -$signature = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; -$expected = 'sha256=' . hash_hmac('sha256', $input, APP_SECRET); -if (!hash_equals($expected, $signature)) { - http_response_code(401); - exit; -} -``` diff --git a/modules/lab_examenes/api/get.php b/modules/lab_examenes/api/get.php index da063f9..5435789 100644 --- a/modules/lab_examenes/api/get.php +++ b/modules/lab_examenes/api/get.php @@ -1,4 +1,7 @@ false,'error'=>'No autorizado']); exit; } diff --git a/modules/medicos/api/list.php b/modules/medicos/api/list.php index c3b5c5c..15438e7 100644 --- a/modules/medicos/api/list.php +++ b/modules/medicos/api/list.php @@ -1,4 +1,7 @@ false,'error'=>'No autorizado']); exit; } diff --git a/modules/medicos/api/save.php b/modules/medicos/api/save.php index a760bbf..c4dccb1 100644 --- a/modules/medicos/api/save.php +++ b/modules/medicos/api/save.php @@ -1,4 +1,7 @@ false,'error'=>'No autorizado']); exit; } diff --git a/modules/soporte/docs/manual/10-primeros-pasos.md b/modules/soporte/docs/manual/10-primeros-pasos.md index 067af55..02e1f36 100644 --- a/modules/soporte/docs/manual/10-primeros-pasos.md +++ b/modules/soporte/docs/manual/10-primeros-pasos.md @@ -34,6 +34,27 @@ Casi siempre es una de estas dos: | **Formularios** | Consentimientos y fichas; diseño y envíos | | **Soporte** | Esta documentación | +## El recorrido de un paciente + +Desde que saca su turno hasta que se va: + +``` + KIOSKO RECEPCIÓN TOMA DE MUESTRAS + │ │ │ + ▼ ▼ ▼ + ┌──────┐ llama ┌──────┐ deriva ┌──────────────┐ ┌────────────┐ + │espera├──────────►│recep.├───────────►│ espera lugar ├──►│ en servicio│ + └──┬───┘ └──┬───┘ └──────────────┘ └──────┬─────┘ + │ │ │ + │ no responde │ ▼ + └──────────────────┴──────────► ausente ┌────────────────┐ + │ finalizado │ + cancelado └────────────────┘ + cuenta para facturar +``` + +Un turno **nunca se borra**. Si el paciente no aparece se marca *ausente*; si no se hace, *cancelado*. Los dos quedan registrados, y ninguno cuenta como facturación. + ## Cosas que conviene saber desde el principio **Los turnos no se borran.** Se cancelan o se marcan como ausente, pero quedan registrados. Es a propósito: el historial tiene valor clínico y administrativo. diff --git a/modules/soporte/docs/manual/15-kiosko-y-pantallas.md b/modules/soporte/docs/manual/15-kiosko-y-pantallas.md new file mode 100644 index 0000000..5508c25 --- /dev/null +++ b/modules/soporte/docs/manual/15-kiosko-y-pantallas.md @@ -0,0 +1,70 @@ +# Kiosko y pantallas de TV + +Las dos pantallas que funcionan solas, sin nadie operándolas. Conviene entenderlas porque cuando fallan, el que se entera primero es quien está en recepción. + +## El kiosko + +El tótem de la entrada, donde el paciente saca su turno sin ayuda. + +``` + PACIENTE LLEGA + │ + ▼ + ┌──────────────┐ + │ Elige tipo │ general, preferencial, embarazada, + │ de turno │ solo entrega de muestras… + └──────┬───────┘ + ▼ + ┌──────────────┐ + │Datos básicos │ nombre y celular (opcional) + └──────┬───────┘ + ▼ + ┌──────────────┐ + │ Imprime │──► el turno aparece en la pantalla de TV + │ su turno │ y en la cola de recepción + └──────────────┘ +``` + +Es una de las **dos únicas pantallas públicas** del sistema: no pide usuario ni contraseña, porque nadie va a iniciar sesión en el tótem de la entrada. + +### Prioridades + +El tipo de turno que elige el paciente define su lugar en la cola. Las prioridades las configura un administrador; quien atiende no necesita hacer nada: **Llamar siguiente** ya respeta el orden. + +### Si el paciente deja su celular + +Puede recibir por WhatsApp el aviso de su turno y los consentimientos para firmar desde el teléfono mientras espera. Vale la pena insistirle en que lo deje. + +### Cuando el kiosko falla + +Un turno siempre se puede crear a mano desde recepción. El kiosko es una comodidad, no un requisito — si está caído, la atención sigue. + +## Pantalla de TV + +La de la sala de espera. Muestra el turno que se está llamando y la cola, y reproduce contenido del laboratorio de fondo. + +También es pública: se abre en el navegador del televisor y se deja andando. + +### El contenido de fondo + +Es una lista de videos e imágenes que se reproducen en bucle, uno detrás de otro: + +``` + ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ + │ video 1 │──►│ imagen │──►│ video 2 │──►│ imagen │──┐ + │ hasta │ │ 8 seg │ │ hasta │ │ 10 seg │ │ + │ el final│ │ │ │ el final│ │ │ │ + └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ + ▲ │ + └──────────────────── vuelve a empezar ────────────┘ +``` + +Los videos van completos; a las imágenes se les fija cuántos segundos duran. Se administra desde **Configuración del turnero → Pantalla TV**: se suben, se reordenan arrastrando y se eliminan de a uno. + +### Si la pantalla se queda pegada + +Recargá la página en el televisor. Si el contenido no cambió, verificá que la lista tenga elementos activos en la configuración. + +## Verificar paciente + +Una consulta rápida por cédula para ver la ficha y el historial de alguien, sin abrir su turno. Útil cuando el paciente pregunta algo en el mostrador y no querés perder lo que estás haciendo. diff --git a/modules/soporte/docs/manual/20-recepcion.md b/modules/soporte/docs/manual/20-recepcion.md index b80af4f..ad3ea4b 100644 --- a/modules/soporte/docs/manual/20-recepcion.md +++ b/modules/soporte/docs/manual/20-recepcion.md @@ -45,6 +45,22 @@ Se admite pago combinado — efectivo más tarjeta, por ejemplo. ### 5. Consentimientos +Quién firma qué, y dónde: + +``` + RECEPCIÓN TOMA DE MUESTRAS + ┌─────────────────────┐ ┌──────────────────────┐ + │ Consentimiento │ │ Datos Toma de │ + │ pruebas de lab │ │ Muestras (F-LAB-08) │ + │ │ │ │ + │ firma: EL PACIENTE │ │ firma: EL PERSONAL │ + │ vía WhatsApp │ │ en la estación │ + └─────────────────────┘ └──────────────────────┘ + obligatorio obligatorio SIEMPRE + salvo "solo entrega" (incluso solo entrega) +``` + + Los que hagan falta aparecen listados con su estado. Se envían al WhatsApp del paciente, que los firma desde el celular. **No podés guardar la solicitud si quedan consentimientos sin firmar**, salvo que sea una visita de *solo entrega de muestras*. diff --git a/modules/soporte/docs/manual/25-chat-whatsapp.md b/modules/soporte/docs/manual/25-chat-whatsapp.md new file mode 100644 index 0000000..defcf01 --- /dev/null +++ b/modules/soporte/docs/manual/25-chat-whatsapp.md @@ -0,0 +1,69 @@ +--- +roles: recepcionista, lab_recepcion, operador_bot, supervisor +--- + +# Chat de WhatsApp + +La línea de WhatsApp del laboratorio la atiende un bot, pero cuando hace falta una persona, la conversación pasa a un operador. Esta es esa pantalla. + +## Cómo se reparte el trabajo + +``` + MENSAJE DEL PACIENTE + │ + ▼ + ┌─────────────┐ no ┌──────────────────────┐ + │ ¿Aceptó los ├────────►│ Le pide aceptar y │ + │ términos? │ │ no avanza hasta que │ + └──────┬──────┘ │ responda ACEPTO │ + │ sí └──────────────────────┘ + ▼ + ┌─────────────┐ sí ┌──────────────────────┐ + │ ¿La tomó un ├────────►│ El bot NO interviene │ + │ operador? │ │ Respondés vos │ + └──────┬──────┘ └──────────────────────┘ + │ no + ▼ + ┌─────────────┐ fuera ┌──────────────────────┐ + │ ¿Está en ├────────►│ Responde con el │ + │ horario? │ │ mensaje de fuera de │ + └──────┬──────┘ │ horario │ + │ dentro └──────────────────────┘ + ▼ + El bot responde +``` + +Lo importante: **cuando tomás una conversación, el bot deja de responder ahí**. No hay riesgo de que le conteste encima al paciente mientras vos estás escribiendo. + +## Atender una conversación + +La lista muestra los hilos con mensajes recientes. Al abrir uno ves el historial completo y podés responder. + +Si el paciente ya está registrado, se ve su ficha; si no, se puede crear desde ahí mismo. + +## La ventana de 24 horas + +Es una regla de WhatsApp, no del sistema: + +> Podés escribir libremente durante **24 horas** desde el último mensaje del paciente. Pasado ese plazo, solo se le puede escribir con una **plantilla aprobada**. + +Por eso a veces el sistema no te deja mandar un texto libre y ofrece plantillas. No es una falla: es la restricción de WhatsApp. + +Las plantillas las crea y aprueba Meta. Si necesitás una nueva para un caso que se repite, pedila a un administrador — el trámite lleva días. + +## Términos y condiciones + +Todo contacto nuevo debe aceptar los términos antes de que el bot converse. Responde **ACEPTO** o **NO ACEPTO**. + +Se le vuelven a pedir cuando pasan 6 meses o cuando se publica una versión nueva. Si un paciente dice que no puede abrir el documento de términos, avisá: puede ser que el enlace esté caído, y eso lo resuelve un administrador. + +## Problemas frecuentes + +**El paciente dice que escribió y nadie le respondió.** +Revisá si la conversación quedó tomada por un operador que no siguió. En ese estado el bot no responde y queda esperando a una persona. + +**No me deja enviar un mensaje.** +Pasaron más de 24 horas desde el último mensaje del paciente. Usá una plantilla. + +**El paciente no recibe los consentimientos.** +Verificá el número en su ficha. Si está bien y aun así no llegan, es problema de plantilla — avisá a un administrador. diff --git a/modules/soporte/docs/manual/30-toma-de-muestras.md b/modules/soporte/docs/manual/30-toma-de-muestras.md index ccaba06..ef37920 100644 --- a/modules/soporte/docs/manual/30-toma-de-muestras.md +++ b/modules/soporte/docs/manual/30-toma-de-muestras.md @@ -28,6 +28,19 @@ Al rechazar hay que indicar el motivo. Ese motivo queda registrado y se ve despu ### Muestras de visitas anteriores +``` + VISITA 1 · lunes VISITA 2 · jueves + ┌────────────────────┐ ┌────────────────────┐ + │ Turno A-042 │ │ Turno B-017 │ + │ │ │ │ + │ Sangre recibida │ │ Orina recibida │ + │ Orina PENDIENTE ├───────────────►│ └ visita anterior│ + └────────────────────┘ reaparece └────────────────────┘ + finalizado sola │ + NO se modifica ◄───────────────────────────── + quedan enlazados +``` + Si el paciente quedó debiendo una muestra otro día, te aparece con una etiqueta ámbar **visita anterior**, e incluye los exámenes de aquella orden para que sepas de qué se trataba. Se reciben con un clic, igual que cualquier otra. Al hacerlo, los dos turnos quedan enlazados: desde el historial podés saltar de uno al otro. @@ -48,6 +61,22 @@ Lo firmás vos, no el paciente. Para exámenes que requieren varias tomas en el tiempo: curvas de glicemia, prolactina, cortisol, test de Sullivan. +``` + Glicemia pre y post carga + + min 0 min 30 min 60 min 120 + │ │ │ │ + ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ + │ ✔ │ ────► │ ✔ │ ────► │ │ ... │ │ + └─────┘ 30min └─────┘ 30min └─────┘ └─────┘ + 07:28 08:06 pendiente bloqueada + M. Monterrosa Y. Parada ▲ + └ cuenta regresiva + + Cada toma guarda SU hora y QUIÉN la firmó. Si cambia + el turno del personal, cada firma conserva su nombre. +``` + Cómo funciona: 1. **Marcá el examen.** El formulario muestra solo las tomas de ese examen; si el paciente tiene dos exámenes seriados, muestra las de ambos. diff --git a/modules/soporte/docs/operacion/40-respaldos.md b/modules/soporte/docs/operacion/40-respaldos.md new file mode 100644 index 0000000..a3736b4 --- /dev/null +++ b/modules/soporte/docs/operacion/40-respaldos.md @@ -0,0 +1,88 @@ +# Respaldos y recuperación + +Qué hay que respaldar, y qué se pierde si no está. + +## Las tres cosas a respaldar + +``` + ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ + │ BASE DE DATOS │ │ ARCHIVOS SUBIDOS │ │ CÓDIGO │ + │ │ │ │ │ │ + │ 91 tablas │ │ uploads/terms/ │ │ repositorio git │ + │ pacientes, turnos, │ │ uploads/turnero/ │ │ │ + │ formularios, │ │ │ │ ya respaldado por │ + │ firmas │ │ NO están en git │ │ estar en el remoto │ + └────────────────────┘ └────────────────────┘ └────────────────────┘ + crítico crítico cubierto +``` + +El código está a salvo por estar versionado. Los otros dos **no tienen respaldo automático por el solo hecho de existir**. + +## Base de datos + +Es lo único irreemplazable. Contiene historia clínica, consentimientos firmados y facturación — información con valor legal y sin forma de reconstruirse. + +```bash +mysqldump -h -u -p \ + --single-transaction --routines --triggers \ + | gzip > respaldo_$(date +%F).sql.gz +``` + +`--single-transaction` evita bloquear las tablas mientras corre, así se puede hacer con el sistema en uso. + +### Qué contiene lo crítico + +| Tabla | Por qué importa | +|---|---| +| `lab_pacientes` | Fichas clínicas | +| `turnero_consentimientos`, `lab_form_envios` | **Formularios firmados** — valor legal | +| `turnero_turnos`, `turnero_solicitudes` | Historial de atención y facturación | +| `terms_acceptance` | Aceptación de términos, ~5.000 registros | +| `admin_users`, `roles`, `role_modules` | Acceso al sistema | + +Las firmas se guardan como imagen **dentro** de las tablas, no como archivos sueltos. Un respaldo de la base las incluye. + +## Archivos subidos + +``` +uploads/terms/ documentos de términos y condiciones +uploads/turnero/tv_media/ videos e imágenes de la pantalla de TV +``` + +**No están en el repositorio.** Al mover el sistema de servidor hay que copiarlos aparte, o los enlaces quedan apuntando a archivos que ya no existen. + +Es exactamente lo que pasó con el documento de términos cuando cambió el dominio: la base seguía apuntando a una URL que ya no respondía. + +## Antes de un cambio riesgoso + +Si vas a tocar datos en producción, respaldá **solo lo que vas a tocar**: + +```bash +mysqldump -h -u -p role_modules admin_users \ + > antes_del_cambio.sql +``` + +Es rápido y suele alcanzar. Un respaldo completo para cambiar una columna es desproporcionado; no tener ninguno es imprudente. + +## Verificar que el respaldo sirve + +Un respaldo que nunca se restauró no es un respaldo, es un archivo: + +```bash +gunzip -t respaldo_2026-08-03.sql.gz # ¿está íntegro? +zcat respaldo_2026-08-03.sql.gz | head -40 # ¿tiene lo que esperás? +``` + +Lo ideal es restaurarlo de vez en cuando en una base de prueba y comprobar que el sistema arranca contra ella. + +## Qué NO es recuperable + +Aunque tengas respaldos, hay datos que nunca se guardaron y no hay de dónde sacarlos: + +| Dato | Desde cuándo existe | +|---|---| +| Quién creó cada consentimiento del turnero | 3 de agosto de 2026 | +| Quién firmó cada toma de F-LAB-28 | 3 de agosto de 2026 | +| Cédula del personal no enfermero | 3 de agosto de 2026 | + +Los registros anteriores tienen esos campos vacíos, y **no hay traza de auditoría** que permita reconstruirlos. Vale como advertencia: cuando se agrega una columna para registrar quién hizo algo, lo anterior se pierde. diff --git a/modules/soporte/docs/tecnica/55-registro-examenes.md b/modules/soporte/docs/tecnica/55-registro-examenes.md new file mode 100644 index 0000000..ba61ef4 --- /dev/null +++ b/modules/soporte/docs/tecnica/55-registro-examenes.md @@ -0,0 +1,54 @@ +# Registro de exámenes + +Registro de exámenes realizados en sede: creación de órdenes, toma de muestras e ingreso de resultados. Es de los módulos nuevos — todo su código vive dentro de `modules/registro_exams/`. + +## Vistas + +| Vista | Qué hace | +|---|---| +| `lista` | Órdenes con filtros y estado | +| `nueva_orden` | Alta de una orden | +| `orden` | Detalle: ítems, estados e ingreso de resultados | +| `etiqueta` | Etiqueta imprimible para rotular la muestra | + +## Endpoints + +| Endpoint | Qué hace | +|---|---| +| `get_ordenes.php` | Lista con filtros | +| `get_orden.php` | Detalle de una orden | +| `save_orden.php` | Crea o actualiza | +| `save_resultado.php` | Guarda el resultado de un ítem | +| `cambiar_estado_item.php` | Avanza el estado de un ítem individual | + +Usan `api/_helpers.php` del módulo, con las mismas convenciones que el turnero. + +## Flujo + +``` + nueva_orden orden orden + │ │ │ + ▼ ▼ ▼ + ┌─────────┐ ┌───────────┐ ┌─────────────┐ + │ crear ├──────►│ muestra ├──────────►│ resultado │ + │ orden │ │ tomada │ │ ingresado │ + └─────────┘ └───────────┘ └─────────────┘ + │ │ + ▼ ▼ + etiqueta se rotula + imprimible la muestra +``` + +El estado se lleva **por ítem**, no por orden completa: una orden puede tener unos exámenes resueltos y otros pendientes. + +## Relación con otros módulos + +| Módulo | Vínculo | +|---|---| +| `lab_examenes` | De ahí sale el catálogo y los valores de referencia | +| `lab_pacientes` | El paciente de la orden | +| `medicos` | El médico que la solicitó | + +## Al tocarlo + +Los resultados de laboratorio son información clínica: un ítem mal guardado o un valor de referencia equivocado tienen consecuencias reales. Cualquier cambio en `save_resultado.php` merece probarse con una orden de prueba antes de subirlo. diff --git a/modules/soporte/docs/tecnica/70-catalogos.md b/modules/soporte/docs/tecnica/70-catalogos.md new file mode 100644 index 0000000..922d5fc --- /dev/null +++ b/modules/soporte/docs/tecnica/70-catalogos.md @@ -0,0 +1,67 @@ +# Catálogos del laboratorio + +Los módulos que administran las tablas maestras. Se agrupan acá porque comparten la misma forma: una pantalla de listado con alta, edición y baja sobre una tabla. + +## Los módulos + +| Módulo | Tabla principal | Qué administra | +|---|---|---| +| `lab_examenes` | `exam_tipos` | Catálogo de exámenes, valores de referencia y tarifas | +| `medicos` | `medicos` | Médicos solicitantes | +| `lab_pacientes` | `lab_pacientes` | Fichas clínicas e historial | +| `lab_enfermeras` | `lab_enfermeras` | Personal clínico | +| `lab_eps` | `lab_eps` | EPS y aseguradoras | +| `lab_empresas` | `lab_empresas` | Empresas, convenios, subgrupos y tarifas | +| `lab_ciudades` | `lab_ciudades` | Ciudades de pacientes | +| `usuarios` | `admin_users`, `roles` | Usuarios y asignación de roles | + +## Los que tienen endpoints propios + +La mayoría son puentes al sistema anterior. Dos tienen código propio: + +### `lab_examenes` + +| Endpoint | Qué hace | +|---|---| +| `list.php` / `get.php` | Listado y detalle | +| `save.php` | Alta y edición del examen | +| `save_item.php` | Ítems que componen un examen | +| `get_tarifas.php` / `save_tarifa.php` | Tarifas por empresa o convenio | + +Es el catálogo del que dependen el turnero y el registro de exámenes. Un examen mal configurado se propaga a todo lo demás: consentimientos que no se piden, tarifas que no se aplican. + +**`exam_tipo_consentimientos`** vincula un examen con los formularios que obliga a firmar. Es una de las dos fuentes de consentimientos del turnero; la otra es la estación destino. + +### `medicos` + +`list.php`, `save.php`, `delete.php`. El médico se asocia a la solicitud del turnero y sale impreso en los documentos. + +## Pacientes + +`lab_pacientes` es el más consultado de todos: lo usan el turnero, domicilios, registro de exámenes y el bot. + +Campos que otros módulos dan por sentados: + +| Campo | Quién lo usa | +|---|---| +| `numero_documento` | Búsqueda en todas las pantallas | +| `telefono` | Envío de consentimientos y encuestas | +| `nombre_completo`, `tipo_documento` | Encabezado de todos los documentos | +| `fecha_nacimiento` | Cálculo de edad en formularios | +| `eps` | Facturación | + +Un teléfono mal cargado se manifiesta lejos de donde se originó: como un consentimiento que nunca llegó. + +## Usuarios + +Ver [Roles y permisos](?m=soporte&v=documentacion&s=arquitectura&d=roles-y-permisos) para el detalle del control de acceso. + +Lo esencial al crear o editar un usuario: + +- **`role` y `role_id` deben cambiarse juntos.** La interfaz lee uno, los permisos salen del otro. +- **Cargá la cédula.** Es lo que aparece bajo la firma en los formularios. +- El usuario debe **volver a iniciar sesión** para que un cambio de permisos surta efecto. + +## Al agregar un catálogo nuevo + +Si es un ABM simple, seguí el patrón de `medicos`: un `views/index.php` y tres endpoints (`list`, `save`, `delete`). Registralo en `SYSTEM_MODULES` y concedelo a los roles que corresponda, o nadie lo verá. diff --git a/modules/turnero/api/buscar_cie10.php b/modules/turnero/api/buscar_cie10.php index 4479234..c9c484e 100644 --- a/modules/turnero/api/buscar_cie10.php +++ b/modules/turnero/api/buscar_cie10.php @@ -1,4 +1,7 @@