Files
cataRio/postgres/init/02_functions.sql
josedario87 8ec394a74e Fix: Usar clock_timestamp() en trigger updated_at para garantizar timestamps únicos
- Cambiar now() por clock_timestamp() en función set_updated_at()
- now() retorna el timestamp del inicio de la transacción
- clock_timestamp() retorna el timestamp actual del sistema
- Garantiza que cada UPDATE tenga un timestamp diferente
- Mejora la precisión para auditoría de cambios
2025-10-17 17:56:51 -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 := clock_timestamp();
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';