DDL schemas for Trading Platform: - User management - Authentication - Payments - Education - ML predictions - Trading data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
159 lines
4.7 KiB
PL/PgSQL
159 lines
4.7 KiB
PL/PgSQL
-- =====================================================
|
|
-- FUNCTION: education.update_gamification_profile()
|
|
-- =====================================================
|
|
-- Proyecto: OrbiQuant IA (Trading Platform)
|
|
-- Módulo: OQI-002 - Education
|
|
-- Especificación: Función adicional para gamificación
|
|
-- Descripción: Actualiza el perfil de gamificación del usuario
|
|
-- =====================================================
|
|
|
|
-- Función para actualizar XP y nivel
|
|
CREATE OR REPLACE FUNCTION education.update_user_xp(
|
|
p_user_id UUID,
|
|
p_xp_to_add INTEGER
|
|
)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
v_profile RECORD;
|
|
v_new_total_xp INTEGER;
|
|
v_new_level INTEGER;
|
|
v_xp_to_next INTEGER;
|
|
BEGIN
|
|
-- Obtener o crear perfil
|
|
INSERT INTO education.user_gamification_profile (user_id)
|
|
VALUES (p_user_id)
|
|
ON CONFLICT (user_id) DO NOTHING;
|
|
|
|
-- Obtener perfil actual
|
|
SELECT * INTO v_profile
|
|
FROM education.user_gamification_profile
|
|
WHERE user_id = p_user_id;
|
|
|
|
-- Calcular nuevo XP total
|
|
v_new_total_xp := v_profile.total_xp + p_xp_to_add;
|
|
|
|
-- Calcular nuevo nivel (cada nivel requiere 100 XP más que el anterior)
|
|
-- Nivel 1: 0-99 XP, Nivel 2: 100-299 XP, Nivel 3: 300-599 XP, etc.
|
|
v_new_level := FLOOR((-100 + SQRT(10000 + 800 * v_new_total_xp)) / 200) + 1;
|
|
|
|
-- XP necesario para siguiente nivel
|
|
v_xp_to_next := (v_new_level * 100 + (v_new_level * (v_new_level - 1) * 100)) - v_new_total_xp;
|
|
|
|
-- Actualizar perfil
|
|
UPDATE education.user_gamification_profile
|
|
SET
|
|
total_xp = v_new_total_xp,
|
|
current_level = v_new_level,
|
|
xp_to_next_level = v_xp_to_next,
|
|
weekly_xp = weekly_xp + p_xp_to_add,
|
|
monthly_xp = monthly_xp + p_xp_to_add,
|
|
last_activity_date = CURRENT_DATE,
|
|
updated_at = NOW()
|
|
WHERE user_id = p_user_id;
|
|
|
|
-- Si subió de nivel, crear achievement
|
|
IF v_new_level > v_profile.current_level THEN
|
|
INSERT INTO education.user_achievements (
|
|
user_id,
|
|
achievement_type,
|
|
title,
|
|
description,
|
|
xp_bonus
|
|
) VALUES (
|
|
p_user_id,
|
|
'level_up',
|
|
'Level Up! - Nivel ' || v_new_level,
|
|
'Has alcanzado el nivel ' || v_new_level,
|
|
50
|
|
);
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION education.update_user_xp(UUID, INTEGER) IS 'Actualiza XP del usuario y recalcula nivel';
|
|
|
|
-- Función para actualizar streak
|
|
CREATE OR REPLACE FUNCTION education.update_user_streak(p_user_id UUID)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
v_last_activity DATE;
|
|
v_current_streak INTEGER;
|
|
v_longest_streak INTEGER;
|
|
BEGIN
|
|
-- Obtener o crear perfil
|
|
INSERT INTO education.user_gamification_profile (user_id)
|
|
VALUES (p_user_id)
|
|
ON CONFLICT (user_id) DO NOTHING;
|
|
|
|
-- Obtener datos actuales
|
|
SELECT last_activity_date, current_streak_days, longest_streak_days
|
|
INTO v_last_activity, v_current_streak, v_longest_streak
|
|
FROM education.user_gamification_profile
|
|
WHERE user_id = p_user_id;
|
|
|
|
-- Actualizar streak
|
|
IF v_last_activity IS NULL THEN
|
|
-- Primera actividad
|
|
v_current_streak := 1;
|
|
ELSIF v_last_activity = CURRENT_DATE THEN
|
|
-- Ya tuvo actividad hoy, no hacer nada
|
|
RETURN;
|
|
ELSIF v_last_activity = CURRENT_DATE - INTERVAL '1 day' THEN
|
|
-- Actividad día consecutivo
|
|
v_current_streak := v_current_streak + 1;
|
|
ELSE
|
|
-- Se rompió el streak
|
|
v_current_streak := 1;
|
|
END IF;
|
|
|
|
-- Actualizar longest streak si corresponde
|
|
IF v_current_streak > v_longest_streak THEN
|
|
v_longest_streak := v_current_streak;
|
|
|
|
-- Crear achievement por streak milestones
|
|
IF v_current_streak IN (7, 30, 100) THEN
|
|
INSERT INTO education.user_achievements (
|
|
user_id,
|
|
achievement_type,
|
|
title,
|
|
description,
|
|
xp_bonus,
|
|
metadata
|
|
) VALUES (
|
|
p_user_id,
|
|
'streak_milestone',
|
|
'Streak de ' || v_current_streak || ' días',
|
|
'Has mantenido una racha de ' || v_current_streak || ' días consecutivos',
|
|
v_current_streak * 5,
|
|
jsonb_build_object('streak_days', v_current_streak)
|
|
);
|
|
END IF;
|
|
END IF;
|
|
|
|
-- Actualizar perfil
|
|
UPDATE education.user_gamification_profile
|
|
SET
|
|
current_streak_days = v_current_streak,
|
|
longest_streak_days = v_longest_streak,
|
|
last_activity_date = CURRENT_DATE,
|
|
updated_at = NOW()
|
|
WHERE user_id = p_user_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION education.update_user_streak(UUID) IS 'Actualiza streak del usuario basado en actividad diaria';
|
|
|
|
-- Trigger para actualizar streak en actividades
|
|
CREATE OR REPLACE FUNCTION education.trigger_update_streak()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
PERFORM education.update_user_streak(NEW.user_id);
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER update_streak_on_activity
|
|
AFTER INSERT ON education.user_activity_log
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION education.trigger_update_streak();
|