codigo0/backend/database/migrations/002_create_drugs_schema.sql

218 lines
8 KiB
SQL

-- ============================================
-- 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
-- ============================================