- 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
106 lines
3.6 KiB
PL/PgSQL
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';
|