Arquitectura y operación

Propuesta técnica del modelo de datos LIS para PostgreSQL 18+

Estado: propuesta de diseño

Motor objetivo: PostgreSQL 18 o posterior

Convención: nombres técnicos en español, minúsculas y snake_case

Alcance: modelo relacional para laboratorio clínico multisede, con trazabilidad clínica, calidad, inventario, facturación, microbiología, informes y auditoría.

Este documento evoluciona —no replica literalmente— LIS_datos_modelo_postgresql.sql. Conserva su cobertura y la de LIS_datos_ejemplo.sql, corrige riesgos de integridad/concurrencia y agrega componentes necesarios para una trazabilidad completa. No contiene una migración ejecutable ni sustituye la validación clínica, regulatoria o de seguridad.

Contenido

  1. Objetivos y criterios
  2. Decisiones PostgreSQL 18+
  3. Arquitectura de datos
  4. Modelo clínico central
  5. Catálogo y configuración clínica
  6. Muestras y ejecución analítica
  7. Resultados, validación e informes
  8. Equipos y calidad
  9. Reactivos e inventario
  10. Microbiología
  11. Facturación y cobertura
  12. Usuarios, seguridad y auditoría
  13. Estados y reglas de integridad
  14. Índices, vistas y funciones
  15. Interoperabilidad
  16. Operación, crecimiento y recuperación
  17. Diferencias frente al SQL fuente
  18. Matriz de migración
  19. Pruebas de aceptación del modelo

1. Objetivos y criterios

El modelo debe permitir:

  • reconstruir el recorrido completo desde paciente y orden hasta la versión exacta de un informe;
  • operar varias sedes y distinguir registro, toma, procesamiento y entrega;
  • configurar pruebas, perfiles, analitos, métodos, referencias y tarifas con vigencia;
  • compartir o dividir muestras sin perder identidad ni cadena de custodia;
  • conservar resultados originales, repeticiones, correcciones y validaciones;
  • impedir la publicación cuando faltan controles o aprobaciones obligatorias;
  • documentar valores críticos y su comunicación confirmada;
  • relacionar resultados con equipos, ejecuciones y lotes realmente usados;
  • soportar microbiología, facturación, pagos, cuentas por cobrar, alertas y auditoría;
  • configurar como datos —no como código— las pruebas reflejas, el delta check y la autovalidación, con evidencia de cada aplicación;
  • registrar los datos clínicos que intervienen en un cálculo o en la selección de una referencia;
  • seguir una muestra derivada a un laboratorio de referencia sin perder la custodia;
  • interoperar mediante mapeos explícitos sin acoplar el modelo físico a una sola versión de un estándar.

1.1 Alcance funcional

El núcleo cubre hematología, química, uroanálisis, microbiología, parasitología, inmunología/serología, hormonas y coagulación. Banco de sangre y patología/citología pueden usar las entidades comunes de orden, muestra, resultado e informe, pero requieren submodelos especializados antes de producción (donantes/componentes/compatibilidad y casos/bloques/láminas/diagnósticos, respectivamente).

1.2 Criterios de normalización

Se busca tercera forma normal para maestros y hechos, con duplicación intencional solo para instantáneas históricas: precio vendido, nombre/método reportado, unidad, intervalo de referencia mostrado y representación del informe. Una instantánea no es un dato maestro alternativo; es evidencia de lo vigente en el momento del hecho.

2. Decisiones PostgreSQL 18+

Tema Decisión
Esquema Objetos del dominio en lis; extensiones o integraciones en esquemas separados. Evitar usar public como espacio indiscriminado.
Identificadores Estrategia mixta según la clase de tabla, detallada en §2.2: entero de identidad en catálogos pequeños, uuid con uuidv7() en maestros y hechos expuestos, bigint de identidad en bitácoras internas. Los códigos legibles siguen siendo claves únicas de negocio, independientes de la clave técnica.
Extensiones No se necesita uuid-ossp para generar UUIDv7 en PostgreSQL 18. btree_gist sí es necesaria: las restricciones de no solapamiento de §13.2 combinan igualdad sobre columnas escalares con && sobre un rango. pgcrypto solo si existe un caso definido; autenticación y secretos preferiblemente fuera del núcleo clínico.
Texto text por defecto; varchar(n) solo si el límite es una regla real de interoperabilidad o negocio.
Tiempo date para nacimiento, vencimientos y vigencias civiles; timestamptz para eventos. Guardar instantes en UTC y presentar en la zona de la sede.
Números numeric para mediciones exactas, dinero y cantidades de inventario; integer/smallint para orden y versión. No usar money ni coma flotante para importes.
Estados text con FK a catálogos de estado y transición para flujos evolutivos; CHECK para conjuntos verdaderamente cerrados. Evitar ENUM PostgreSQL en estados que cambian con operación.
Datos flexibles jsonb solo para mensaje original, metadatos externos o antes/después de auditoría. Los datos consultados o validados con frecuencia son columnas relacionales.
Direcciones de red inet para la dirección de origen de auditoría cuando se almacene.
Arreglos Evitar arreglos para relaciones. Las opciones de un analito se normalizan en una tabla hija.
Borrado RESTRICT para hechos clínicos/financieros; inactivación de maestros. CASCADE solo en componentes internos que no tienen sentido fuera de su agregado y antes de liberación.

La fecha extraíble de un UUIDv7 no reemplaza creado_en: el instante clínico debe ser siempre una columna explícita.

2.1 Convenciones de columnas

  • PK: id.
  • FK: <entidad>_id.
  • Identificador legible: codigo, numero_orden, numero_factura, numero_informe.
  • Tiempos: verbos en participio o evento, por ejemplo recolectada_en, recibida_en, validada_en.
  • Auditoría técnica mínima en maestros: creado_en, creado_por_id, actualizado_en, actualizado_por_id.
  • Activación de maestros: activo; hechos usan estados, anulaciones o versiones, no borrado suave genérico.
  • Todas las constraints e índices reciben nombres explícitos y estables.

2.2 Estrategia de claves primarias

No todas las tablas necesitan el mismo tipo de clave. Un uuid ocupa 16 bytes y se repite en cada fila hija y en cada índice que lo referencie; en un catálogo de decenas de filas ese coste no compra nada.

Clase de tabla Clave primaria Razón
Catálogos de baja cardinalidad: seccion_laboratorio, tipo_muestra, tipo_recipiente, unidad_medida, rol, catálogos de estado y de transición, tipos de precio y de movimiento integer generated always as identity, o smallint donde el dominio es claramente cerrado Nunca superan unos miles de filas, no se exponen al exterior y no se generan de forma distribuida. Cuatro bytes frente a dieciséis reducen el tamaño de cada índice y de cada fila que los referencia.
Maestros de negocio: paciente, prueba, analito, medico_solicitante, aseguradora, equipo, reactivo uuid con uuidv7() Aparecen en URL, códigos de barras, integraciones y exportaciones. Conviene que no sean adivinables ni enumerables.
Hechos clínicos y financieros: orden_laboratorio, prueba_solicitada, muestra, alicuota, ejecucion_analitica, resultado, resultado_version, informe_resultados, factura uuid con uuidv7() Se crean en varias sedes y se referencian desde fuera del sistema. UUIDv7 conserva la localidad temporal en el índice, a diferencia de UUIDv4.
Bitácoras internas de alto volumen: evento_muestra, movimiento_inventario, mensaje_interfaz, evento_auditoria bigint generated always as identity Solo inserción, crecimiento sin límite y ninguna exposición externa. Ocho bytes frente a dieciséis sí importan a esta escala. Para evento_auditoria ver además §12.2.

Dos consecuencias prácticas: una clave foránea hereda siempre el tipo de la clave a la que apunta, así que el tipo se decide una sola vez por tabla referenciada; y el identificador legible de negocio (codigo, numero_orden, numero_factura, numero_informe) es independiente de la clave técnica y mantiene su propia restricción de unicidad en cualquiera de los tres casos.

2.3 Características de PostgreSQL 18 aprovechadas

Característica Uso en este modelo
PRIMARY KEY y UNIQUE con WITHOUT OVERLAPS, y claves foráneas con PERIOD Evaluado y no adoptado. Exige que la vigencia sea una columna de rango, y este modelo mantiene el par clásico vigente_desde/vigente_hasta por comodidad de mapeo desde la aplicación y de consulta. La misma garantía se obtiene con una restricción EXCLUDE sobre la expresión de rango, sin cambiar las columnas: ver §13.2.
uuidv7() nativo Identificadores temporalmente ordenables sin extensión externa (§2.2).
Columnas generadas virtuales, ahora el modo por defecto Derivaciones que se leen pero no se almacenan, calculadas sobre columnas de la propia fila. No usarlas para datos clínicos que deban congelarse: una instantánea histórica es una columna real, no una expresión reevaluada.
RETURNING OLD/NEW registrar_transicion_estado y los triggers de auditoría obtienen el valor anterior y el nuevo en la misma sentencia, sin releer la fila (§14.3).
NOT NULL NOT VALID en ALTER TABLE Migraciones de expansión y contracción sobre tablas grandes sin bloquear para validar toda la tabla (§16).
Restricciones CHECK y foráneas NOT ENFORCED Declarar una regla ya acordada antes de poder imponerla sobre datos históricos, y activarla cuando los datos estén saneados.
Recorrido por saltos en índices B-tree Un índice compuesto atiende ahora consultas que no restringen sus primeras columnas. Reduce el número de índices necesarios; conviene revisar §14.1 con esto en mente en lugar de crear un índice por patrón de consulta.

3. Arquitectura de datos

flowchart TD
    Personas[Personas y cobertura] --> Ordenes[Órdenes y atención]
    Catalogo[Catálogo clínico] --> Ordenes
    Ordenes --> Muestras[Muestras y alícuotas]
    Muestras --> Analitica[Ejecución analítica]
    Catalogo --> Analitica
    Calidad[Equipos y calidad] --> Analitica
    Inventario[Reactivos e inventario] --> Analitica
    Analitica --> Resultados[Resultados y validación]
    Catalogo --> Reglas[Reglas clínicas]
    Reglas --> Resultados
    Reglas --> Ordenes
    Resultados --> Informes[Informes y entrega]
    Ordenes --> Finanzas[Facturación y cartera]
    Resultados --> Alertas[Alertas y notificaciones]
    Personas --> Auditoria[Seguridad y auditoría]
    Informes --> Auditoria
    Finanzas --> Auditoria

    classDef maestro fill:#D0EBFF,stroke:#1971C2,stroke-width:2px,color:#0B2E4F
    classDef clinico fill:#D3F9D8,stroke:#2B8A3E,stroke-width:2px,color:#1B4332
    classDef soporte fill:#FFF3BF,stroke:#E67700,stroke-width:2px,color:#5F3C00
    classDef gobierno fill:#E5DBFF,stroke:#6741D9,stroke-width:2px,color:#2F1B69
    class Personas,Catalogo maestro
    class Ordenes,Muestras,Analitica,Resultados,Informes clinico
    class Calidad,Inventario,Finanzas,Alertas,Reglas soporte
    class Auditoria gobierno

3.1 Dominios

Dominio Entidades principales
Organización y acceso organizacion, sede, cuenta_usuario, rol, cuenta_rol, profesional_laboratorio, laboratorio_referencia
Personas y cobertura paciente, identificador_paciente, contacto_paciente, medico_solicitante, aseguradora, cobertura_paciente, consentimiento_paciente
Catálogo seccion_laboratorio, tipo_muestra, tipo_recipiente, unidad_medida, prueba, perfil, perfil_prueba, analito, opcion_analito, intervalo_referencia, tarifa_prueba, codigo_externo
Operación clínica orden_laboratorio, dato_clinico_orden, prueba_solicitada, muestra, evento_muestra, alicuota, prueba_alicuota, ejecucion_analitica, derivacion_externa
Resultados resultado, resultado_version, validacion_resultado, notificacion_critica, informe_resultados, informe_resultado_detalle, entrega_informe
Reglas clínicas regla_refleja, regla_delta, regla_autovalidacion, ejecucion_regla
Equipos/calidad equipo, equipo_prueba, mantenimiento_equipo, calibracion_equipo, lote_control, ejecucion_control, programa_calidad_externo, resultado_calidad_externo
Inventario reactivo, lote_reactivo, prueba_reactivo, consumo_reactivo, movimiento_inventario
Microbiología cultivo, lectura_cultivo, aislamiento, antibiograma, resultado_antimicrobiano
Finanzas factura, detalle_factura, pago, cuenta_por_cobrar
Gobierno alerta, evento_auditoria, catálogos de estados y transiciones

4. Modelo clínico central

erDiagram
    PACIENTE ||--o{ ORDEN_LABORATORIO : tiene
    MEDICO_SOLICITANTE ||--o{ ORDEN_LABORATORIO : solicita
    SEDE ||--o{ ORDEN_LABORATORIO : registra
    ORDEN_LABORATORIO ||--|{ PRUEBA_SOLICITADA : contiene
    PRUEBA ||--o{ PRUEBA_SOLICITADA : instancia
    ORDEN_LABORATORIO ||--o{ MUESTRA : origina
    MUESTRA ||--o{ ALICUOTA : divide
    PRUEBA_SOLICITADA }o--o{ ALICUOTA : utiliza
    PRUEBA_SOLICITADA ||--o{ EJECUCION_ANALITICA : procesa
    EJECUCION_ANALITICA ||--o{ RESULTADO_VERSION : produce
    PRUEBA_SOLICITADA ||--o{ RESULTADO : contiene
    RESULTADO ||--|{ RESULTADO_VERSION : versiona
    RESULTADO_VERSION ||--o{ VALIDACION_RESULTADO : valida
    ORDEN_LABORATORIO ||--o{ INFORME_RESULTADOS : emite

4.1 Personas y cobertura

Entidad Campos esenciales Integridad
organizacion codigo, nombre, identificación legal, zona horaria, activo Raíz para una instalación independiente; permite evolución SaaS sin mezclar datos.
sede organizacion_id, codigo, nombre, tipo, dirección, teléfono, correo, zona horaria, activo Única por organización y código.
paciente numero_historia, nombres, fecha_nacimiento, sexo_biologico, identidad de género opcional, grupo sanguíneo, alergias, observaciones, activo Historia única por organización; nacimiento no futuro.
identificador_paciente paciente_id, sistema/tipo, valor, emisor, vigencia, principal Único por organización, sistema y valor; permite más de un documento.
contacto_paciente dirección, ciudad, teléfono, correo, emergencia, preferencia de contacto Separar dato vigente de eventos clínicos.
medico_solicitante código, nombre, especialidad, licencia, institución y contacto Licencia/código únicos en el ámbito definido cuando existan.
aseguradora código, nombre, identificación tributaria, contacto, parámetros administrativos, activo No guardar un porcentaje universal si la cobertura depende de contrato/prueba.
cobertura_paciente paciente, aseguradora, póliza, plan, vigente_desde/vigente_hasta, estado Permite varias coberturas históricas; no sobrescribe la usada por una orden. Vigencias sin solapar por paciente y aseguradora (§13.2).
consentimiento_paciente paciente, alcance (prueba o categoría), otorgado por, fecha, medio, vigencia, revocación, evidencia Requerido para determinadas pruebas según normativa local; se verifica antes de procesar y antes de divulgar.

sexo_biologico y identidad_genero son conceptos separados. La selección de referencias clínicas usa los criterios validados por el laboratorio y conserva cuál se aplicó; no debe inferirse de un campo ambiguo llamado genero.

4.2 Orden y prueba solicitada

Entidad Campos esenciales Integridad
orden_laboratorio número, paciente, médico, sedes de registro/toma/proceso, registrador, estado, prioridad, cobertura, autorización, CIE-10/texto, observaciones, fechas e importes Número único; importes no negativos; cancelación con motivo; paciente inmutable tras iniciar procesamiento salvo corrección formal.
prueba_solicitada orden, prueba, estado, prioridad, instantáneas de código/nombre/método, precio unitario, descuento/final, técnico, fechas, cancelación Una fila por servicio realmente solicitado; evita duplicados no intencionales al expandir perfiles.
dato_clinico_orden orden, tipo de dato codificado, valor numérico o texto, unidad, fecha de toma del dato, capturado por Peso, talla, semanas de gestación, diuresis, medicación. Necesario para calcular TFG, depuración o referencias ajustadas por gestación. Estructurado y fechado, nunca dentro de diagnostico_texto.
historial_estado_orden orden, estado anterior/nuevo, motivo, usuario, instante Fuente de trazabilidad del ciclo; no depende solo de fechas agregadas en la orden.
historial_estado_prueba prueba solicitada, transición, motivo, usuario, instante Conserva devoluciones, repeticiones y cancelaciones.

Los totales en la orden son una proyección conciliada con las pruebas solicitadas. Los importes finales vendidos se conservan aunque la tarifa del catálogo cambie.

La orden y la prueba solicitada tienen ciclos distintos: la orden agrega, la prueba avanza. El estado de la orden se deriva del conjunto de sus pruebas, nunca al revés.

stateDiagram-v2
    [*] --> Pendiente
    Pendiente --> En_proceso: muestra aceptada y distribuida
    Pendiente --> Derivada: prueba no realizada internamente
    Pendiente --> Cancelada: cancelación o rechazo sin nueva toma
    Derivada --> En_proceso: resultado recibido del laboratorio de referencia
    En_proceso --> En_espera: repetición, dilución o incubación en curso
    En_espera --> En_proceso: nueva ejecución
    En_proceso --> Validada_tecnicamente: revisión técnica conforme
    Validada_tecnicamente --> En_espera: devuelta para repetir o aclarar
    Validada_tecnicamente --> Validada_profesionalmente: aprobación clínica
    Validada_profesionalmente --> Publicada: incluida en un informe emitido
    Publicada --> Publicada: corrección, nueva versión de resultado
    Publicada --> [*]
    Cancelada --> [*]

    classDef inicial fill:#E6E6FA,stroke:#5F3DC4,stroke-width:2px,color:#2F1B69
    classDef curso fill:#D0EBFF,stroke:#1971C2,stroke-width:2px,color:#0B2E4F
    classDef cierre fill:#D3F9D8,stroke:#2B8A3E,stroke-width:2px,color:#1B4332
    classDef excepcion fill:#FFE3E3,stroke:#C92A2A,stroke-width:2px,color:#5C0000
    class Pendiente inicial
    class En_proceso,En_espera,Derivada curso
    class Validada_tecnicamente,Validada_profesionalmente,Publicada cierre
    class Cancelada excepcion

5. Catálogo y configuración clínica

erDiagram
    SECCION_LABORATORIO ||--o{ PRUEBA : agrupa
    TIPO_MUESTRA ||--o{ REQUISITO_MUESTRA : clasifica
    TIPO_RECIPIENTE ||--o{ REQUISITO_MUESTRA : contiene
    PRUEBA ||--|{ REQUISITO_MUESTRA : requiere
    PERFIL ||--|{ PERFIL_PRUEBA : compone
    PRUEBA ||--o{ PERFIL_PRUEBA : integra
    PRUEBA ||--|{ ANALITO : reporta
    ANALITO ||--o{ OPCION_ANALITO : ofrece
    ANALITO ||--o{ INTERVALO_REFERENCIA : interpreta
    PRUEBA ||--o{ TARIFA_PRUEBA : tarifa
    ASEGURADORA ||--o{ TARIFA_PRUEBA : acuerda
    UNIDAD_MEDIDA ||--o{ ANALITO : expresa
    PRUEBA ||--o{ CODIGO_EXTERNO : mapea
    ANALITO ||--o{ CODIGO_EXTERNO : mapea
    PRUEBA ||--o{ REGLA_REFLEJA : desencadena
    ANALITO ||--o{ REGLA_DELTA : vigila
    PRUEBA ||--o{ REGLA_AUTOVALIDACION : libera
Entidad Campos esenciales Reglas
seccion_laboratorio código, nombre, descripción, responsable, activo Código único por organización.
tipo_muestra código, nombre, descripción, activo Catálogo extensible; no ENUM rígido.
tipo_recipiente código, nombre, color orientativo, aditivo, activo El color por sí solo no define el recipiente.
prueba código, nombre/corto, sección, metodología base, TAT objetivo, ayuno, instrucciones, orden de impresión, indicador de derivación externa, activo Código único. Los códigos LOINC y equivalentes no son columnas de esta tabla: viven en codigo_externo con su sistema y versión (§15).
requisito_muestra prueba, tipo de muestra/recipiente, volumen mínimo, condición, preferencia Permite más de una combinación válida por prueba.
perfil / perfil_prueba código/nombre del perfil; prueba y orden Relación explícita N:M; impedir ciclos y autorreferencia.
analito prueba, código, nombre, tipo de valor, unidad_medida_id, decimales, fórmula, título/calculado, orden, activo Código único dentro de prueba; fórmula versionada y validada. La unidad es una referencia al catálogo, no texto libre.
opcion_analito analito, código, etiqueta, orden, códigos externos Sustituye text[]; preserva semántica y traducción.
intervalo_referencia analito, método, unidad, sexo/edad y otros criterios, min/max, críticos, texto normal, vigente_desde/vigente_hasta, fuente y aprobación Intervalos que no deben solaparse para el mismo conjunto de criterios; se impone con una restricción EXCLUDE en la propia tabla (§13.2).
tarifa_prueba prueba, tipo de precio, aseguradora/plan opcional, moneda, precio, vigente_desde/vigente_hasta, activo Precio no negativo; vigencias no solapadas para la misma clave comercial, impuestas con EXCLUDE (§13.2).
unidad_medida código UCUM, símbolo presentable, descripción, activo Catálogo compartido por analitos, intervalos y resultados; evita que «mg/dL» y «mg/dl» convivan como unidades distintas.
codigo_externo entidad referida (prueba, analito, opción, tipo de muestra, microorganismo), sistema, código, versión, display, vigencia Sustituye cualquier columna suelta tipo loinc_code. Una misma prueba puede tener códigos de varios sistemas y versiones a la vez (§15).

5.1 Reglas clínicas configurables

Tres comportamientos que el marco conceptual exige no son código: son configuración versionada, con vigencia y aprobación, y dejan evidencia cada vez que se aplican.

Entidad Campos esenciales Reglas
regla_refleja prueba o analito origen, condición evaluada, prueba desencadenada, requiere confirmación humana, vigencia, aprobador Al dispararse crea una prueba_solicitada nueva sobre la orden original, con su tarifa y su cobertura; no escribe un comentario en el resultado origen.
regla_delta analito, magnitud o porcentaje de cambio, ventana temporal, acción esperada, vigencia, aprobador Compara con resultados previos del mismo paciente. Es apoyo a la revisión: bloquea la autovalidación, no decide por sí sola.
regla_autovalidacion prueba o analito, condiciones (criticidad, banderas, delta, no conformidad de muestra, estado de control de calidad y de equipo), vigencia, aprobador Nunca libera un resultado crítico. Debe poder desactivarse globalmente sin desplegar código.
ejecucion_regla regla y versión aplicada, resultado_version o prueba solicitada afectada, decisión, instante Evidencia de qué regla actuó sobre qué dato. Sin esta tabla, una liberación automática es indistinguible de una manual.

6. Muestras y ejecución analítica

Entidad Campos esenciales Reglas
muestra código de barras, orden, paciente, tipo, recipiente, volumen, estado, recolector, sedes, recolección/recepción, temperatura, ubicación, observaciones, periodo de recolección (inicio, fin, volumen total) Orden y paciente coherentes; código único; rechazo exige motivo. El periodo solo aplica a muestras temporizadas, como la orina de 24 h, y sin él los analitos que dependen del volumen total quedan sin calcular, no en cero.
evento_muestra muestra, tipo de evento, estado anterior/nuevo, sede/ubicación, usuario, instante, temperatura, observación Libro inmutable de cadena de custodia.
no_conformidad_muestra muestra, categoría, descripción, decisión, autorizado por, fechas Distingue condición observada de la decisión de rechazo.
alicuota código, muestra origen, volumen, unidad, estado, ubicación y fechas Nunca existe sin muestra origen; volumen no negativo.
prueba_alicuota prueba solicitada, alícuota, propósito, principal Relación N:M; impide vincular paciente/orden incompatibles.
ejecucion_analitica prueba solicitada, alícuota, equipo, método, operador, origen, estado, inicio/fin, repetición, dilución, mensaje de interfaz Cada repetición es un evento; no se sobrescribe la ejecución anterior.
mensaje_interfaz equipo, protocolo/versión, dirección, correlación, contenido o referencia, recibido/procesado, error Deduplicación por equipo/correlación; acceso restringido por datos sensibles.
derivacion_externa prueba solicitada, muestra o alícuota enviada, laboratorio_referencia, número de envío, condiciones de transporte, enviada/recibida en, costo acordado, resultado retornado, responsable que firma La custodia no se interrumpe al salir de la sede. El informe debe identificar qué laboratorio produjo el resultado y quién lo firmó.

Estado de muestra

stateDiagram-v2
    [*] --> Pendiente
    Pendiente --> Recolectada: toma y etiquetado
    Recolectada --> Recibida: recepción técnica
    Recibida --> Rechazada: no conformidad
    Recibida --> En_proceso: distribución
    En_proceso --> Procesada: ejecuciones finalizadas
    Procesada --> Almacenada: conservación
    Almacenada --> Descartada: fin de retención
    Rechazada --> Descartada
    Descartada --> [*]

El estado fuente no incluía almacenamiento y descarte; se agregan para completar la cadena de custodia. La nueva toma se representa como una nueva muestra relacionada, no reutilizando el código rechazado.

7. Resultados, validación e informes

Entidad Campos esenciales Reglas
resultado prueba solicitada, analito, estado, versión vigente Único por prueba solicitada/analito; es cabecera, no almacena un valor mutable.
resultado_version resultado, número de versión, ejecución, valor numérico/texto/código, unidad, referencia aplicada, rango mostrado, bandera, criticidad, origen, creado por/en, motivo Exactamente un tipo de valor principal; versión única y creciente; inmutable.
validacion_resultado versión, tipo, origen (humano o automático), decisión, profesional o regla aplicada, comentario, fecha La validación apunta a la versión revisada; una corrección invalida la liberación previa para la nueva versión. Cuando el origen es automático, referencia la ejecucion_regla que la produjo (§5.1); el campo de profesional queda vacío y no se rellena con un usuario de sistema que simule una firma.
notificacion_critica versión, estado, destinatario, relación, canal, emisor, enviada/confirmada/escalada en, evidencia Debe cerrarse o escalarse; la alerta visual no basta.
informe_resultados orden, número, versión, estado, emisor, fecha, formato, hash, ubicación del artefacto, reemplaza a Emisión y corrección crean versiones; número/version únicos.
informe_resultado_detalle informe, resultado_version, orden de presentación Congela exactamente qué versiones se publicaron.
entrega_informe informe, canal, destinatario, usuario, fecha, confirmación Varias entregas/reimpresiones del mismo informe son posibles.

7.1 Cálculo de criticidad

  1. Seleccionar el intervalo vigente para analito, método, unidad y criterios del paciente en la fecha clínicamente relevante.
  2. Si no existe o existen varios igualmente aplicables, marcar referencia no resuelta y enviar a revisión; nunca asumir normal.
  3. Comparar límites críticos antes que límites de referencia.
  4. Guardar intervalo_referencia_id, representación mostrada, bandera y criticidad en la versión.
  5. Disparar alerta/notificación según política sin liberar automáticamente.

7.2 Corrección

Una corrección agrega resultado_version, nuevas validaciones y un informe que referencia/reemplaza al anterior. resultado_version e informe_resultado_detalle permiten reproducir cualquier informe histórico aunque cambien paciente, catálogo o referencia.

stateDiagram-v2
    [*] --> Capturada: ejecución analítica o interfaz
    Capturada --> Referencia_no_resuelta: sin intervalo aplicable único
    Referencia_no_resuelta --> Capturada: configuración corregida
    Capturada --> Revisada: coherencia, delta y criticidad evaluadas
    Revisada --> Reemplazada: repetición produce versión posterior
    Revisada --> Liberada: validaciones exigidas completas
    Liberada --> Publicada: incluida en un informe emitido
    Publicada --> Reemplazada: corrección publicada en versión posterior
    Reemplazada --> [*]
    Publicada --> [*]

    classDef curso fill:#D0EBFF,stroke:#1971C2,stroke-width:2px,color:#0B2E4F
    classDef cierre fill:#D3F9D8,stroke:#2B8A3E,stroke-width:2px,color:#1B4332
    classDef excepcion fill:#FFE3E3,stroke:#C92A2A,stroke-width:2px,color:#5C0000
    class Capturada,Revisada curso
    class Liberada,Publicada cierre
    class Referencia_no_resuelta,Reemplazada excepcion

Ninguna transición modifica una versión existente: Reemplazada significa que existe una versión posterior vigente, no que la anterior se haya alterado. Por eso el puntero de versión vigente vive en la cabecera resultado y las filas de resultado_version son inmutables una vez escritas.

8. Equipos y calidad

Entidad Campos esenciales Reglas
equipo código, nombre, marca, modelo, serie, sección, sede, interfaz, estado, instalación, activo Serie única cuando exista; retiro no borra ejecuciones.
equipo_prueba equipo, prueba, método/configuración, prioridad, vigencia Define qué puede procesar cada equipo.
mantenimiento_equipo equipo, tipo, programado/realizado, proveedor, resultado, evidencia Un equipo bloqueado no recibe ejecuciones ordinarias.
calibracion_equipo equipo, analito/método, lote/calibrador, resultado, vigencia, aprobador Separada del control de calidad.
lote_control material, fabricante, lote, nivel, apertura, vencimiento, valores asignados Lote y nivel identificables.
ejecucion_control equipo, analito, lote, corrida/turno, valor, media, desviación, regla, estado, ejecutor, fecha Soporta Levey-Jennings y Westgard; no solo un booleano.
evento_bloqueo_analitico equipo/método/analito, causa, inicio, resolución, autorizador Relaciona CC rechazado con el periodo afectado.
programa_calidad_externo proveedor, programa, ronda, periodo y estado Estructura el CCE ausente del SQL fuente.
resultado_calidad_externo programa/ronda, analito, resultado, asignado, grupo par, sesgo, evaluación y acción Conserva comparación y acciones correctivas.

9. Reactivos e inventario

erDiagram
    SECCION_LABORATORIO ||--o{ REACTIVO : usa
    REACTIVO ||--o{ LOTE_REACTIVO : recibe
    PRUEBA ||--o{ PRUEBA_REACTIVO : requiere
    REACTIVO ||--o{ PRUEBA_REACTIVO : participa
    LOTE_REACTIVO ||--o{ MOVIMIENTO_INVENTARIO : mueve
    EJECUCION_ANALITICA ||--o{ CONSUMO_REACTIVO : consume
    LOTE_REACTIVO ||--o{ CONSUMO_REACTIVO : traza
Entidad Campos esenciales Reglas
reactivo código, nombre, fabricante, catálogo, unidad, sección, stock mínimo, costo de referencia, refrigeración/temperatura, activo Código único; condición estructurada, no solo texto libre cuando se automatice.
lote_reactivo reactivo, lote, fabricación, recepción, vencimiento, apertura, cantidades, costo, proveedor, certificado y estado Único por reactivo/lote; cantidades no negativas; vencido/bloqueado no consumible.
prueba_reactivo prueba, reactivo, cantidad teórica, unidad, vigencia Receta estimada para planificación.
consumo_reactivo ejecución, lote, cantidad, unidad, fecha, usuario Evidencia del lote real usado.
movimiento_inventario lote, tipo, cantidad firmada o dirección, saldo posterior, motivo, documento, usuario, fecha Solo inserción; todo ajuste exige motivo.

El saldo actual puede materializarse para consulta, pero debe reconciliarse con la suma de movimientos. El stock a nivel de reactivo es una agregación de lotes utilizables, no una segunda fuente manual.

10. Microbiología

Entidad Campos esenciales Reglas
cultivo prueba solicitada, muestra/alícuota, estado, medio, temperatura, siembra, incubación, responsable Una prueba puede tener uno o varios cultivos si el procedimiento lo requiere.
lectura_cultivo cultivo, secuencia, fecha, descripción macro/micro, crecimiento, recuento, lector Varias lecturas 24/48/72 h; no sobrescribir.
aislamiento cultivo, microorganismo codificado/texto, método de identificación, cantidad/significancia Un cultivo puede producir varios aislamientos.
antibiograma aislamiento, método, versión de criterio/punto de corte, fecha, equipo Pertenece al aislamiento, no solo al cultivo agregado.
resultado_antimicrobiano antibiograma, antimicrobiano, concentración, diámetro, MIC, interpretación S/I/R y comentarios Único por antibiograma/antimicrobiano; conserva dato medido e interpretación.

Este desglose mejora las tablas fuente cultivos y antibiogramas, que guardan un solo germen y mezclan cabecera con una fila de antimicrobiano.

11. Facturación y cobertura

Entidad Campos esenciales Reglas
factura número, orden, paciente, aseguradora, fecha, moneda, subtotal, descuento, impuesto, total, estado, emisor, anulación Número único; total conciliado; anulación con motivo/usuario/fecha.
detalle_factura factura, prueba solicitada/concepto, descripción, cantidad, unitario, descuento, impuesto, total Congela cada línea; no reconstruir desde tarifas actuales.
pago factura, método, monto, referencia, banco/canal, fecha, receptor, estado/reversión Monto positivo; reversión como evento, no borrado.
cuenta_por_cobrar factura, aseguradora, monto, pagado, estado, envío, cobro, observaciones 0 <= monto_pagado <= monto; estado consistente con el saldo.

paciente_id y aseguradora_id pueden conservarse en factura como instantáneas relacionales verificadas, aunque sean derivables de la orden, porque el documento financiero tiene identidad histórica propia.

12. Usuarios, seguridad y auditoría

Entidad Propósito
cuenta_usuario Referencia al proveedor de identidad, nombre de acceso, estado, último acceso y vínculo opcional con profesional. No almacenar secretos reversibles.
rol / cuenta_rol Modelo N:M para administración, recepción, flebotomía, técnico, bioanalista, patología, facturación y almacén; permite combinaciones y vigencia.
profesional_laboratorio Identidad profesional, licencia, especialidad, firma/certificado referenciado y sedes habilitadas.
alerta Tipo, entidad referida, prioridad, mensaje, destinatario, estado, fechas y resolución.
evento_auditoria organización/sede, entidad, registro, acción, antes/después jsonb, actor, rol efectivo, inet, correlación y fecha. Solo inserción.

12.1 Controles

  • Revocar privilegios por defecto a PUBLIC en el esquema aplicativo.
  • Separar roles PostgreSQL de migración, aplicación, solo lectura operacional y auditoría.
  • La aplicación nunca se conecta como propietario ni superusuario.
  • Conceder permisos mínimos por tablas/vistas o funciones; no GRANT ALL general.
  • Considerar RLS solo si existe aislamiento real por organización y todas las rutas de acceso se prueban. Las sedes de una misma organización no son automáticamente tenants.
  • Proteger copias de seguridad y exportaciones con los mismos controles que la base activa.
  • Auditar accesos/entregas de información clínica según política, además de cambios.
  • Cifrar transporte con TLS y mantener llaves, certificados y secretos fuera de tablas de negocio.

12.2 Dónde vive la auditoría

Conviene separar dos cosas que el SQL fuente mezclaba bajo la palabra «auditoría».

Trazabilidad que es parte del registro clínico o financiero. resultado_version, validacion_resultado, evento_muestra, notificacion_critica, historial_estado_orden, movimiento_inventario, entrega_informe. Se consultan desde la aplicación, se imprimen en informes, participan en reglas de integridad y deben ser transaccionalmente coherentes con el hecho que describen. Permanecen en PostgreSQL, con claves foráneas reales.

Bitácora técnica que no es dato de negocio. evento_auditoria (el antiguo audit_log) y mensaje_interfaz. Son un flujo append-only, de alto volumen, esquema laxo (jsonb de antes/después, contenido crudo de protocolo) y consulta poco frecuente y casi siempre por rango de fechas. Ese perfil no es el de una base relacional.

Nota de arquitectura. Se recomienda trasladar la bitácora técnica a un motor distinto, orientado a documentos JSON o a registros de eventos —OpenSearch/Elasticsearch, ClickHouse, Loki o un almacén de objetos con archivo por fecha—, dejando en PostgreSQL únicamente la trazabilidad que participa del negocio. Razones: el volumen de auditoría suele superar en un orden de magnitud al de los datos clínicos y distorsiona respaldos, autovacuum y tiempos de restauración; su retención legal es distinta y normalmente más larga que la operativa; y su patrón de consulta —búsqueda por texto y agregación temporal— se sirve mucho mejor fuera de un motor relacional. Si por simplicidad inicial se mantiene en PostgreSQL, debe ir en tablas particionadas por fecha, con política de archivado y purga explícita desde el primer día, no como una tabla que crece indefinidamente. Lo que no puede trasladarse fuera es la evidencia que un informe o una regla de integridad necesitan leer: esa es registro clínico, no bitácora.

13. Estados y reglas de integridad

13.1 Catálogos iniciales

Concepto Valores iniciales consolidados
Orden registrada, pagada, en_toma, en_proceso, parcial, completada, entregada, cancelada
Muestra pendiente, recolectada, recibida, en_proceso, procesada, almacenada, rechazada, descartada
Prueba solicitada pendiente, en_proceso, en_espera, derivada, validada_tecnicamente, validada_profesionalmente, publicada, cancelada (§4.2)
Versión de resultado capturada, referencia_no_resuelta, revisada, liberada, publicada, reemplazada (§7.2)
Pago/factura pendiente, parcial, pagado, anulado, reembolsado
Criticidad sin_evaluar, normal, bajo, alto, critico_bajo, critico_alto. Se elimina panico del catálogo fuente: es sinónimo de valor crítico, no un nivel adicional, y mantenerlo como valor hermano hacía ambigua la regla de notificación.
Movimiento entrada, salida, ajuste_positivo, ajuste_negativo, devolucion, descarte
Método de pago efectivo, tarjeta_debito, tarjeta_credito, transferencia, seguro, convenio, mixto
Tipo de precio particular, seguro, convenio, emergencia, empleado

13.2 Restricciones importantes

  • fecha_nacimiento <= current_date; las reglas dependientes de la fecha actual se validan en servicio/trigger, no en un CHECK inmutable incorrecto.

  • edad_min_dias <= edad_max_dias, valor_min <= valor_max y críticos coherentes cuando existan.

  • Vigencia: vigente_hasta IS NULL OR vigente_hasta >= vigente_desde. Con dos columnas un periodo invertido sí es representable, así que este CHECK no es opcional: sin él, el constructor de rango de la restricción de no solapamiento fallaría en tiempo de ejecución en vez de rechazarse limpiamente al insertar.

  • Importes, volúmenes, cantidades y tiempos no negativos; descuento dentro de la base.

  • Un valor de resultado cumple una exclusión lógica entre numérico, texto y opción. Fórmulas almacenan el valor evaluado además de su procedencia.

  • Un intervalo de referencia no puede solaparse con otro de igual analito, método, unidad y criterios. La vigencia se modela con el par clásico vigente_desde/vigente_hasta, y el no solapamiento se impone en la base con una restricción EXCLUDE sobre la expresión de rango. No hace falta convertir las columnas a daterange:

    create extension if not exists btree_gist;
    
    create table lis.intervalo_referencia (
        id            uuid primary key default uuidv7(),
        analito_id    uuid    not null references lis.analito (id),
        metodo_id     integer references lis.metodo (id),
        unidad_id     integer not null references lis.unidad_medida (id),
        sexo_id       integer references lis.sexo_biologico (id),   -- nulo = aplica a todos
        edad_min_dias integer not null default 0,
        edad_max_dias integer not null default 36500,
        valor_min     numeric,
        valor_max     numeric,
        vigente_desde date    not null,
        vigente_hasta date,                                          -- nulo = sin fin previsto
    
        constraint intervalo_referencia_vigencia_coherente
            check (vigente_hasta is null or vigente_hasta >= vigente_desde),
        constraint intervalo_referencia_edad_coherente
            check (edad_min_dias <= edad_max_dias),
    
        constraint intervalo_referencia_sin_solape
            exclude using gist (
                analito_id              with =,
                coalesce(metodo_id, -1) with =,
                unidad_id               with =,
                coalesce(sexo_id, -1)   with =,
                int4range(edad_min_dias, edad_max_dias, '[]')        with &&,
                daterange(vigente_desde, vigente_hasta, '[]')        with &&
            )
    );

    El mismo patrón aplica a tarifa_prueba, equipo_prueba, cobertura_paciente, prueba_reactivo y cuenta_rol. Dos detalles no son opcionales, y ambos se comprobaron contra PostgreSQL 18.4:

    1. coalesce(...) en todo criterio opcional. Una restricción EXCLUDE ignora las filas en las que el operador devuelve nulo. Con sexo_id with = a secas, dos filas con sexo_id nulo y vigencias solapadas se insertan sin error, porque null = null no es verdadero. Sustituir el nulo por un centinela cierra el hueco. La alternativa, más limpia si se puede, es hacer la columna not null y tener una fila «no aplica» en el catálogo.
    2. El tercer argumento '[]'. Por defecto daterange(a, b) es semiabierto y excluye b, de modo que una vigencia que termina el 30 de junio y otra que empieza el 30 de junio no se detectan como solapadas, aunque para el negocio ese día está cubierto dos veces. Como vigente_hasta se lee de forma inclusiva, el rango debe construirse inclusivo. Lo mismo vale para el rango de edades.

    Un vigente_hasta nulo produce un rango sin límite superior y se compara correctamente: dos vigencias abiertas sobre los mismos criterios se rechazan entre sí.

  • Una FK por sí sola no valida relaciones transitivas (por ejemplo, paciente de muestra = paciente de orden); usar claves compuestas adicionales o trigger de restricción transaccional.

  • Los estados solo cambian por transiciones autorizadas y se registra el historial.

  • Publicar requiere versión validada, referencia resuelta o excepción documentada, y control de calidad apto cuando aplique.

  • No usar ON DELETE CASCADE desde orden a resultados liberados. La cancelación conserva hechos.

14. Índices, vistas y funciones

14.1 Índices iniciales orientados a consultas

PostgreSQL no crea automáticamente índices en columnas FK del lado referenciante. Deben indexarse las FK usadas en uniones/borrado y diseñarse índices compuestos según las consultas.

Consulta Índice candidato
Paciente por documento único (organizacion_id, sistema, valor) en identificador_paciente
Paciente por apellido/nombre B-tree normalizado o búsqueda textual, según requisitos reales
Órdenes recientes por sede/estado (sede_registro_id, estado, registrada_en desc)
Lista de trabajo parcial/compuesto por sección, estado, prioridad y fecha para estados activos
Muestra por código único (organizacion_id, codigo_barras)
Cadena de custodia (muestra_id, ocurrido_en)
Resultado por prueba/analito único (prueba_solicitada_id, analito_id)
Versión vigente único parcial por resultado_id donde vigente o puntero validado desde cabecera
Críticos pendientes parcial por fecha donde criticidad crítica y notificación sin cierre
Lotes por vencimiento (estado, fecha_vencimiento) y por reactivo_id
Auditoría por entidad (entidad, registro_id, ocurrido_en desc); BRIN por fecha si el volumen lo justifica

No crear un índice adicional sobre una columna ya cubierta por PK o UNIQUE. Validar índices con consultas y EXPLAIN (ANALYZE, BUFFERS) en datos representativos.

El recorrido por saltos de PostgreSQL 18 permite que un índice compuesto atienda consultas que no restringen sus primeras columnas, siempre que esas primeras columnas tengan pocos valores distintos. Antes de añadir un índice que solo reordena las columnas de otro existente, conviene medir si el que ya está cubre el caso. Esto es especialmente aplicable a la lista de trabajo, donde sección, estado y prioridad tienen cardinalidad baja.

14.2 Vistas

Vista Contenido
v_ordenes_completas Orden, paciente, médico, sedes, cobertura, estado e importes.
v_lista_trabajo Pruebas activas por sección/equipo con prioridad, muestra y antigüedad.
v_resultados_para_informe Versiones vigentes/liberadas ordenadas por sección, prueba y analito.
v_reactivos_stock_bajo Saldo utilizable, mínimo, déficit y vencimiento próximo.
v_alertas_activas Críticos, QC, equipos, stock y vencimientos sin resolver.
v_tiempos_respuesta Hitos y duración por orden/prueba/sección.

El SQL fuente llama “vistas materializadas” a objetos creados con CREATE VIEW; la propuesta los clasifica correctamente. Solo materializar una vista si las mediciones justifican costo, latencia y política de refresco.

14.3 Funciones y triggers

  • generar_numero_orden/factura/informe: usar secuencia o contador por organización/año bloqueado transaccionalmente. No usar MAX + 1, que produce colisiones bajo concurrencia.
  • seleccionar_intervalo_referencia: determinista respecto a una fecha y criterios; si no hay una coincidencia única, devuelve condición de revisión.
  • evaluar_criticidad: opera sobre el intervalo ya seleccionado y no clasifica “normal” cuando falta referencia.
  • calcular_edad: calcula años, meses o días con respecto a la fecha clínica del informe; el texto de edad se genera para presentación y no se guarda como dato maestro ni se recalcula siempre contra current_date.
  • registrar_transicion_estado: valida transición, actualiza la proyección e inserta historial en una transacción. Con RETURNING old.estado, new.estado de PostgreSQL 18 obtiene ambos valores de la propia sentencia de actualización, sin releer la fila ni arriesgar una lectura desfasada.
  • actualizar_fecha_modificacion: permitido en maestros; no sustituye auditoría.
  • Triggers de auditoría cubren las tablas definidas por política y reciben identidad/correlación desde la sesión de aplicación.
  • Funciones SECURITY DEFINER, si existen, fijan search_path, validan permisos y tienen superficie mínima.

15. Interoperabilidad

Concepto LIS HL7 FHIR orientativo Terminología
Paciente Patient Identificadores nacionales/locales
Médico/profesional Practitioner, PractitionerRole Catálogos profesionales locales
Orden/prueba solicitada ServiceRequest LOINC u otro catálogo ordenable validado
Muestra/alícuota Specimen SNOMED CT para tipo/sitio cuando aplique
Resultado/analito Observation LOINC para observación; UCUM para unidades; SNOMED CT para valores codificados
Informe DiagnosticReport Código del panel/informe y conclusiones codificadas cuando aplique

Ese mapeo es la entidad codigo_externo de §5: sistema, codigo, version, display y vigencia, nunca una columna suelta loinc_code sin contexto. Las unidades se expresan con el catálogo unidad_medida referenciando UCUM, de modo que un Observation pueda emitirse con unidad codificada y no con una cadena escrita a mano. Las interfaces ASTM/HL7 v2 de equipos se adaptan a un modelo canónico y conservan correlación/mensaje original para soporte.

16. Operación, crecimiento y recuperación

  • Usar un pool de conexiones; evitar una conexión por usuario final y sesiones inactivas prolongadas.
  • Activar pg_stat_statements y monitorear latencia, bloqueos, conexiones, autovacuum, crecimiento y consultas de lista de trabajo/informe.
  • Mantener transacciones cortas; operaciones humanas largas usan estados, no transacciones abiertas.
  • Establecer respaldos completos y archivado continuo de WAL si el RPO exige recuperación a un punto en el tiempo.
  • Probar restauraciones periódicamente; un respaldo no probado no demuestra recuperabilidad.
  • Definir RPO, RTO, retención y archivo con el propietario del negocio antes de fijar frecuencias.
  • Considerar partición temporal para evento_auditoria, evento_muestra, mensaje_interfaz, resultado_version o movimientos solo cuando volumen y mantenimiento lo justifiquen. PostgreSQL 18 no convierte la partición en un requisito por sí sola.
  • Mantener migraciones versionadas, transaccionales cuando sea posible, con expansión/contracción para cambios incompatibles e índices concurrentes en producción cuando corresponda. Para añadir NOT NULL a una tabla grande sin bloquearla mientras se valida, usar NOT NULL NOT VALID y validar después; para reglas que aún no se pueden imponer sobre datos históricos, declararlas NOT ENFORCED y activarlas al sanear. PostgreSQL no admite ADD CONSTRAINT IF NOT EXISTS: la idempotencia se consigue comprobando pg_constraint en un bloque DO.

17. Diferencias frente al SQL fuente

Hallazgo en la fuente Riesgo Evolución propuesta
UUIDv4 mediante uuid-ossp Extensión innecesaria y peor localidad de índice. uuidv7() nativo de PostgreSQL 18.
Roles, estados y tipos como ENUM Alteración operativa más rígida. Catálogos/FK para flujos; CHECK solo en conjuntos cerrados.
pacientes.aseguradora_id único No representa coberturas múltiples o históricas. cobertura_paciente y fotografía en la orden.
Perfil modelado con perfil_padre_id y perfil_examenes Dos fuentes de verdad. perfil + perfil_prueba únicamente.
Una combinación de muestra/tubo por examen No permite alternativas válidas. requisito_muestra: una prueba admite varios requisitos de muestra alternativos (1:N).
orden_examenes.muestra_id Una prueba no puede usar varias alícuotas; mezcla muestra primaria y porción. muestra → alicuota y relación prueba_alicuota N:M.
Resultado mutable con numérico y texto opcionales Ambigüedad, ausencia de unicidad y pérdida de versiones. resultado + resultado_version, exclusión de tipo y unicidad prueba/analito.
Falta de referencia aplicable retorna normal Puede ocultar una configuración incompleta. Estado sin_evaluar y revisión obligatoria.
Lote de reactivo como texto en resultado No garantiza trazabilidad referencial. consumo_reactivo enlaza ejecución con lote_reactivo.
Historial solo de valores anterior/nuevo No conserva unidad, referencia, ejecución ni liberación exacta. Versionado completo e informe con detalle de versiones.
Validación sobre prueba, no versión Una corrección puede parecer validada por una aprobación anterior. Validación sobre resultado_version.
Informe sin detalle de resultados/versiones No puede reproducirse con certeza. informe_resultado_detalle y reemplaza_a.
MAX + 1 para número de orden Colisión bajo concurrencia. Secuencia o contador bloqueado por ámbito/año.
Stock duplicado como dato editable Descuadre entre reactivo, lote y movimientos. Movimientos como libro mayor y saldo proyectado/reconciliado.
Un germen por cultivo y antibiograma plano Insuficiente para cultivos polimicrobianos. Lecturas, aislamientos, cabecera de antibiograma y resultados antimicrobianos.
CCI con booleano de aceptación No representa bloqueo, investigación y liberación. Ejecución de control y evento de bloqueo/acción.
CCE solo descrito, sin tablas Pérdida de evidencia externa. Programa y resultado de calidad externo.
ON DELETE CASCADE desde orden a resultados Riesgo de pérdida clínica. Cancelación y RESTRICT una vez activado/liberado.
Auditoría definida pero no conectada La tabla vacía no audita. Política, triggers/eventos, actor de sesión y pruebas de cobertura.
Contraseñas y firmas binarias en usuarios Acopla identidad y material sensible al dominio. Proveedor de identidad y referencia segura a firma/certificado.
Índices incompletos en FK Uniones/borrados pueden escanear tablas. Auditoría sistemática de FK e índices según uso.
criticidad con panico junto a critico_alto Dos nombres para el mismo concepto hacen ambigua la regla de notificación. panico se elimina del catálogo; el valor crítico es un único nivel (§13.1).
loinc_code como columna de examenes Un código sin sistema ni versión no es interoperable ni admite varios vocabularios. Entidad codigo_externo con sistema, código, versión y vigencia (§5, §15).
Unidad de medida como texto libre en analitos «mg/dL» y «mg/dl» conviven como unidades distintas. Catálogo unidad_medida referenciado, alineado con UCUM.
Solo diagnostico_cie10 y diagnostico_texto en la orden Sin peso, talla ni gestación no se calcula TFG ni se ajustan referencias, aunque los datos de ejemplo incluyen una paciente embarazada. dato_clinico_orden estructurado y fechado (§4.2).
Sin soporte de prueba refleja, delta check ni autovalidación Los datos de ejemplo encadenan urocultivo → antibiograma a mano; el marco conceptual nombra el delta check sin dónde configurarlo. regla_refleja, regla_delta, regla_autovalidacion y ejecucion_regla (§5.1).
Sin periodo de recolección en muestras La proteinuria de 24 h del catálogo no es calculable. Periodo de recolección y volumen total en muestra (§6).
Sin derivación a laboratorio de referencia Se pierde la custodia y no se sabe qué laboratorio firma el resultado. laboratorio_referencia y derivacion_externa (§6).
UUID uniforme en todas las tablas Dieciséis bytes en catálogos de decenas de filas y en bitácoras de alto volumen. Estrategia mixta de claves por clase de tabla (§2.2).
audit_log relacional sin política de crecimiento Distorsiona respaldos, autovacuum y restauraciones. Separación entre trazabilidad de negocio y bitácora técnica, con motor propio para la segunda (§12.2).
Vigencias como dos columnas validadas por convención El solapamiento solo se evita por disciplina de aplicación. Se conservan las dos columnas, pero el solapamiento lo impide una restricción EXCLUDE en la base (§13.2).

18. Matriz de migración

Las 33 tablas del esquema original quedan cubiertas así:

Tabla fuente Destino o tratamiento
sedes organizacion + sede
usuarios cuenta_usuario, rol, cuenta_rol, profesional_laboratorio
pacientes paciente, identificador_paciente, contacto_paciente, cobertura_paciente
medicos medico_solicitante
aseguradoras aseguradora
secciones seccion_laboratorio
examenes prueba + requisito_muestra; el indicador de perfil pasa a perfil
perfil_examenes perfil + perfil_prueba
analitos analito + opcion_analito
valores_referencia intervalo_referencia versionado
lista_precios tarifa_prueba versionada
ordenes orden_laboratorio + historial de estados
orden_examenes prueba_solicitada + historial + prueba_alicuota
muestras muestra, evento_muestra, no_conformidad_muestra, alicuota
resultados resultado + resultado_version
resultados_historial absorbida por resultado_version y auditoría
validaciones validacion_resultado sobre versión concreta
equipos equipo, mantenimiento y calibración
equipo_examenes equipo_prueba
lotes_control lote_control
control_calidad ejecucion_control + bloqueo analítico
reactivos reactivo
reactivo_lotes lote_reactivo
movimientos_inventario movimiento_inventario inmutable
examen_reactivos prueba_reactivo; el uso real va a consumo_reactivo
facturas factura + detalle_factura
pagos pago con reversión
cuentas_por_cobrar cuenta_por_cobrar
informes informe_resultados, detalle y entrega
cultivos cultivo, lectura_cultivo, aislamiento
antibiogramas antibiograma + resultado_antimicrobiano
alertas alerta; críticos además usan notificacion_critica
audit_log evento_auditoria particionable y de solo inserción

18.1 Uso de los datos de ejemplo

El archivo de ejemplo sirve como escenario de migración y aceptación: configuración base de tres sedes y ocho roles; aseguradoras y médicos; secciones, pruebas, perfiles, analitos, referencias y tarifas; equipos, reactivos y controles; cinco pacientes con órdenes particulares/aseguradas y normal/urgente; facturación y pagos; toma/recepción; resultados normales y críticos; validaciones; alertas; informes; consumo de inventario; urocultivo y antibiograma posterior.

Antes de cargarlo se deben reemplazar contraseñas y datos personales ficticios por fixtures seguros, adaptar UUID a valores válidos para el motor, y ajustar los inserts a las nuevas entidades/versiones. Nunca usar esas credenciales de ejemplo en un entorno real.

18.2 Entidades sin equivalente en la fuente

Estas entidades no migran desde ninguna tabla del SQL original: cubren conceptos que las cuatro fuentes no modelaban. Se listan aparte para que la matriz anterior siga siendo una correspondencia uno a uno verificable.

Entidad nueva Necesidad que cubre
dato_clinico_orden Peso, talla, gestación y diuresis para cálculos y referencias ajustadas.
consentimiento_paciente Autorización previa y divulgación en pruebas que lo exigen.
unidad_medida, codigo_externo Unidades y terminologías codificadas en vez de texto libre.
regla_refleja, regla_delta, regla_autovalidacion, ejecucion_regla Comportamiento clínico configurable con evidencia de aplicación.
laboratorio_referencia, derivacion_externa Pruebas no realizadas internamente.
mensaje_interfaz, evento_muestra, no_conformidad_muestra, alicuota Cadena de custodia y origen de los resultados por interfaz.
mantenimiento_equipo, calibracion_equipo, evento_bloqueo_analitico Aptitud del equipo como precondición de liberación.
programa_calidad_externo, resultado_calidad_externo Evidencia del control de calidad externo.
notificacion_critica, entrega_informe, informe_resultado_detalle Comunicación confirmada y reproducibilidad del informe.

19. Pruebas de aceptación del modelo

19.1 Integridad

  1. Rechazar un paciente duplicado con el mismo identificador en la misma organización y permitir otro emisor/sistema válido.
  2. Impedir asociar una muestra o alícuota de otro paciente a una prueba solicitada.
  3. Expandir un perfil sin duplicar pruebas ya incluidas según la política elegida.
  4. Impedir rangos o tarifas con vigencias incompatibles para la misma clave.
  5. Impedir un resultado con valor numérico y textual principal simultáneos.
  6. Impedir consumo negativo, sobreconsumo no autorizado o uso de lote vencido/bloqueado.
  7. Impedir borrado físico de una orden con resultados o informes.
  8. Impedir dos intervalos de referencia o dos tarifas con vigencias solapadas para los mismos criterios, comprobando que la rechaza la restricción EXCLUDE del motor y no una validación de la aplicación. Incluir el caso de dos filas con el mismo criterio opcional nulo y el de dos vigencias que comparten día frontera.
  9. Impedir procesar o divulgar una prueba cuyo consentimiento obligatorio no esté vigente.
  10. Impedir que un analito dependiente del volumen total se calcule cuando la muestra temporizada no tiene periodo ni volumen.

19.2 Flujo clínico

  1. Ejecutar la jornada del archivo de ejemplo desde CC hasta entrega.
  2. Rechazar una muestra y crear una nueva toma sin perder trazabilidad.
  3. Compartir una alícuota entre varias pruebas y usar varias alícuotas en una prueba.
  4. Recibir un resultado por interfaz, repetirlo y liberar la versión seleccionada.
  5. Detectar un crítico, documentar comunicación y escalamiento.
  6. Corregir un resultado ya informado y reproducir tanto el informe original como el corregido.
  7. Mantener una orden parcial mientras un cultivo continúa 48–72 horas.
  8. Registrar dos microorganismos y antibiogramas independientes en un cultivo polimicrobiano.
  9. Disparar una prueba refleja desde un resultado positivo y comprobar que crea una prueba solicitada nueva, con su tarifa, su cobertura y su propia trazabilidad.
  10. Autovalidar un resultado que cumple la regla vigente, comprobar que queda registrada la regla que lo liberó, y comprobar que un resultado crítico de la misma prueba no se autovalida.
  11. Derivar una prueba a un laboratorio de referencia, recibir el resultado y reproducir el informe identificando qué laboratorio lo produjo y quién lo firmó.
  12. Agregar una prueba a una orden ya registrada reutilizando una muestra vigente, y comprobar que se rechaza cuando el criterio de estabilidad ha expirado.

19.3 Concurrencia, seguridad y operación

  1. Generar simultáneamente números de orden sin duplicados.
  2. Verificar que roles no autorizados no lean ni modifiquen resultados, pagos o auditoría.
  3. Confirmar que cada FK crítica tiene índice útil y que la lista de trabajo usa el índice previsto.
  4. Verificar que los eventos auditables generan actor, fecha, correlación y antes/después.
  5. Restaurar una copia en un entorno aislado y reconciliar conteos e informes con hashes.
  6. Comprobar que la bitácora técnica puede archivarse, purgarse o trasladarse a su motor definitivo sin afectar la reproducción de informes históricos ni ninguna regla de integridad (§12.2).

Referencias técnicas