- Prefijo v2: CVT - TRACEABILITY-MASTER.yml creado - Listo para integracion como submodulo Workspace: v2.0.0 | SIMCO: v4.0.0
465 lines
18 KiB
PL/PgSQL
465 lines
18 KiB
PL/PgSQL
-- ============================================================================
|
|
-- VETERINARIA SCHEMA - Farmacia (VET-006)
|
|
-- Sistema de gestion de farmacia veterinaria
|
|
-- ============================================================================
|
|
-- Fecha: 2026-01-07
|
|
-- Version: 1.0
|
|
-- Basado en: VET-006-farmacia.md
|
|
-- ============================================================================
|
|
|
|
-- ============================================================================
|
|
-- ENUMS
|
|
-- ============================================================================
|
|
|
|
DO $$ BEGIN
|
|
CREATE TYPE veterinaria.categoria_medicamento AS ENUM (
|
|
'antibiotico',
|
|
'antiparasitario',
|
|
'analgesico',
|
|
'antiinflamatorio',
|
|
'vacuna',
|
|
'vitamina',
|
|
'dermatologico',
|
|
'oftalmico',
|
|
'cardiaco',
|
|
'digestivo',
|
|
'otro'
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
END $$;
|
|
|
|
DO $$ BEGIN
|
|
CREATE TYPE veterinaria.tipo_movimiento_farmacia AS ENUM (
|
|
'entrada',
|
|
'salida',
|
|
'ajuste_positivo',
|
|
'ajuste_negativo',
|
|
'devolucion',
|
|
'merma'
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
END $$;
|
|
|
|
DO $$ BEGIN
|
|
CREATE TYPE veterinaria.fraccion_controlada AS ENUM (
|
|
'no_controlado',
|
|
'fraccion_i',
|
|
'fraccion_ii',
|
|
'fraccion_iii',
|
|
'fraccion_iv'
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
END $$;
|
|
|
|
-- ============================================================================
|
|
-- TABLAS PRINCIPALES
|
|
-- ============================================================================
|
|
|
|
-- Catalogo de medicamentos
|
|
CREATE TABLE IF NOT EXISTS veterinaria.medicamentos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
-- Identificacion
|
|
codigo VARCHAR(50),
|
|
nombre VARCHAR(150) NOT NULL,
|
|
nombre_comercial VARCHAR(150),
|
|
principio_activo VARCHAR(200),
|
|
-- Clasificacion
|
|
categoria veterinaria.categoria_medicamento DEFAULT 'otro',
|
|
-- Presentacion
|
|
presentacion VARCHAR(100), -- 'tabletas', 'inyectable', 'suspension', etc.
|
|
concentracion VARCHAR(50), -- '500mg', '100mg/ml'
|
|
contenido VARCHAR(50), -- '30 tabletas', '100ml'
|
|
-- Fabricante
|
|
laboratorio VARCHAR(100),
|
|
-- Control
|
|
requiere_receta BOOLEAN DEFAULT false,
|
|
controlado BOOLEAN DEFAULT false,
|
|
fraccion_controlada veterinaria.fraccion_controlada DEFAULT 'no_controlado',
|
|
-- Stock
|
|
stock_minimo INTEGER DEFAULT 10,
|
|
stock_actual INTEGER DEFAULT 0,
|
|
-- Precios
|
|
precio_compra NUMERIC(10,2),
|
|
precio_venta NUMERIC(10,2),
|
|
-- Especies aplicables (NULL = todas)
|
|
especies_aplicables UUID[], -- Array de especie_id
|
|
-- Estado
|
|
active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE veterinaria.medicamentos IS 'Catalogo de medicamentos veterinarios';
|
|
|
|
-- Lotes de medicamentos (control de caducidad)
|
|
CREATE TABLE IF NOT EXISTS veterinaria.medicamentos_lotes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
medicamento_id UUID NOT NULL REFERENCES veterinaria.medicamentos(id) ON DELETE CASCADE,
|
|
-- Lote
|
|
numero_lote VARCHAR(50) NOT NULL,
|
|
fecha_caducidad DATE NOT NULL,
|
|
-- Cantidades
|
|
cantidad_inicial INTEGER NOT NULL,
|
|
cantidad_actual INTEGER NOT NULL,
|
|
-- Compra
|
|
precio_compra NUMERIC(10,2),
|
|
factura_compra VARCHAR(50),
|
|
proveedor VARCHAR(100),
|
|
fecha_recepcion DATE DEFAULT CURRENT_DATE,
|
|
-- Estado
|
|
bloqueado BOOLEAN DEFAULT false, -- Bloquear si esta vencido
|
|
motivo_bloqueo TEXT,
|
|
-- Control
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE veterinaria.medicamentos_lotes IS 'Lotes de medicamentos con control de caducidad';
|
|
|
|
-- Dispensaciones de medicamentos
|
|
CREATE TABLE IF NOT EXISTS veterinaria.dispensaciones (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
-- Referencias
|
|
medicamento_id UUID NOT NULL REFERENCES veterinaria.medicamentos(id),
|
|
lote_id UUID NOT NULL REFERENCES veterinaria.medicamentos_lotes(id),
|
|
mascota_id UUID REFERENCES veterinaria.mascotas(id),
|
|
veterinario_id UUID, -- Referencia a clinica.doctors
|
|
receta_id UUID, -- Referencia a clinica.prescriptions si existe
|
|
consultation_id UUID, -- Referencia a clinica.consultations
|
|
-- Dispensacion
|
|
cantidad INTEGER NOT NULL,
|
|
fecha_dispensacion TIMESTAMPTZ DEFAULT NOW(),
|
|
-- Instrucciones
|
|
dosis VARCHAR(100), -- '1 tableta cada 8 horas'
|
|
duracion_tratamiento VARCHAR(50), -- '7 dias'
|
|
instrucciones TEXT,
|
|
-- Control
|
|
dispensado_por UUID, -- employee_id
|
|
notas TEXT,
|
|
-- Auditoria
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE veterinaria.dispensaciones IS 'Registro de dispensacion de medicamentos';
|
|
|
|
-- Movimientos de inventario (kardex)
|
|
CREATE TABLE IF NOT EXISTS veterinaria.movimientos_farmacia (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
medicamento_id UUID NOT NULL REFERENCES veterinaria.medicamentos(id),
|
|
lote_id UUID REFERENCES veterinaria.medicamentos_lotes(id),
|
|
-- Movimiento
|
|
tipo veterinaria.tipo_movimiento_farmacia NOT NULL,
|
|
cantidad INTEGER NOT NULL,
|
|
stock_anterior INTEGER NOT NULL,
|
|
stock_posterior INTEGER NOT NULL,
|
|
-- Referencia
|
|
referencia_tipo VARCHAR(50), -- 'dispensacion', 'compra', 'ajuste'
|
|
referencia_id UUID,
|
|
-- Detalles
|
|
motivo TEXT,
|
|
documento VARCHAR(100), -- Factura, nota, etc.
|
|
-- Auditoria
|
|
usuario_id UUID,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE veterinaria.movimientos_farmacia IS 'Kardex de movimientos de inventario de farmacia';
|
|
|
|
-- Bitacora de medicamentos controlados
|
|
CREATE TABLE IF NOT EXISTS veterinaria.bitacora_controlados (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
medicamento_id UUID NOT NULL REFERENCES veterinaria.medicamentos(id),
|
|
lote_id UUID REFERENCES veterinaria.medicamentos_lotes(id),
|
|
dispensacion_id UUID REFERENCES veterinaria.dispensaciones(id),
|
|
-- Movimiento
|
|
tipo_movimiento veterinaria.tipo_movimiento_farmacia NOT NULL,
|
|
cantidad INTEGER NOT NULL,
|
|
-- Paciente
|
|
mascota_id UUID REFERENCES veterinaria.mascotas(id),
|
|
propietario_nombre VARCHAR(200), -- Snapshot del nombre
|
|
-- Prescripcion
|
|
receta_id UUID,
|
|
veterinario_id UUID,
|
|
veterinario_cedula VARCHAR(50),
|
|
-- Justificacion
|
|
justificacion TEXT NOT NULL,
|
|
diagnostico TEXT,
|
|
-- Auditoria
|
|
fecha_registro TIMESTAMPTZ DEFAULT NOW(),
|
|
registrado_por UUID NOT NULL,
|
|
ip_address VARCHAR(45),
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE veterinaria.bitacora_controlados IS 'Bitacora de movimientos de medicamentos controlados (requerido por COFEPRIS)';
|
|
|
|
-- ============================================================================
|
|
-- INDICES
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_tenant ON veterinaria.medicamentos(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_codigo ON veterinaria.medicamentos(tenant_id, codigo);
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_nombre ON veterinaria.medicamentos(tenant_id, nombre);
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_categoria ON veterinaria.medicamentos(tenant_id, categoria);
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_controlado ON veterinaria.medicamentos(tenant_id, controlado) WHERE controlado = true;
|
|
CREATE INDEX IF NOT EXISTS idx_medicamentos_stock_bajo ON veterinaria.medicamentos(tenant_id)
|
|
WHERE stock_actual <= stock_minimo;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_lotes_tenant ON veterinaria.medicamentos_lotes(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_lotes_medicamento ON veterinaria.medicamentos_lotes(medicamento_id);
|
|
CREATE INDEX IF NOT EXISTS idx_lotes_caducidad ON veterinaria.medicamentos_lotes(fecha_caducidad);
|
|
CREATE INDEX IF NOT EXISTS idx_lotes_numero ON veterinaria.medicamentos_lotes(tenant_id, numero_lote);
|
|
CREATE INDEX IF NOT EXISTS idx_lotes_proximos_caducar ON veterinaria.medicamentos_lotes(tenant_id, fecha_caducidad)
|
|
WHERE cantidad_actual > 0 AND bloqueado = false;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dispensaciones_tenant ON veterinaria.dispensaciones(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dispensaciones_medicamento ON veterinaria.dispensaciones(medicamento_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dispensaciones_mascota ON veterinaria.dispensaciones(mascota_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dispensaciones_fecha ON veterinaria.dispensaciones(fecha_dispensacion);
|
|
CREATE INDEX IF NOT EXISTS idx_dispensaciones_veterinario ON veterinaria.dispensaciones(veterinario_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_movimientos_tenant ON veterinaria.movimientos_farmacia(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_movimientos_medicamento ON veterinaria.movimientos_farmacia(medicamento_id);
|
|
CREATE INDEX IF NOT EXISTS idx_movimientos_fecha ON veterinaria.movimientos_farmacia(created_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_bitacora_tenant ON veterinaria.bitacora_controlados(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_bitacora_medicamento ON veterinaria.bitacora_controlados(medicamento_id);
|
|
CREATE INDEX IF NOT EXISTS idx_bitacora_fecha ON veterinaria.bitacora_controlados(fecha_registro);
|
|
|
|
-- ============================================================================
|
|
-- RLS
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE veterinaria.medicamentos ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE veterinaria.medicamentos_lotes ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE veterinaria.dispensaciones ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE veterinaria.movimientos_farmacia ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE veterinaria.bitacora_controlados ENABLE ROW LEVEL SECURITY;
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_medicamentos ON veterinaria.medicamentos;
|
|
CREATE POLICY tenant_isolation_medicamentos ON veterinaria.medicamentos
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_lotes ON veterinaria.medicamentos_lotes;
|
|
CREATE POLICY tenant_isolation_lotes ON veterinaria.medicamentos_lotes
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_dispensaciones ON veterinaria.dispensaciones;
|
|
CREATE POLICY tenant_isolation_dispensaciones ON veterinaria.dispensaciones
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_movimientos ON veterinaria.movimientos_farmacia;
|
|
CREATE POLICY tenant_isolation_movimientos ON veterinaria.movimientos_farmacia
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_bitacora ON veterinaria.bitacora_controlados;
|
|
CREATE POLICY tenant_isolation_bitacora ON veterinaria.bitacora_controlados
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
-- ============================================================================
|
|
-- TRIGGERS
|
|
-- ============================================================================
|
|
|
|
-- Trigger para actualizar stock_actual en medicamentos
|
|
CREATE OR REPLACE FUNCTION veterinaria.actualizar_stock_medicamento()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF TG_OP = 'INSERT' THEN
|
|
-- Actualizar stock del medicamento
|
|
UPDATE veterinaria.medicamentos
|
|
SET stock_actual = stock_actual + NEW.cantidad_inicial,
|
|
updated_at = NOW()
|
|
WHERE id = NEW.medicamento_id;
|
|
ELSIF TG_OP = 'UPDATE' THEN
|
|
-- Si cambia cantidad_actual
|
|
UPDATE veterinaria.medicamentos
|
|
SET stock_actual = (
|
|
SELECT COALESCE(SUM(cantidad_actual), 0)
|
|
FROM veterinaria.medicamentos_lotes
|
|
WHERE medicamento_id = NEW.medicamento_id
|
|
AND bloqueado = false
|
|
),
|
|
updated_at = NOW()
|
|
WHERE id = NEW.medicamento_id;
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_actualizar_stock ON veterinaria.medicamentos_lotes;
|
|
CREATE TRIGGER trg_actualizar_stock
|
|
AFTER INSERT OR UPDATE OF cantidad_actual ON veterinaria.medicamentos_lotes
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION veterinaria.actualizar_stock_medicamento();
|
|
|
|
COMMENT ON FUNCTION veterinaria.actualizar_stock_medicamento() IS 'Actualiza stock_actual en medicamentos cuando cambian los lotes';
|
|
|
|
-- Trigger para registrar movimiento en dispensacion
|
|
CREATE OR REPLACE FUNCTION veterinaria.registrar_movimiento_dispensacion()
|
|
RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
v_stock_anterior INTEGER;
|
|
BEGIN
|
|
-- Obtener stock anterior
|
|
SELECT stock_actual INTO v_stock_anterior
|
|
FROM veterinaria.medicamentos
|
|
WHERE id = NEW.medicamento_id;
|
|
|
|
-- Descontar del lote
|
|
UPDATE veterinaria.medicamentos_lotes
|
|
SET cantidad_actual = cantidad_actual - NEW.cantidad,
|
|
updated_at = NOW()
|
|
WHERE id = NEW.lote_id;
|
|
|
|
-- Registrar movimiento
|
|
INSERT INTO veterinaria.movimientos_farmacia (
|
|
tenant_id, medicamento_id, lote_id,
|
|
tipo, cantidad, stock_anterior, stock_posterior,
|
|
referencia_tipo, referencia_id, usuario_id
|
|
) VALUES (
|
|
NEW.tenant_id, NEW.medicamento_id, NEW.lote_id,
|
|
'salida', NEW.cantidad, v_stock_anterior, v_stock_anterior - NEW.cantidad,
|
|
'dispensacion', NEW.id, NEW.dispensado_por
|
|
);
|
|
|
|
-- Si es controlado, registrar en bitacora
|
|
IF EXISTS (
|
|
SELECT 1 FROM veterinaria.medicamentos
|
|
WHERE id = NEW.medicamento_id AND controlado = true
|
|
) THEN
|
|
INSERT INTO veterinaria.bitacora_controlados (
|
|
tenant_id, medicamento_id, lote_id, dispensacion_id,
|
|
tipo_movimiento, cantidad, mascota_id,
|
|
propietario_nombre, receta_id, veterinario_id,
|
|
justificacion, registrado_por
|
|
)
|
|
SELECT
|
|
NEW.tenant_id, NEW.medicamento_id, NEW.lote_id, NEW.id,
|
|
'salida', NEW.cantidad, NEW.mascota_id,
|
|
CONCAT(p.nombre, ' ', COALESCE(p.apellidos, '')),
|
|
NEW.receta_id, NEW.veterinario_id,
|
|
COALESCE(NEW.notas, 'Dispensacion de medicamento'),
|
|
NEW.dispensado_por
|
|
FROM veterinaria.mascotas m
|
|
JOIN veterinaria.propietarios p ON m.propietario_id = p.id
|
|
WHERE m.id = NEW.mascota_id;
|
|
END IF;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_registrar_dispensacion ON veterinaria.dispensaciones;
|
|
CREATE TRIGGER trg_registrar_dispensacion
|
|
AFTER INSERT ON veterinaria.dispensaciones
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION veterinaria.registrar_movimiento_dispensacion();
|
|
|
|
COMMENT ON FUNCTION veterinaria.registrar_movimiento_dispensacion() IS 'Registra movimiento y bitacora al dispensar medicamentos';
|
|
|
|
-- ============================================================================
|
|
-- FUNCIONES DE CONSULTA
|
|
-- ============================================================================
|
|
|
|
-- Funcion para obtener lotes proximos a caducar
|
|
CREATE OR REPLACE FUNCTION veterinaria.get_lotes_proximos_caducar(
|
|
p_tenant_id UUID,
|
|
p_dias INTEGER DEFAULT 30
|
|
)
|
|
RETURNS TABLE (
|
|
lote_id UUID,
|
|
medicamento_id UUID,
|
|
medicamento_nombre VARCHAR,
|
|
numero_lote VARCHAR,
|
|
fecha_caducidad DATE,
|
|
dias_restantes INTEGER,
|
|
cantidad_actual INTEGER
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
l.id AS lote_id,
|
|
m.id AS medicamento_id,
|
|
m.nombre AS medicamento_nombre,
|
|
l.numero_lote,
|
|
l.fecha_caducidad,
|
|
(l.fecha_caducidad - CURRENT_DATE)::INTEGER AS dias_restantes,
|
|
l.cantidad_actual
|
|
FROM veterinaria.medicamentos_lotes l
|
|
JOIN veterinaria.medicamentos m ON l.medicamento_id = m.id
|
|
WHERE l.tenant_id = p_tenant_id
|
|
AND l.cantidad_actual > 0
|
|
AND l.bloqueado = false
|
|
AND l.fecha_caducidad <= CURRENT_DATE + p_dias
|
|
ORDER BY l.fecha_caducidad ASC;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION veterinaria.get_lotes_proximos_caducar(UUID, INTEGER) IS 'Obtiene lotes que caducaran en los proximos N dias';
|
|
|
|
-- Funcion para obtener medicamentos con stock bajo
|
|
CREATE OR REPLACE FUNCTION veterinaria.get_medicamentos_stock_bajo(p_tenant_id UUID)
|
|
RETURNS TABLE (
|
|
medicamento_id UUID,
|
|
codigo VARCHAR,
|
|
nombre VARCHAR,
|
|
stock_actual INTEGER,
|
|
stock_minimo INTEGER,
|
|
diferencia INTEGER
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
m.id AS medicamento_id,
|
|
m.codigo,
|
|
m.nombre,
|
|
m.stock_actual,
|
|
m.stock_minimo,
|
|
(m.stock_minimo - m.stock_actual) AS diferencia
|
|
FROM veterinaria.medicamentos m
|
|
WHERE m.tenant_id = p_tenant_id
|
|
AND m.active = true
|
|
AND m.stock_actual <= m.stock_minimo
|
|
ORDER BY diferencia DESC;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION veterinaria.get_medicamentos_stock_bajo(UUID) IS 'Obtiene medicamentos con stock igual o menor al minimo';
|
|
|
|
-- Funcion para seleccionar lote FEFO (First Expired, First Out)
|
|
CREATE OR REPLACE FUNCTION veterinaria.seleccionar_lote_fefo(
|
|
p_medicamento_id UUID,
|
|
p_cantidad INTEGER
|
|
)
|
|
RETURNS UUID AS $$
|
|
DECLARE
|
|
v_lote_id UUID;
|
|
BEGIN
|
|
SELECT id INTO v_lote_id
|
|
FROM veterinaria.medicamentos_lotes
|
|
WHERE medicamento_id = p_medicamento_id
|
|
AND cantidad_actual >= p_cantidad
|
|
AND bloqueado = false
|
|
AND fecha_caducidad > CURRENT_DATE
|
|
ORDER BY fecha_caducidad ASC
|
|
LIMIT 1;
|
|
|
|
IF v_lote_id IS NULL THEN
|
|
RAISE EXCEPTION 'No hay lotes disponibles con stock suficiente para el medicamento %', p_medicamento_id;
|
|
END IF;
|
|
|
|
RETURN v_lote_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION veterinaria.seleccionar_lote_fefo(UUID, INTEGER) IS 'Selecciona el lote con fecha de caducidad mas proxima (FEFO)';
|
|
|
|
-- ============================================================================
|
|
-- FIN VETERINARIA FARMACIA SCHEMA
|
|
-- ============================================================================
|