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 deLIS_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
- Objetivos y criterios
- Decisiones PostgreSQL 18+
- Arquitectura de datos
- Modelo clínico central
- Catálogo y configuración clínica
- Muestras y ejecución analítica
- Resultados, validación e informes
- Equipos y calidad
- Reactivos e inventario
- Microbiología
- Facturación y cobertura
- Usuarios, seguridad y auditoría
- Estados y reglas de integridad
- Índices, vistas y funciones
- Interoperabilidad
- Operación, crecimiento y recuperación
- Diferencias frente al SQL fuente
- Matriz de migración
- 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
- Seleccionar el intervalo vigente para analito, método, unidad y criterios del paciente en la fecha clínicamente relevante.
- Si no existe o existen varios igualmente aplicables, marcar referencia no resuelta y enviar a revisión; nunca asumir
normal. - Comparar límites críticos antes que límites de referencia.
- Guardar
intervalo_referencia_id, representación mostrada, bandera y criticidad en la versión. - 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
PUBLICen 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 ALLgeneral. - 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,
autovacuumy 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 unCHECKinmutable incorrecto. -
edad_min_dias <= edad_max_dias,valor_min <= valor_maxy 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 esteCHECKno 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ónEXCLUDEsobre la expresión de rango. No hace falta convertir las columnas adaterange: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_reactivoycuenta_rol. Dos detalles no son opcionales, y ambos se comprobaron contra PostgreSQL 18.4:coalesce(...)en todo criterio opcional. Una restricciónEXCLUDEignora las filas en las que el operador devuelve nulo. Consexo_id with =a secas, dos filas consexo_idnulo y vigencias solapadas se insertan sin error, porquenull = nullno es verdadero. Sustituir el nulo por un centinela cierra el hueco. La alternativa, más limpia si se puede, es hacer la columnanot nully tener una fila «no aplica» en el catálogo.- El tercer argumento
'[]'. Por defectodaterange(a, b)es semiabierto y excluyeb, 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. Comovigente_hastase lee de forma inclusiva, el rango debe construirse inclusivo. Lo mismo vale para el rango de edades.
Un
vigente_hastanulo 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 CASCADEdesde 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 usarMAX + 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 contracurrent_date.registrar_transicion_estado: valida transición, actualiza la proyección e inserta historial en una transacción. ConRETURNING old.estado, new.estadode 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, fijansearch_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_statementsy 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_versiono 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 NULLa una tabla grande sin bloquearla mientras se valida, usarNOT NULL NOT VALIDy validar después; para reglas que aún no se pueden imponer sobre datos históricos, declararlasNOT ENFORCEDy activarlas al sanear. PostgreSQL no admiteADD CONSTRAINT IF NOT EXISTS: la idempotencia se consigue comprobandopg_constrainten un bloqueDO.
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
- Rechazar un paciente duplicado con el mismo identificador en la misma organización y permitir otro emisor/sistema válido.
- Impedir asociar una muestra o alícuota de otro paciente a una prueba solicitada.
- Expandir un perfil sin duplicar pruebas ya incluidas según la política elegida.
- Impedir rangos o tarifas con vigencias incompatibles para la misma clave.
- Impedir un resultado con valor numérico y textual principal simultáneos.
- Impedir consumo negativo, sobreconsumo no autorizado o uso de lote vencido/bloqueado.
- Impedir borrado físico de una orden con resultados o informes.
- Impedir dos intervalos de referencia o dos tarifas con vigencias solapadas para los mismos criterios, comprobando que la rechaza la restricción
EXCLUDEdel 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. - Impedir procesar o divulgar una prueba cuyo consentimiento obligatorio no esté vigente.
- Impedir que un analito dependiente del volumen total se calcule cuando la muestra temporizada no tiene periodo ni volumen.
19.2 Flujo clínico
- Ejecutar la jornada del archivo de ejemplo desde CC hasta entrega.
- Rechazar una muestra y crear una nueva toma sin perder trazabilidad.
- Compartir una alícuota entre varias pruebas y usar varias alícuotas en una prueba.
- Recibir un resultado por interfaz, repetirlo y liberar la versión seleccionada.
- Detectar un crítico, documentar comunicación y escalamiento.
- Corregir un resultado ya informado y reproducir tanto el informe original como el corregido.
- Mantener una orden parcial mientras un cultivo continúa 48–72 horas.
- Registrar dos microorganismos y antibiogramas independientes en un cultivo polimicrobiano.
- 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.
- 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.
- 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ó.
- 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
- Generar simultáneamente números de orden sin duplicados.
- Verificar que roles no autorizados no lean ni modifiquen resultados, pagos o auditoría.
- Confirmar que cada FK crítica tiene índice útil y que la lista de trabajo usa el índice previsto.
- Verificar que los eventos auditables generan actor, fecha, correlación y antes/después.
- Restaurar una copia en un entorno aislado y reconciliar conteos e informes con hashes.
- 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).