# 📊 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 ```typescript 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:** ```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) ```typescript 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:** ```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) ```typescript 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:** ```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) ```typescript 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 ```typescript 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:** ```typescript // 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:** ```typescript // 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:** ```typescript // 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:** 1. Cada cambio incrementa la versión 2. Versiones anteriores se mantienen (historial) 3. Solo la última versión validada es "activa" 4. 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:** ```typescript 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:** ```typescript 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:** 1. Validar estructura (schema) 2. Validar reglas de negocio (ej: máx. 5 advertencias) 3. Validar referencias (ej: fármacos deben existir) 4. Si pasa validación → Permitir guardar 5. 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:** ```sql -- 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) ```typescript // 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.**