15 KiB
📊 MODELO DE DATOS DE CONTENIDO - EMERGES TES
Versión: 1.0
Fecha: 2025-01-XX
Estado: Documento de Especificación - Sin Implementación
Autor: Arquitecto de Software Senior + Arquitecto de Contenido
🎯 PROPÓSITO DEL DOCUMENTO
Este documento define EL MODELO DE DATOS CONCEPTUAL para el sistema de gestión de contenido de EMERGES TES. Especifica:
- ✅ Estructura de datos para contenido editable
- ✅ IDs estables e inmutables
- ✅ Sistema de versionado
- ✅ Metadatos de validación clínica
- ✅ Relaciones entre entidades
Este documento es la especificación técnica para implementación futura.
1️⃣ PRINCIPIOS DE DISEÑO
Principio 1: IDs Estables e Inmutables
Cada entidad de contenido tiene un ID único que:
- ✅ No cambia nunca (inmutable)
- ✅ No depende del texto o título
- ✅ Es legible y descriptivo
- ✅ Sigue convención consistente
Convención de IDs:
- Protocolos:
{tema}-{variante}(ej:rcp-adulto-svb) - Fármacos:
{nombre-generico-lowercase}(ej:adrenalina) - Guías:
{tema}-{variante}(ej:rcp-adulto-svb) - Manual:
{bloque}-{subbloque}(ej:bloque-04-1)
Principio 2: Versionado Semántico
Cada contenido tiene versión que:
- ✅ Incrementa en cada cambio
- ✅ Permite rollback
- ✅ Facilita auditoría
- ✅ Soporta comparación de versiones
Formato: Número entero incremental (1, 2, 3, ...)
Principio 3: Separación de Contenido y Metadatos
Contenido (editable):
- Textos, pasos, dosis, explicaciones
Metadatos (sistema):
- IDs, versiones, validación, auditoría
Ventaja: Permite editar contenido sin tocar metadatos del sistema.
2️⃣ MODELO DE DATOS POR TIPO
2.1 Protocolo Operativo
interface Protocol {
// Identificación (inmutable)
id: string; // "rcp-adulto-svb"
version: number; // 1, 2, 3...
// Contenido (editable)
title: string; // "RCP Adulto - Soporte Vital Básico"
shortTitle: string; // "RCP Adulto SVB"
category: 'soporte_vital' | 'patologias' | 'escena';
subcategory?: string; // "rcp"
priority: 'critico' | 'alto' | 'medio' | 'bajo';
ageGroup: 'adulto' | 'pediatrico' | 'neonatal' | 'todos';
// Pasos del protocolo (editable)
steps: string[]; // Array de pasos numerados
// Advertencias (editable)
warnings: string[]; // Máx. 5 advertencias críticas
// Puntos clave (editable)
keyPoints?: string[]; // Puntos importantes
// Material necesario (editable)
equipment?: string[]; // Lista de material
// Fármacos relacionados (referencias)
drugs?: string[]; // IDs de fármacos: ["adrenalina", "amiodarona"]
// Metadatos del sistema (no editable directamente)
metadata: ContentMetadata;
}
Ejemplo JSON:
{
"id": "rcp-adulto-svb",
"version": 3,
"title": "RCP Adulto - Soporte Vital Básico",
"shortTitle": "RCP Adulto SVB",
"category": "soporte_vital",
"subcategory": "rcp",
"priority": "critico",
"ageGroup": "adulto",
"steps": [
"Garantizar seguridad de la escena",
"Comprobar consciencia: estimular y preguntar \"¿Se encuentra bien?\"",
"Si no responde, llamar inmediatamente al 112"
],
"warnings": [
"Profundidad compresiones: 5-6 cm",
"Frecuencia: 100-120 compresiones/min"
],
"keyPoints": [
"Compresiones de calidad salvan vidas",
"No interrumpir para pulso hasta que haya signos de vida"
],
"equipment": ["DEA", "Bolsa-mascarilla", "Cánula orofaríngea"],
"drugs": ["adrenalina"],
"metadata": {
"validatedBy": "dr-juan-perez",
"validatedAt": "2025-01-15T10:00:00Z",
"clinicalSource": "ERC 2021",
"validationStatus": "validated",
"createdAt": "2024-12-01T08:00:00Z",
"createdBy": "editor-clinico-001",
"updatedAt": "2025-01-15T10:00:00Z",
"updatedBy": "editor-clinico-001",
"changeLog": [...]
}
}
2.2 Fármaco (Vademécum)
interface Drug {
// Identificación (inmutable)
id: string; // "adrenalina"
version: number; // 1, 2, 3...
// Contenido (editable)
genericName: string; // "Adrenalina (Epinefrina)"
tradeName: string; // "Adrenalina Braun®"
category: 'cardiovascular' | 'respiratorio' | 'neurologico' | 'analgesia' | 'oxigenoterapia' | 'otros';
presentation: string; // Descripción de presentación
// Dosis (editable - crítico)
adultDose: string; // "ANAFILAXIA: 0.5 mg IM..."
pediatricDose?: string; // "ANAFILAXIA: 0.01 mg/kg IM..."
// Vías de administración (editable)
routes: ('IV' | 'IM' | 'SC' | 'IO' | 'Nebulizado' | 'SL' | 'Rectal' | 'Nasal')[];
// Dilución (editable)
dilution?: string; // "ANAFILAXIA: Sin diluir..."
// Indicaciones (editable)
indications: string[]; // Array de indicaciones
// Contraindicaciones (editable)
contraindications: string[]; // Array de contraindicaciones
// Efectos secundarios (editable)
sideEffects?: string[]; // Array de efectos secundarios
// Antídoto (editable)
antidote?: string; // Antídoto si aplica
// Notas clínicas (editable)
notes?: string[]; // Notas importantes
// Puntos críticos TES (editable)
criticalPoints?: string[]; // Errores críticos a evitar
// Fuente (editable)
source?: string; // "BLOQUE_06_1_VADEMECUM_OPERATIVO.md"
// Metadatos del sistema
metadata: ContentMetadata;
}
Ejemplo JSON:
{
"id": "adrenalina",
"version": 5,
"genericName": "Adrenalina (Epinefrina)",
"tradeName": "Adrenalina Braun®",
"category": "cardiovascular",
"presentation": "ANAFILAXIA: Ampolla 1 mg/1 ml (1:1000)...",
"adultDose": "ANAFILAXIA: 0.5 mg IM (0.5 ml de ampolla 1:1000)...",
"pediatricDose": "ANAFILAXIA: 0.01 mg/kg IM (Máx. 0.5 mg)...",
"routes": ["IM", "IV", "IO"],
"dilution": "ANAFILAXIA: Sin diluir. PCR: Sin diluir...",
"indications": [
"Anafilaxia grave: Reacción alérgica sistémica...",
"Parada cardiorrespiratoria: Cualquier ritmo..."
],
"contraindications": [
"No hay contraindicaciones absolutas en emergencias vitales"
],
"sideEffects": ["Temblor", "Taquicardia", "Palidez"],
"notes": [
"⚠️ CONCENTRACIÓN CRÍTICA: 1:1000 (1 mg/ml) para Anafilaxia IM..."
],
"criticalPoints": [
"⚠️ ERROR CRÍTICO: Confundir 1:1000 con 1:10.000..."
],
"source": "BLOQUE_06_1_VADEMECUM_OPERATIVO.md",
"metadata": {...}
}
2.3 Guía Formativa (Sección)
interface GuideSection {
// Identificación (inmutable)
guideId: string; // "rcp-adulto-svb"
sectionNumber: number; // 1-8
version: number; // 1, 2, 3...
// Contenido (editable)
title: string; // "Introducción y Contexto"
content: string; // Markdown completo de la sección
// Metadatos del sistema
metadata: ContentMetadata;
}
Ejemplo JSON:
{
"guideId": "rcp-adulto-svb",
"sectionNumber": 1,
"version": 2,
"title": "Introducción y Contexto",
"content": "# SECCIÓN 1: Introducción y Contexto\n\n**Guía de Refuerzo — RCP Adulto SVB**\n\n---\n\n## Bloque 1: Texto Explicativo\n\n...",
"metadata": {...}
}
2.4 Manual Completo (Bloque)
interface ManualBlock {
// Identificación (inmutable)
blockId: string; // "bloque-04-1"
version: number; // 1, 2, 3...
// Contenido (editable)
title: string; // "RCP Adultos"
content: string; // Markdown completo del bloque
// Estructura
parentBlock?: string; // Bloque padre (si aplica)
order: number; // Orden dentro del bloque padre
// Metadatos del sistema
metadata: ContentMetadata;
}
2.5 Metadatos Comunes
interface ContentMetadata {
// Validación clínica
validatedBy?: string; // ID del validador (ej: "dr-juan-perez")
validatedAt?: Date; // Fecha de validación ISO 8601
clinicalSource?: string; // "ERC 2021", "AHA 2020", "SEMES 2022"
validationStatus: 'draft' | 'pending' | 'validated' | 'rejected';
// Control de calidad
reviewedBy?: string; // ID del revisor
reviewedAt?: Date; // Fecha de revisión
qualityScore?: number; // 0-100 (opcional)
// Historial
createdAt: Date; // Fecha de creación ISO 8601
createdBy: string; // ID del creador
updatedAt: Date; // Fecha de última actualización
updatedBy: string; // ID del último editor
// Historial de cambios
changeLog: ChangeLogEntry[]; // Array de cambios
}
interface ChangeLogEntry {
version: number; // Versión del cambio
timestamp: Date; // Fecha del cambio
userId: string; // ID del usuario que hizo el cambio
action: 'create' | 'update' | 'delete' | 'validate' | 'reject';
changes: {
field: string; // Campo modificado
oldValue?: any; // Valor anterior (si aplica)
newValue?: any; // Valor nuevo
}[];
comment?: string; // Comentario del cambio
}
3️⃣ RELACIONES ENTRE ENTIDADES
Relación: Protocolo → Fármacos
Tipo: Referencia (no embebida)
Implementación:
// En Protocol
drugs?: string[]; // ["adrenalina", "amiodarona"]
// Resolución
const protocolDrugs = protocol.drugs?.map(drugId =>
drugs.find(d => d.id === drugId)
);
Ventaja: Si se actualiza un fármaco, todos los protocolos que lo referencian se actualizan automáticamente.
Relación: Protocolo → Guía Formativa
Tipo: Mapeo explícito (no embebida)
Implementación:
// En protocol-guide-manual-mapping.ts
{
protocoloId: "rcp-adulto-svb",
guiaId: "rcp-adulto-svb",
tieneGuia: true
}
Ventaja: Permite que protocolos y guías evolucionen independientemente.
Relación: Guía → Manual
Tipo: Mapeo explícito (no embebida)
Implementación:
// En protocol-guide-manual-mapping.ts
{
guiaId: "rcp-adulto-svb",
manualBloque: "BLOQUE_04_1",
tieneManual: true
}
4️⃣ SISTEMA DE VERSIONADO
Versionado de Contenido
Estrategia: Versionado incremental por entidad
Reglas:
- Cada cambio incrementa la versión
- Versiones anteriores se mantienen (historial)
- Solo la última versión validada es "activa"
- Rollback permite restaurar versiones anteriores
Ejemplo:
Protocolo: rcp-adulto-svb
v1 (2024-12-01): Creación inicial
v2 (2025-01-10): Actualización de pasos según ERC 2021
v3 (2025-01-15): Añadida advertencia sobre profundidad
v3 (activa) ← Versión actual
Comparación de Versiones
Funcionalidad: Permite ver diferencias entre versiones
Implementación:
interface VersionDiff {
version1: number;
version2: number;
changes: {
field: string;
oldValue: any;
newValue: any;
}[];
}
5️⃣ VALIDACIÓN Y ESQUEMAS
Esquemas de Validación
Propuesta: JSON Schema o Zod (TypeScript)
Ejemplo con Zod:
import { z } from 'zod';
const ProtocolSchema = z.object({
id: z.string().regex(/^[a-z0-9-]+$/),
version: z.number().int().positive(),
title: z.string().min(1).max(200),
steps: z.array(z.string().min(1)).min(1),
warnings: z.array(z.string()).max(5),
metadata: ContentMetadataSchema
});
Validación en Panel
Antes de guardar:
- Validar estructura (schema)
- Validar reglas de negocio (ej: máx. 5 advertencias)
- Validar referencias (ej: fármacos deben existir)
- Si pasa validación → Permitir guardar
- Si falla → Mostrar errores
6️⃣ ALMACENAMIENTO
Opción 1: Archivos JSON (Git-based)
Estructura:
content/
├── protocols/
│ ├── rcp-adulto-svb.json
│ ├── rcp-adulto-sva.json
│ └── ...
├── drugs/
│ ├── adrenalina.json
│ ├── amiodarona.json
│ └── ...
├── guides/
│ ├── rcp-adulto-svb/
│ │ ├── section-01.json
│ │ ├── section-02.json
│ │ └── ...
│ └── ...
└── manual/
├── bloque-04-1.json
└── ...
Ventaja: Versionado automático con Git, historial completo
Opción 2: Base de Datos
Tablas propuestas:
-- Protocolos
CREATE TABLE protocols (
id VARCHAR(100) PRIMARY KEY,
version INT NOT NULL,
content JSONB NOT NULL,
metadata JSONB NOT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- Fármacos
CREATE TABLE drugs (
id VARCHAR(100) PRIMARY KEY,
version INT NOT NULL,
content JSONB NOT NULL,
metadata JSONB NOT NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP
);
-- Guías (secciones)
CREATE TABLE guide_sections (
guide_id VARCHAR(100),
section_number INT,
version INT NOT NULL,
content JSONB NOT NULL,
metadata JSONB NOT NULL,
PRIMARY KEY (guide_id, section_number, version)
);
-- Historial de versiones
CREATE TABLE content_versions (
id SERIAL PRIMARY KEY,
content_type VARCHAR(50), -- 'protocol', 'drug', 'guide', 'manual'
content_id VARCHAR(100),
version INT,
content JSONB,
created_at TIMESTAMP,
created_by VARCHAR(100)
);
7️⃣ MIGRACIÓN DESDE ESTRUCTURA ACTUAL
Mapeo de Archivos Actuales
Protocolos:
src/data/procedures.ts
→ content/protocols/*.json
Fármacos:
src/data/drugs.ts
→ content/drugs/*.json
Guías:
docs/consolidado/SECCION_XX_*.md
→ content/guides/{guideId}/section-{num}.json
Manual:
public/manual/BLOQUE_XX_*/*.md
→ content/manual/bloque-{id}.json
Script de Migración (Conceptual)
// 1. Leer procedures.ts
const procedures = require('./src/data/procedures.ts');
// 2. Convertir a formato JSON
procedures.forEach(proc => {
const protocolJson = {
id: proc.id,
version: 1,
...proc,
metadata: {
validationStatus: 'validated',
createdAt: new Date().toISOString(),
createdBy: 'migration-script',
changeLog: []
}
};
// 3. Guardar en content/protocols/
fs.writeFileSync(
`content/protocols/${proc.id}.json`,
JSON.stringify(protocolJson, null, 2)
);
});
📋 RESUMEN EJECUTIVO
Modelo de datos:
- ✅ IDs estables e inmutables
- ✅ Versionado incremental
- ✅ Separación contenido/metadatos
- ✅ Relaciones por referencia (no embebidas)
Entidades principales:
- Protocol (Protocolo Operativo)
- Drug (Fármaco)
- GuideSection (Sección de Guía)
- ManualBlock (Bloque de Manual)
Metadatos comunes:
- Validación clínica
- Control de calidad
- Historial de cambios
- Auditoría
Almacenamiento:
- Opción 1: Archivos JSON (Git-based) - MVP
- Opción 2: Base de datos - Escala
Este documento es la especificación técnica para implementación futura del sistema de gestión de contenido.