clinica-veterinaria/database/schemas/01-veterinaria-schema-ddl.sql
rckrdmrd 6e195553d2 feat: Initial commit - clinica-veterinaria
ERP especializado para clínicas veterinarias.

Estructura inicial:
- database/ (PostgreSQL DDL)
- docs/ (Documentación)
- orchestration/ (Sistema NEXUS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:42:03 -06:00

388 lines
15 KiB
SQL

-- ============================================================================
-- VETERINARIA SCHEMA - Especialización de ERP-Clínicas
-- Clínica Veterinaria
-- ============================================================================
-- Fecha: 2026-01-04
-- Versión: 1.0
-- Hereda de: erp-clinicas FASE-8
-- ============================================================================
-- Schema
CREATE SCHEMA IF NOT EXISTS veterinaria;
-- ============================================================================
-- ENUMS
-- ============================================================================
DO $$ BEGIN
CREATE TYPE veterinaria.sexo_animal AS ENUM ('macho', 'hembra', 'desconocido');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
DO $$ BEGIN
CREATE TYPE veterinaria.estado_hospitalizacion AS ENUM (
'ingresado', 'en_tratamiento', 'estable', 'critico', 'alta', 'fallecido'
);
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;
-- ============================================================================
-- CATÁLOGOS
-- ============================================================================
-- Especies
CREATE TABLE IF NOT EXISTS veterinaria.especies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
nombre VARCHAR(50) NOT NULL,
nombre_cientifico VARCHAR(100),
descripcion TEXT,
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.especies IS 'Catálogo de especies animales';
-- Razas
CREATE TABLE IF NOT EXISTS veterinaria.razas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
especie_id UUID NOT NULL REFERENCES veterinaria.especies(id) ON DELETE CASCADE,
nombre VARCHAR(100) NOT NULL,
descripcion TEXT,
tamanio_promedio VARCHAR(20), -- 'pequeño', 'mediano', 'grande', 'gigante'
peso_promedio_kg NUMERIC(5,2),
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.razas IS 'Catálogo de razas por especie';
-- Vacunas
CREATE TABLE IF NOT EXISTS veterinaria.vacunas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
nombre VARCHAR(100) NOT NULL,
descripcion TEXT,
especie_id UUID REFERENCES veterinaria.especies(id),
laboratorio VARCHAR(100),
dosis_ml NUMERIC(5,2),
intervalo_refuerzo_dias INTEGER,
es_obligatoria BOOLEAN DEFAULT false,
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.vacunas IS 'Catálogo de vacunas veterinarias';
-- ============================================================================
-- TABLAS PRINCIPALES
-- ============================================================================
-- Propietarios (dueños de mascotas)
CREATE TABLE IF NOT EXISTS veterinaria.propietarios (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
partner_id UUID, -- Referencia opcional a core.partners
nombre VARCHAR(100) NOT NULL,
apellidos VARCHAR(100),
telefono VARCHAR(20),
telefono_emergencia VARCHAR(20),
email VARCHAR(100),
direccion TEXT,
rfc VARCHAR(13),
-- Control
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.propietarios IS 'Propietarios/dueños de mascotas';
-- Mascotas (pacientes)
CREATE TABLE IF NOT EXISTS veterinaria.mascotas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
propietario_id UUID NOT NULL REFERENCES veterinaria.propietarios(id),
especie_id UUID NOT NULL REFERENCES veterinaria.especies(id),
raza_id UUID REFERENCES veterinaria.razas(id),
-- Datos básicos
nombre VARCHAR(100) NOT NULL,
sexo veterinaria.sexo_animal DEFAULT 'desconocido',
fecha_nacimiento DATE,
edad_aproximada VARCHAR(50), -- "3 años", "6 meses"
color VARCHAR(50),
peso_kg NUMERIC(6,2),
-- Identificación
numero_chip VARCHAR(50),
tiene_chip BOOLEAN DEFAULT false,
-- Estado
esterilizado BOOLEAN DEFAULT false,
fecha_esterilizacion DATE,
-- Notas
alergias TEXT,
condiciones_especiales TEXT,
notas TEXT,
-- Foto
foto_url VARCHAR(255),
-- Control
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.mascotas IS 'Mascotas/pacientes de la clínica veterinaria';
-- Cartilla de vacunación
CREATE TABLE IF NOT EXISTS veterinaria.cartilla_vacunacion (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
mascota_id UUID NOT NULL REFERENCES veterinaria.mascotas(id) ON DELETE CASCADE,
vacuna_id UUID NOT NULL REFERENCES veterinaria.vacunas(id),
veterinario_id UUID, -- Referencia a clinica.doctors
-- Datos de aplicación
fecha_aplicacion DATE NOT NULL,
fecha_proximo_refuerzo DATE,
lote VARCHAR(50),
laboratorio VARCHAR(100),
-- Notas
observaciones TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.cartilla_vacunacion IS 'Historial de vacunación de mascotas';
-- Desparasitaciones
CREATE TABLE IF NOT EXISTS veterinaria.desparasitaciones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
mascota_id UUID NOT NULL REFERENCES veterinaria.mascotas(id) ON DELETE CASCADE,
veterinario_id UUID,
-- Datos
tipo VARCHAR(50) NOT NULL, -- 'interna', 'externa', 'ambas'
producto VARCHAR(100) NOT NULL,
dosis VARCHAR(50),
via_administracion VARCHAR(50),
fecha_aplicacion DATE NOT NULL,
fecha_proxima DATE,
-- Notas
observaciones TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.desparasitaciones IS 'Historial de desparasitaciones';
-- Hospitalización
CREATE TABLE IF NOT EXISTS veterinaria.hospitalizacion (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
mascota_id UUID NOT NULL REFERENCES veterinaria.mascotas(id),
veterinario_id UUID,
consultation_id UUID, -- Referencia a clinica.consultations
-- Datos de ingreso
fecha_ingreso TIMESTAMPTZ NOT NULL DEFAULT NOW(),
motivo_ingreso TEXT NOT NULL,
diagnostico_ingreso TEXT,
-- Ubicación
area VARCHAR(50), -- 'jaula_pequena', 'jaula_grande', 'quirofano', 'uci'
numero_jaula VARCHAR(20),
-- Estado
estado veterinaria.estado_hospitalizacion DEFAULT 'ingresado',
-- Alta
fecha_alta TIMESTAMPTZ,
diagnostico_alta TEXT,
instrucciones_alta TEXT,
-- Control
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.hospitalizacion IS 'Registro de hospitalizaciones';
-- Monitoreo de hospitalización
CREATE TABLE IF NOT EXISTS veterinaria.hospitalizacion_monitoreo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
hospitalizacion_id UUID NOT NULL REFERENCES veterinaria.hospitalizacion(id) ON DELETE CASCADE,
-- Signos vitales
fecha_hora TIMESTAMPTZ NOT NULL DEFAULT NOW(),
peso_kg NUMERIC(6,2),
temperatura NUMERIC(4,1),
frecuencia_cardiaca INTEGER,
frecuencia_respiratoria INTEGER,
-- Alimentación
comio BOOLEAN,
bebio_agua BOOLEAN,
-- Eliminación
orino BOOLEAN,
defeco BOOLEAN,
consistencia_heces VARCHAR(50),
-- Estado
estado_animo VARCHAR(50),
nivel_dolor INTEGER CHECK (nivel_dolor BETWEEN 0 AND 10),
-- Notas
observaciones TEXT,
registrado_por UUID, -- employee_id
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.hospitalizacion_monitoreo IS 'Monitoreo durante hospitalización';
-- Servicios de estética
CREATE TABLE IF NOT EXISTS veterinaria.estetica (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
mascota_id UUID NOT NULL REFERENCES veterinaria.mascotas(id),
estilista_id UUID, -- employee_id
-- Servicios
fecha_servicio TIMESTAMPTZ NOT NULL DEFAULT NOW(),
servicios TEXT[], -- ['baño', 'corte', 'limpieza_oidos', 'corte_unas']
tipo_corte VARCHAR(50),
shampoo_usado VARCHAR(100),
-- Estado
estado VARCHAR(20) DEFAULT 'pendiente', -- 'pendiente', 'en_proceso', 'terminado'
hora_inicio TIME,
hora_fin TIME,
-- Notas
observaciones TEXT,
observaciones_piel TEXT,
-- Precio
precio NUMERIC(10,2),
-- Control
created_at TIMESTAMPTZ DEFAULT NOW()
);
COMMENT ON TABLE veterinaria.estetica IS 'Servicios de estética/grooming';
-- ============================================================================
-- EXTENSIONES A TABLAS DE ERP-CLINICAS
-- ============================================================================
-- Extensión a clinica.consultations (si existe)
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables
WHERE table_schema = 'clinica' AND table_name = 'consultations') THEN
-- mascota_id
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'consultations'
AND column_name = 'mascota_id') THEN
ALTER TABLE clinica.consultations ADD COLUMN mascota_id UUID
REFERENCES veterinaria.mascotas(id);
END IF;
-- peso_actual
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'consultations'
AND column_name = 'peso_actual') THEN
ALTER TABLE clinica.consultations ADD COLUMN peso_actual NUMERIC(6,2);
END IF;
-- temperatura
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_schema = 'clinica' AND table_name = 'consultations'
AND column_name = 'temperatura') THEN
ALTER TABLE clinica.consultations ADD COLUMN temperatura NUMERIC(4,1);
END IF;
END IF;
END $$;
-- ============================================================================
-- ÍNDICES
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_especies_tenant ON veterinaria.especies(tenant_id);
CREATE INDEX IF NOT EXISTS idx_razas_tenant ON veterinaria.razas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_razas_especie ON veterinaria.razas(especie_id);
CREATE INDEX IF NOT EXISTS idx_vacunas_tenant ON veterinaria.vacunas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_vacunas_especie ON veterinaria.vacunas(especie_id);
CREATE INDEX IF NOT EXISTS idx_propietarios_tenant ON veterinaria.propietarios(tenant_id);
CREATE INDEX IF NOT EXISTS idx_propietarios_telefono ON veterinaria.propietarios(telefono);
CREATE INDEX IF NOT EXISTS idx_mascotas_tenant ON veterinaria.mascotas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_mascotas_propietario ON veterinaria.mascotas(propietario_id);
CREATE INDEX IF NOT EXISTS idx_mascotas_especie ON veterinaria.mascotas(especie_id);
CREATE INDEX IF NOT EXISTS idx_mascotas_chip ON veterinaria.mascotas(numero_chip) WHERE numero_chip IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_cartilla_tenant ON veterinaria.cartilla_vacunacion(tenant_id);
CREATE INDEX IF NOT EXISTS idx_cartilla_mascota ON veterinaria.cartilla_vacunacion(mascota_id);
CREATE INDEX IF NOT EXISTS idx_cartilla_fecha ON veterinaria.cartilla_vacunacion(fecha_proximo_refuerzo);
CREATE INDEX IF NOT EXISTS idx_desparasitaciones_tenant ON veterinaria.desparasitaciones(tenant_id);
CREATE INDEX IF NOT EXISTS idx_desparasitaciones_mascota ON veterinaria.desparasitaciones(mascota_id);
CREATE INDEX IF NOT EXISTS idx_hospitalizacion_tenant ON veterinaria.hospitalizacion(tenant_id);
CREATE INDEX IF NOT EXISTS idx_hospitalizacion_mascota ON veterinaria.hospitalizacion(mascota_id);
CREATE INDEX IF NOT EXISTS idx_hospitalizacion_estado ON veterinaria.hospitalizacion(tenant_id, estado);
CREATE INDEX IF NOT EXISTS idx_hospitalizacion_monitoreo_hosp ON veterinaria.hospitalizacion_monitoreo(hospitalizacion_id);
CREATE INDEX IF NOT EXISTS idx_estetica_tenant ON veterinaria.estetica(tenant_id);
CREATE INDEX IF NOT EXISTS idx_estetica_mascota ON veterinaria.estetica(mascota_id);
CREATE INDEX IF NOT EXISTS idx_estetica_fecha ON veterinaria.estetica(fecha_servicio);
-- ============================================================================
-- RLS
-- ============================================================================
ALTER TABLE veterinaria.especies ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.razas ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.vacunas ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.propietarios ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.mascotas ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.cartilla_vacunacion ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.desparasitaciones ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.hospitalizacion ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.hospitalizacion_monitoreo ENABLE ROW LEVEL SECURITY;
ALTER TABLE veterinaria.estetica ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_especies ON veterinaria.especies;
CREATE POLICY tenant_isolation_especies ON veterinaria.especies
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_razas ON veterinaria.razas;
CREATE POLICY tenant_isolation_razas ON veterinaria.razas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_vacunas ON veterinaria.vacunas;
CREATE POLICY tenant_isolation_vacunas ON veterinaria.vacunas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_propietarios ON veterinaria.propietarios;
CREATE POLICY tenant_isolation_propietarios ON veterinaria.propietarios
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_mascotas ON veterinaria.mascotas;
CREATE POLICY tenant_isolation_mascotas ON veterinaria.mascotas
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_cartilla ON veterinaria.cartilla_vacunacion;
CREATE POLICY tenant_isolation_cartilla ON veterinaria.cartilla_vacunacion
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_desparasitaciones ON veterinaria.desparasitaciones;
CREATE POLICY tenant_isolation_desparasitaciones ON veterinaria.desparasitaciones
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_hospitalizacion ON veterinaria.hospitalizacion;
CREATE POLICY tenant_isolation_hospitalizacion ON veterinaria.hospitalizacion
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_hosp_monitoreo ON veterinaria.hospitalizacion_monitoreo;
CREATE POLICY tenant_isolation_hosp_monitoreo ON veterinaria.hospitalizacion_monitoreo
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
DROP POLICY IF EXISTS tenant_isolation_estetica ON veterinaria.estetica;
CREATE POLICY tenant_isolation_estetica ON veterinaria.estetica
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
-- ============================================================================
-- FIN VETERINARIA SCHEMA
-- ============================================================================