15 KiB
📐 MODELO DE DATOS CANÓNICO - SISTEMA DE CONTENIDO
Versión: 1.0.0
Fecha: 2025-01-06
Estado: FASE 4 - Base de Contenido
🎯 PROPÓSITO
Este documento define el modelo de datos canónico para el sistema de gestión de contenido externo de la app TES.
Características:
- ✅ Completamente desacoplado del código de la app
- ✅ No modifica
procedures.ts,drugs.tsni componentes existentes - ✅ Diseñado para durabilidad (10+ años)
- ✅ Optimizado para uso real de TES en guardia
- ✅ Soporta formación continua y referencia profesional
🏗️ ARQUITECTURA DEL MODELO
┌─────────────────────────────────────────┐
│ CONTENT ITEM (Base) │
│ ┌─────────┬─────────┬──────────────┐ │
│ │Protocol │ Guide │ Manual │ │
│ │ Drug │ Checklist│ │ │
│ └─────────┴─────────┴──────────────┘ │
└─────────────────────────────────────────┘
│
│ (asociación)
▼
┌─────────────────────────────────────────┐
│ MEDIA RESOURCE │
│ ┌─────────┬─────────┐ │
│ │ Image │ Video │ │
│ └─────────┴─────────┘ │
└─────────────────────────────────────────┘
│
│ (versión)
▼
┌─────────────────────────────────────────┐
│ CONTENT VERSION │
│ (Historial y rollback) │
└─────────────────────────────────────────┘
│
│ (auditoría)
▼
┌─────────────────────────────────────────┐
│ AUDIT LOG │
│ (Trazabilidad completa) │
└─────────────────────────────────────────┘
📋 ENTIDADES PRINCIPALES
1. ContentItem
Descripción: Entidad base que representa todo el contenido del sistema.
Tipos:
protocol: Protocolos operativos (RCP, OVACE, ABCDE, etc.)guide: Guías formativas (8 secciones)manual: Capítulos del manual completodrug: Fármacos del vademécumchecklist: Checklists reutilizables
Campos Clave:
| Campo | Tipo | Descripción | Ejemplo |
|---|---|---|---|
id |
UUID | Identificador único | 550e8400-e29b-41d4-a716-446655440000 |
type |
enum | Tipo de contenido | protocol |
slug |
string | Slug para URLs | rcp-adulto-svb |
title |
string | Título completo | RCP Adulto - Soporte Vital Básico |
clinical_context |
enum | Contexto clínico | RCP |
usage_type |
enum | Tipo de uso | operativo |
priority |
enum | Prioridad clínica | critica |
status |
enum | Estado | published |
source_guideline |
enum | Fuente clínica | ERC |
version |
string | Versión semántica | 1.0.0 |
content |
JSONB | Contenido específico | Ver secciones siguientes |
Ejemplo Real: RCP Adulto SVB
{
id: "550e8400-e29b-41d4-a716-446655440000",
type: "protocol",
slug: "rcp-adulto-svb",
title: "RCP Adulto - Soporte Vital Básico",
short_title: "RCP Adulto SVB",
description: "Protocolo de reanimación cardiopulmonar básica en adultos",
clinical_context: "RCP",
usage_type: "operativo",
priority: "critica",
status: "published",
source_guideline: "ERC",
source_year: 2021,
source_url: "https://www.erc.edu/...",
version: "1.0.0",
latest_version: "1.0.0",
content: {
// Ver ProtocolContent
},
tags: ["rcp", "svb", "adulto", "emergencia", "critica"],
category: "soporte_vital",
created_at: "2025-01-01T00:00:00Z",
updated_at: "2025-01-06T12:00:00Z"
}
2. ProtocolContent
Descripción: Contenido específico para protocolos operativos.
Estructura:
interface ProtocolContent {
steps: ProtocolStep[]; // Pasos operativos ordenados
checklist?: { // Checklist integrado
enabled: boolean;
title?: string;
items: ChecklistItem[];
};
inline_doses?: InlineDose[]; // Dosis inline
context_tools?: ContextTool[]; // Herramientas de contexto
clinical_sources?: ClinicalSource[]; // Fuentes clínicas
warnings?: string[]; // Advertencias críticas
key_points?: string[]; // Puntos clave
equipment?: string[]; // Equipamiento necesario
drugs?: string[]; // Referencias a fármacos
age_group?: 'adulto' | 'pediatrico' | 'neonatal' | 'todos';
estimated_duration?: string; // Duración estimada
}
Ejemplo: Paso de Protocolo
{
order: 7,
text: "Iniciar compresiones torácicas: 30 compresiones",
critical: true,
equipment: ["DEA"],
time_estimate: "20-30s",
notes: "Profundidad 5-6 cm, frecuencia 100-120/min"
}
3. GuideContent
Descripción: Contenido específico para guías formativas (8 secciones).
Estructura:
interface GuideContent {
sections: GuideSection[]; // Siempre 8 secciones
related_protocol_id?: string; // Protocolo operativo relacionado
related_manual_ids?: string[]; // Capítulos de manual relacionados
learning_objectives?: string[]; // Objetivos de aprendizaje
prerequisites?: string[]; // Prerrequisitos
target_audience?: string[]; // Audiencia objetivo
estimated_time?: string; // Tiempo total estimado
}
Ejemplo: Sección de Guía
{
numero: 4,
titulo: "Medios Visuales y Demostración",
markdown: "# Medios Visuales...",
estimated_time: "10 min",
resources: {
images: ["660e8400-..."],
videos: ["660e8400-..."],
links: [
{ title: "ERC Guidelines", url: "https://..." }
]
}
}
4. MediaResource
Descripción: Recurso multimedia (imagen o vídeo).
Tipos:
image: Infografías, diagramas, fotografíasvideo: Vídeos demostrativos, formativos
Campos Clave:
| Campo | Tipo | Descripción | Ejemplo |
|---|---|---|---|
id |
UUID | Identificador único | 660e8400-... |
type |
enum | Tipo de recurso | image |
file_url |
string | URL completa | https://...supabase.co/... |
title |
string | Título | Posición de Manos - RCP Adulto |
alt_text |
string | Texto alternativo | Posición correcta de manos... |
priority |
enum | Prioridad | critica |
usage_type |
array | Tipos de uso | ["operativo", "formativo"] |
tags |
array | Tags | ["rcp", "adulto", "compresiones"] |
Ejemplo: Imagen
{
id: "660e8400-e29b-41d4-a716-446655440000",
type: "image",
file_url: "https://[project].supabase.co/storage/v1/object/public/infografias/rcp/rcp_posicion_manos_adulto.png",
filename: "rcp_posicion_manos_adulto.png",
path: "/assets/infografias/rcp/rcp_posicion_manos_adulto.png",
title: "Posición de Manos - RCP Adulto",
alt_text: "Posición correcta de manos para compresiones torácicas RCP adulto",
caption: "Posición correcta de manos para compresiones torácicas",
tags: ["rcp", "adulto", "compresiones", "posicion", "operativo"],
block: "bloque-4-soporte-vital",
priority: "critica",
usage_type: ["operativo"],
width: 1200,
height: 800,
format: "png",
file_size: 245678,
status: "published"
}
Ejemplo: Vídeo
{
id: "660e8400-e29b-41d4-a716-446655440002",
type: "video",
file_url: "https://[project].supabase.co/storage/v1/object/public/videos/rcp/rcp_adulto_svb.mp4",
thumbnail_url: "https://[project].supabase.co/storage/v1/object/public/videos/rcp/rcp_adulto_svb_thumb.jpg",
filename: "rcp_adulto_svb.mp4",
path: "/assets/videos/rcp/rcp_adulto_svb.mp4",
title: "RCP Adulto SVB - Técnica Completa",
alt_text: "Vídeo demostrativo RCP Adulto SVB",
caption: "Técnica completa de RCP Adulto SVB",
tags: ["rcp", "adulto", "svb", "video", "operativo"],
block: "bloque-4-soporte-vital",
priority: "critica",
usage_type: ["operativo"],
duration_seconds: 45,
video_format: "mp4",
file_size: 5242880,
status: "published"
}
5. ContentResourceAssociation
Descripción: Asociación entre contenido y recursos multimedia.
Propósito:
- Define dónde se muestra un recurso en un contenido
- Permite múltiples asociaciones (mismo recurso en diferentes secciones)
- Define prioridad y criticidad
Ejemplo:
{
id: "770e8400-e29b-41d4-a716-446655440000",
content_item_id: "550e8400-e29b-41d4-a716-446655440000", // RCP Adulto SVB
media_resource_id: "660e8400-e29b-41d4-a716-446655440000", // Imagen posición manos
section: "pasos",
position: 7,
placement: "inline",
caption: "Posición correcta de manos para compresiones",
is_critical: true,
priority: "critica"
}
Secciones Comunes:
pasos: En pasos de protocolochecklist: En checklist integradoguia_seccion_1aguia_seccion_8: En secciones de guíamanual_intro: En introducción de manualmanual_contenido: En contenido principal de manual
6. ContentVersion
Descripción: Versión histórica de un ContentItem.
Propósito:
- Versionado semántico (1.2.3)
- Rollback a versiones anteriores
- Historial de cambios
Ejemplo:
{
id: "880e8400-e29b-41d4-a716-446655440000",
content_item_id: "550e8400-e29b-41d4-a716-446655440000",
version: "1.1.0",
content: {
// Contenido de esta versión
},
change_summary: "Añadido paso de verificación de seguridad, actualizado checklist",
is_breaking: false,
created_by: "editor-123",
created_at: "2025-01-10T10:00:00Z",
is_active: false
}
7. AuditLog
Descripción: Registro de auditoría de todas las acciones.
Propósito:
- Trazabilidad completa
- Cumplimiento normativo
- Análisis de uso
Ejemplo:
{
id: "990e8400-e29b-41d4-a716-446655440000",
entity_type: "content_item",
entity_id: "550e8400-e29b-41d4-a716-446655440000",
action: "publish",
user_id: "user-456",
user_role: "editor",
metadata: {
previous_status: "approved",
new_status: "published",
version: "1.0.0"
},
timestamp: "2025-01-06T12:00:00Z"
}
🔗 RELACIONES ENTRE ENTIDADES
Diagrama de Relaciones
ContentItem (1) ──< (N) ContentResourceAssociation (N) >── (1) MediaResource
│
│ (1)
│
└──< (N) ContentVersion
ContentItem (1) ──< (N) AuditLog
MediaResource (1) ──< (N) AuditLog
ContentVersion (1) ──< (N) AuditLog
Relaciones Bidireccionales
Protocolo ↔ Guía:
- Protocolo tiene
related_guide_ids[] - Guía tiene
related_protocol_id
Manual ↔ Protocolo/Guía:
- Manual tiene
related_protocol_ids[]yrelated_guide_ids[] - Protocolo/Guía tienen
related_manual_ids[]
📊 EJEMPLOS REALES COMPLETOS
Ejemplo 1: Protocolo RCP Adulto SVB
Ver docs/CONTENT_PACK_SPEC.md sección "Ejemplo Completo"
Ejemplo 2: Guía ABCDE Formativa
{
id: "550e8400-e29b-41d4-a716-446655440010",
type: "guide",
slug: "abcde-operativo",
title: "ABCDE Operativo",
description: "Guía de refuerzo para comprender el enfoque ABCDE",
clinical_context: "ABCDE",
usage_type: "formativo",
priority: "alta",
status: "published",
source_guideline: "MANUAL_TES_DIGITAL",
version: "1.0.0",
content: {
sections: [
{
numero: 1,
titulo: "Introducción y Contexto",
markdown: "# Introducción...",
resources: {
images: ["660e8400-..."] // Infografía introducción
}
},
// ... 7 secciones más
],
related_protocol_id: "550e8400-...", // ABCDE Operativo
learning_objectives: [
"Comprender ABCDE como estructura mental",
"Aplicar ABCDE en todas las emergencias"
]
},
related_protocol_ids: ["550e8400-..."],
tags: ["abcde", "evaluacion", "formacion"]
}
Ejemplo 3: Fármaco Adrenalina
{
id: "550e8400-e29b-41d4-a716-446655440020",
type: "drug",
slug: "adrenalina",
title: "Adrenalina (Epinefrina)",
description: "Fármaco de primera línea en PCR y anafilaxia",
clinical_context: "FARMACOLOGIA",
usage_type: "referencia",
priority: "critica",
status: "published",
source_guideline: "ERC",
source_year: 2021,
version: "1.0.0",
content: {
generic_name: "Adrenalina",
trade_name: "Adrenalina",
category: "cardiovascular",
presentation: "Ampollas 1mg/1ml",
adult_dose: "1mg IV cada 3-5 min (PCR)",
pediatric_dose: "0.01 mg/kg IV cada 3-5 min (PCR)",
routes: ["IV", "IO", "IM"],
indications: ["PCR", "Anafilaxia", "Shock anafiláctico"],
contraindications: ["Hipersensibilidad"],
side_effects: ["Taquicardia", "Hipertensión"],
notes: [
"Primera línea en PCR",
"En anafilaxia: 0.3-0.5 mg IM"
],
critical_points: [
"NO diluir en PCR",
"Administrar lo antes posible"
]
},
tags: ["adrenalina", "epinefrina", "pcr", "anafilaxia", "critica"]
}
✅ VALIDACIONES Y CONSTRAINTS
Validaciones de Contenido
-
ContentItem:
slugdebe ser únicoversiondebe seguir semver (1.2.3)statusdebe ser válido según flujoclinical_contextdebe ser válido
-
ProtocolContent:
stepsdebe tener al menos 1 pasosteps[].orderdebe ser secuencial (1, 2, 3...)checklist.itemsdebe tener al menos 1 item sienabled: true
-
GuideContent:
sectionsdebe tener exactamente 8 seccionessections[].numerodebe ser 1-8sections[].markdownno debe estar vacío
-
MediaResource:
file_urldebe ser URL válidaalt_textno debe estar vacío (accesibilidad)- Si
type: 'video',duration_secondsdebe estar presente
-
ContentResourceAssociation:
content_item_iddebe existirmedia_resource_iddebe existirsection+positiondebe ser único porcontent_item_id
🔍 BÚSQUEDA Y FILTRADO
Índices Recomendados
-
Búsqueda de texto:
title,description,tags→ Índice GIN (full-text search)
-
Filtrado por tipo:
type,usage_type,status,priority→ Índices B-tree
-
Búsqueda por contexto:
clinical_context,category→ Índices B-tree
-
Relaciones:
related_*_ids→ Índices GIN (array search)
📚 REFERENCIAS
- Interfaces TypeScript:
admin-panel/shared/types/content-canonical.ts - Schema SQL:
docs/SUPABASE_SCHEMA.sql - Content Pack Spec:
docs/CONTENT_PACK_SPEC.md - Plan Técnico:
docs/PLAN_TECNICO_SISTEMA_CONTENIDO.md
Fin del Documento