codigo0/docs/CONTENT_MODEL.md

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.ts ni 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 completo
  • drug: Fármacos del vademécum
  • checklist: 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ías
  • video: 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 protocolo
  • checklist: En checklist integrado
  • guia_seccion_1 a guia_seccion_8: En secciones de guía
  • manual_intro: En introducción de manual
  • manual_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[] y related_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

  1. ContentItem:

    • slug debe ser único
    • version debe seguir semver (1.2.3)
    • status debe ser válido según flujo
    • clinical_context debe ser válido
  2. ProtocolContent:

    • steps debe tener al menos 1 paso
    • steps[].order debe ser secuencial (1, 2, 3...)
    • checklist.items debe tener al menos 1 item si enabled: true
  3. GuideContent:

    • sections debe tener exactamente 8 secciones
    • sections[].numero debe ser 1-8
    • sections[].markdown no debe estar vacío
  4. MediaResource:

    • file_url debe ser URL válida
    • alt_text no debe estar vacío (accesibilidad)
    • Si type: 'video', duration_seconds debe estar presente
  5. ContentResourceAssociation:

    • content_item_id debe existir
    • media_resource_id debe existir
    • section + position debe ser único por content_item_id

🔍 BÚSQUEDA Y FILTRADO

Índices Recomendados

  1. Búsqueda de texto:

    • title, description, tags → Índice GIN (full-text search)
  2. Filtrado por tipo:

    • type, usage_type, status, priority → Índices B-tree
  3. Búsqueda por contexto:

    • clinical_context, category → Índices B-tree
  4. 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