Files
cataRio/postgres/init/02_functions.sql
josedario87 f682c3db51 Inicializar rioCata - Sistema de Catación de Café
- Base de datos PostgreSQL 16 con extensiones JSONB y arrays
- Docker Compose para containerización
- Scripts SQL de inicialización (schema, funciones, índices, datos de prueba)
- Suite de tests de validación (18 tests)
- Queries de ejemplo (17 queries)
- Script helper para gestión (scripts/riocata.sh)
- Documentación completa en README.md

Estructura:
- 4 tablas principales: sesion, auth.users, sesion_participante, muestra, evaluacion
- Tipo ENUM para defectos
- 2 triggers automáticos (updated_at, puntaje_final)
- 19 índices de optimización (GIN, B-tree, funcionales)
- Constraints de validación para arrays y JSONB
- 2 funciones auxiliares para análisis
2025-10-17 17:00:48 -06:00

106 lines
3.6 KiB
PL/PgSQL

-- ============================================
-- rioCata - Funciones y Triggers
-- ============================================
-- ============================================
-- FUNCIÓN: Actualizar updated_at
-- ============================================
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
NEW.updated_at := now();
RETURN NEW;
END $$;
COMMENT ON FUNCTION set_updated_at() IS 'Actualiza automáticamente el campo updated_at al timestamp actual';
-- Trigger para actualizar updated_at en evaluacion
CREATE TRIGGER trg_eval_updated_at
BEFORE UPDATE ON evaluacion
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
-- ============================================
-- FUNCIÓN: Calcular puntaje final
-- ============================================
-- Calcula el puntaje_final sumando SOLO los valores afectivos presentes
CREATE OR REPLACE FUNCTION eval_compute_score()
RETURNS trigger LANGUAGE plpgsql AS $$
DECLARE
s int := 0;
BEGIN
-- Suma todos los valores afectivos presentes en intensidades
-- Si alguno es null, COALESCE lo convierte en 0
s := s + COALESCE((NEW.intensidades->'fragancia' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'aroma' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'sabor' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'saborResidual' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'acidez' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'dulzor' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'sensacionBoca' ->>'afectiva')::int, 0);
s := s + COALESCE((NEW.intensidades->'impresionGlobal'->>'afectiva')::int, 0);
NEW.puntaje_final := s;
RETURN NEW;
END $$;
COMMENT ON FUNCTION eval_compute_score() IS 'Calcula automáticamente el puntaje_final como suma de valores afectivos';
-- Trigger para calcular puntaje_final en INSERT y UPDATE
CREATE TRIGGER trg_eval_score_bi
BEFORE INSERT OR UPDATE OF intensidades
ON evaluacion
FOR EACH ROW EXECUTE FUNCTION eval_compute_score();
-- ============================================
-- FUNCIONES AUXILIARES DE CONSULTA
-- ============================================
-- Función para obtener el promedio de un parámetro afectivo en una sesión
CREATE OR REPLACE FUNCTION get_promedio_parametro_afectivo(
p_sesion_id uuid,
p_parametro text -- 'fragancia', 'aroma', 'sabor', etc.
)
RETURNS numeric AS $$
BEGIN
RETURN (
SELECT AVG(((e.intensidades -> p_parametro ->>'afectiva')::int))
FROM sesion s
JOIN muestra m ON m.sesion_id = s.id
JOIN evaluacion e ON e.muestra_id = m.id
WHERE s.id = p_sesion_id
);
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION get_promedio_parametro_afectivo(uuid, text) IS 'Obtiene el promedio de un parámetro afectivo para una sesión';
-- Función para obtener las top N muestras de una sesión por puntaje
CREATE OR REPLACE FUNCTION get_top_muestras(
p_sesion_id uuid,
p_limit int DEFAULT 3
)
RETURNS TABLE (
muestra_codigo text,
puntaje_final int,
catador_email text,
catador_nombre text
) AS $$
BEGIN
RETURN QUERY
SELECT
m.codigo,
e.puntaje_final,
u.email,
u.nombre
FROM muestra m
JOIN evaluacion e ON e.muestra_id = m.id
JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
JOIN auth.users u ON u.id = sp.catador_id
WHERE m.sesion_id = p_sesion_id
ORDER BY e.puntaje_final DESC
LIMIT p_limit;
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION get_top_muestras(uuid, int) IS 'Obtiene las muestras con mejor puntaje de una sesión';