-- ============================================ -- MIGRACIÓN 002: Esquema de Vademécum TES (Drugs) -- ============================================ -- -- Crea las tablas necesarias para el módulo de vademécum TES -- Basado en: docs/VADEMECUM_COMPLETO_TES.md -- -- IMPORTANTE: Este módulo es SOLO capa de REFERENCIA -- NO modifica tablas existentes, solo añade nuevas -- -- ============================================ -- ENUM: drug_line (Primera línea / Segunda línea) -- ============================================ CREATE TYPE tes_content.drug_line AS ENUM ( 'first', -- Primera línea (uso frecuente) 'second' -- Segunda línea (uso menos frecuente) ); -- ============================================ -- ENUM: drug_frequency (Frecuencia de uso) -- ============================================ CREATE TYPE tes_content.drug_frequency AS ENUM ( 'high', -- Uso frecuente 'medium', -- Uso medio 'low' -- Uso poco frecuente ); -- ============================================ -- TABLA: drugs -- ============================================ CREATE TABLE tes_content.drugs ( -- Identificación id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), slug TEXT UNIQUE NOT NULL, -- Identificador legible único (ej: "adrenalina") -- Información básica generic_name TEXT NOT NULL, -- Nombre genérico (ej: "Adrenalina") trade_name TEXT, -- Nombre comercial (ej: "Adrenalina 1mg/1ml") -- Clasificación category TEXT NOT NULL, -- Categoría farmacológica (ej: "cardiovascular", "respiratorio") line tes_content.drug_line NOT NULL, -- Primera línea o segunda línea frequency tes_content.drug_frequency NOT NULL, -- Frecuencia de uso -- Presentación y dosificación presentation TEXT NOT NULL, -- Presentación (ej: "1mg/1ml ampolla") adult_dose TEXT NOT NULL, -- Dosis adulto (ej: "1mg IV/IO cada 3-5 min") pediatric_dose TEXT, -- Dosis pediátrica (nullable pero validable) routes TEXT[] DEFAULT '{}', -- Vías de administración (ej: ["IV", "IO", "IM"]) dilution TEXT, -- Dilución (si aplica) -- Indicaciones y contraindicaciones indications TEXT[] DEFAULT '{}', -- Indicaciones clínicas contraindications TEXT[] DEFAULT '{}', -- Contraindicaciones side_effects TEXT, -- Efectos adversos antidote TEXT, -- Antídoto (si aplica) -- Información específica TES notes TEXT[] DEFAULT '{}', -- Notas importantes critical_points TEXT[] DEFAULT '{}', -- Puntos críticos para TES source TEXT, -- Fuente (ej: "Manual TES Digital") -- Estado y validación status tes_content.content_status NOT NULL DEFAULT 'draft', -- Versionado version TEXT NOT NULL DEFAULT '1.0.0', latest_version TEXT NOT NULL DEFAULT '1.0.0', current_version_id UUID, -- FK a drug_versions (versión actual) -- Auditoría created_by UUID NOT NULL REFERENCES tes_content.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_by UUID REFERENCES tes_content.users(id), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), published_by UUID REFERENCES tes_content.users(id), published_at TIMESTAMPTZ, -- Metadatos adicionales metadata JSONB DEFAULT '{}', -- Constraints CONSTRAINT valid_version_format CHECK (version ~ '^\d+\.\d+\.\d+$'), CONSTRAINT valid_latest_version_format CHECK (latest_version ~ '^\d+\.\d+\.\d+$'), CONSTRAINT pediatric_dose_required_when_published CHECK ( (status = 'published'::tes_content.content_status AND pediatric_dose IS NOT NULL) OR (status != 'published'::tes_content.content_status) ) ); -- ============================================ -- TABLA: drug_versions -- ============================================ CREATE TABLE tes_content.drug_versions ( -- Identificación id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), drug_id UUID NOT NULL REFERENCES tes_content.drugs(id) ON DELETE CASCADE, version TEXT NOT NULL, -- Versión semántica (ej: "1.2.3") -- Snapshot completo del fármaco drug_snapshot JSONB NOT NULL, -- Snapshot completo del fármaco en esta versión -- Cambios change_summary TEXT NOT NULL, -- Resumen de cambios change_details JSONB, -- Detalles de cambios (campos modificados, valores antiguos/nuevos) -- Tipo de cambio change_type TEXT NOT NULL DEFAULT 'patch', -- 'major' | 'minor' | 'patch' is_breaking BOOLEAN DEFAULT false, -- ¿Es cambio incompatible? -- Auditoría created_by UUID NOT NULL REFERENCES tes_content.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), published_at TIMESTAMPTZ, published_by UUID REFERENCES tes_content.users(id), -- Estado is_active BOOLEAN NOT NULL DEFAULT false, -- ¿Es la versión activa? -- Constraints CONSTRAINT valid_version_format CHECK (version ~ '^\d+\.\d+\.\d+$'), CONSTRAINT unique_drug_version UNIQUE (drug_id, version) ); -- ============================================ -- ÍNDICES -- ============================================ -- drugs CREATE INDEX idx_drugs_slug ON tes_content.drugs(slug); CREATE INDEX idx_drugs_category ON tes_content.drugs(category); CREATE INDEX idx_drugs_line ON tes_content.drugs(line); CREATE INDEX idx_drugs_frequency ON tes_content.drugs(frequency); CREATE INDEX idx_drugs_status ON tes_content.drugs(status); CREATE INDEX idx_drugs_generic_name ON tes_content.drugs USING GIN(to_tsvector('spanish', generic_name)); CREATE INDEX idx_drugs_published ON tes_content.drugs(status, updated_at DESC) WHERE status = 'published'; -- drug_versions CREATE INDEX idx_drug_versions_drug_id ON tes_content.drug_versions(drug_id); CREATE INDEX idx_drug_versions_version ON tes_content.drug_versions(version); CREATE INDEX idx_drug_versions_active ON tes_content.drug_versions(is_active) WHERE is_active = true; CREATE INDEX idx_drug_versions_created_at ON tes_content.drug_versions(created_at DESC); -- ============================================ -- TRIGGERS -- ============================================ -- Trigger para actualizar updated_at automáticamente CREATE TRIGGER update_drugs_updated_at BEFORE UPDATE ON tes_content.drugs FOR EACH ROW EXECUTE FUNCTION tes_content.update_updated_at_column(); -- ============================================ -- VISTAS ÚTILES -- ============================================ -- Vista: Fármacos publicados CREATE OR REPLACE VIEW tes_content.published_drugs AS SELECT d.id, d.slug, d.generic_name, d.trade_name, d.category, d.line, d.frequency, d.presentation, d.adult_dose, d.pediatric_dose, d.routes, d.dilution, d.indications, d.contraindications, d.side_effects, d.antidote, d.notes, d.critical_points, d.source, d.version, d.created_at, d.updated_at FROM tes_content.drugs d WHERE d.status = 'published'::tes_content.content_status AND d.version = d.latest_version; -- Vista: Estadísticas de fármacos CREATE OR REPLACE VIEW tes_content.drug_stats AS SELECT category, line, frequency, status, COUNT(*) as count, COUNT(CASE WHEN status = 'published' THEN 1 END) as published_count FROM tes_content.drugs GROUP BY category, line, frequency, status; -- ============================================ -- COMENTARIOS -- ============================================ COMMENT ON TABLE tes_content.drugs IS 'Vademécum TES: Fármacos de referencia para técnicos en emergencias sanitarias'; COMMENT ON COLUMN tes_content.drugs.line IS 'Primera línea (uso frecuente) o segunda línea (uso menos frecuente)'; COMMENT ON COLUMN tes_content.drugs.frequency IS 'Frecuencia de uso: alta, media o baja'; COMMENT ON COLUMN tes_content.drugs.pediatric_dose IS 'Dosis pediátrica. Obligatoria cuando status = published'; COMMENT ON TABLE tes_content.drug_versions IS 'Versiones históricas de fármacos para versionado y rollback'; -- ============================================ -- FIN DE LA MIGRACIÓN -- ============================================