workspace/projects/gamilit/apps/database/scripts/validations/validate-user-initialization.sql
rckrdmrd 289c5a4ee5
Some checks are pending
CI Pipeline / changes (push) Waiting to run
CI Pipeline / core (push) Blocked by required conditions
CI Pipeline / trading-backend (push) Blocked by required conditions
CI Pipeline / trading-data-service (push) Blocked by required conditions
CI Pipeline / trading-frontend (push) Blocked by required conditions
CI Pipeline / erp-core (push) Blocked by required conditions
CI Pipeline / erp-mecanicas (push) Blocked by required conditions
CI Pipeline / gamilit-backend (push) Blocked by required conditions
CI Pipeline / gamilit-frontend (push) Blocked by required conditions
Gamilit: Backend fixes, frontend API updates, deployment guides and validations
Backend:
- Fix email verification and password recovery services
- Fix exercise submission and student progress services

Frontend:
- Update missions, password, and profile API services
- Fix ExerciseContentRenderer component

Docs & Scripts:
- Add SSL/Certbot deployment guide
- Add quick deployment guide
- Database scripts for testing and validations
- Migration and homologation reports
- Functions inventory documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 23:42:48 -06:00

500 lines
18 KiB
SQL

-- =====================================================
-- Script: validate-user-initialization.sql
-- Description: Valida que TODOS los usuarios estén completamente inicializados
-- Version: 1.0
-- Created: 2025-11-24
-- Database-Agent Task: Análisis y corrección de inicialización de usuarios
-- =====================================================
--
-- OBJETIVO:
-- Validar que todos los usuarios (testing + demo + producción) tengan:
-- 1. auth.users (registro inicial)
-- 2. auth_management.profiles (con profiles.id = auth.users.id)
-- 3. gamification_system.user_stats (ML Coins inicializados)
-- 4. gamification_system.comodines_inventory (user_id → profiles.id)
-- 5. gamification_system.user_ranks (rango inicial Ajaw)
-- 6. progress_tracking.module_progress (todos los módulos publicados)
--
-- USUARIOS ESPERADOS:
-- - Testing PROD (@gamilit.com): 3 usuarios
-- - Demo PROD (@demo.glit.edu.mx): 20 usuarios (opcional según ambiente)
-- - Producción (emails reales): 13 usuarios
-- - TOTAL PROD: 16 usuarios (3 testing + 13 producción)
-- - TOTAL FULL: 36 usuarios (3 testing + 20 demo + 13 producción)
-- =====================================================
\set ON_ERROR_STOP off
SET search_path TO auth, auth_management, gamification_system, progress_tracking, public;
-- =====================================================
-- SECCIÓN 1: Validación de auth.users
-- =====================================================
\echo '========================================'
\echo 'VALIDACIÓN 1: auth.users'
\echo '========================================'
SELECT
'1.1. Total usuarios en auth.users' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '❌ ERROR: Menos de 16 usuarios'
END AS resultado
FROM auth.users;
SELECT
'1.2. Usuarios @gamilit.com (testing)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 3 THEN '✅ OK (3 esperados)'
ELSE '❌ ERROR: Se esperaban 3 usuarios @gamilit.com'
END AS resultado
FROM auth.users
WHERE email LIKE '%@gamilit.com';
SELECT
'1.3. Usuarios productivos (no @gamilit.com)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 13 THEN '✅ OK (13 esperados)'
ELSE '⚠️ WARNING: Se esperaban 13 usuarios productivos'
END AS resultado
FROM auth.users
WHERE email NOT LIKE '%@gamilit.com'
AND email NOT LIKE '%@demo.glit.edu.mx';
SELECT
'1.4. Usuarios DEMO (@demo.glit.edu.mx)' AS validacion,
COUNT(*) AS cantidad,
'⏭️ OPCIONAL (ambiente)' AS resultado
FROM auth.users
WHERE email LIKE '%@demo.glit.edu.mx';
-- =====================================================
-- SECCIÓN 2: Validación de auth_management.profiles
-- =====================================================
\echo ''
\echo '========================================'
\echo 'VALIDACIÓN 2: auth_management.profiles'
\echo '========================================'
SELECT
'2.1. Total profiles' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '❌ ERROR: Menos de 16 profiles'
END AS resultado
FROM auth_management.profiles;
SELECT
'2.2. Profiles con id = user_id (CRÍTICO)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = (SELECT COUNT(*) FROM auth_management.profiles)
THEN '✅ OK (100% consistente)'
ELSE '❌ ERROR: Hay profiles con id ≠ user_id'
END AS resultado
FROM auth_management.profiles
WHERE id = user_id;
SELECT
'2.3. Usuarios SIN profile (CRÍTICO)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 0 THEN '✅ OK (todos tienen profile)'
ELSE '❌ ERROR: Hay usuarios sin profile'
END AS resultado
FROM auth.users u
LEFT JOIN auth_management.profiles p ON u.id = p.user_id
WHERE p.id IS NULL;
-- Mostrar usuarios sin profile (si existen)
DO $$
DECLARE
usuarios_sin_profile INTEGER;
BEGIN
SELECT COUNT(*) INTO usuarios_sin_profile
FROM auth.users u
LEFT JOIN auth_management.profiles p ON u.id = p.user_id
WHERE p.id IS NULL;
IF usuarios_sin_profile > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '❌ USUARIOS SIN PROFILE DETECTADOS:';
FOR rec IN
SELECT u.id, u.email
FROM auth.users u
LEFT JOIN auth_management.profiles p ON u.id = p.user_id
WHERE p.id IS NULL
LOOP
RAISE NOTICE ' - % (%)', rec.email, rec.id;
END LOOP;
END IF;
END $$;
-- =====================================================
-- SECCIÓN 3: Validación de gamification_system.user_stats
-- =====================================================
\echo ''
\echo '========================================'
\echo 'VALIDACIÓN 3: gamification_system.user_stats'
\echo '========================================'
SELECT
'3.1. Total user_stats' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '❌ ERROR: Menos de 16 user_stats'
END AS resultado
FROM gamification_system.user_stats;
SELECT
'3.2. Usuarios CON profile pero SIN user_stats (CRÍTICO)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 0 THEN '✅ OK (todos tienen user_stats)'
ELSE '❌ ERROR: Hay profiles sin user_stats'
END AS resultado
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_stats us ON p.user_id = us.user_id
WHERE us.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT
'3.3. user_stats con ML Coins = 100 (inicial)' AS validacion,
COUNT(*) AS cantidad,
'⏭️ INFO (bonus inicial)' AS resultado
FROM gamification_system.user_stats
WHERE ml_coins = 100 AND ml_coins_earned_total = 100;
-- Mostrar profiles sin user_stats (si existen)
DO $$
DECLARE
profiles_sin_stats INTEGER;
BEGIN
SELECT COUNT(*) INTO profiles_sin_stats
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_stats us ON p.user_id = us.user_id
WHERE us.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
IF profiles_sin_stats > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '❌ PROFILES SIN USER_STATS DETECTADOS:';
FOR rec IN
SELECT p.id, p.email, p.role
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_stats us ON p.user_id = us.user_id
WHERE us.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin')
LOOP
RAISE NOTICE ' - % (%, %)', rec.email, rec.role, rec.id;
END LOOP;
END IF;
END $$;
-- =====================================================
-- SECCIÓN 4: Validación de gamification_system.comodines_inventory
-- =====================================================
\echo ''
\echo '========================================'
\echo 'VALIDACIÓN 4: gamification_system.comodines_inventory'
\echo '========================================'
SELECT
'4.1. Total comodines_inventory' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '❌ ERROR: Menos de 16 inventarios'
END AS resultado
FROM gamification_system.comodines_inventory;
SELECT
'4.2. Profiles SIN comodines_inventory (CRÍTICO)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 0 THEN '✅ OK (todos tienen inventario)'
ELSE '❌ ERROR: Hay profiles sin inventario'
END AS resultado
FROM auth_management.profiles p
LEFT JOIN gamification_system.comodines_inventory ci ON p.id = ci.user_id
WHERE ci.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
-- IMPORTANTE: comodines_inventory.user_id apunta a profiles.id (NO auth.users.id)
SELECT
'4.3. comodines_inventory con user_id válido' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = (SELECT COUNT(*) FROM gamification_system.comodines_inventory)
THEN '✅ OK (100% válidos)'
ELSE '❌ ERROR: Hay inventarios con user_id inválido'
END AS resultado
FROM gamification_system.comodines_inventory ci
INNER JOIN auth_management.profiles p ON ci.user_id = p.id;
-- Mostrar profiles sin comodines_inventory (si existen)
DO $$
DECLARE
profiles_sin_inventory INTEGER;
BEGIN
SELECT COUNT(*) INTO profiles_sin_inventory
FROM auth_management.profiles p
LEFT JOIN gamification_system.comodines_inventory ci ON p.id = ci.user_id
WHERE ci.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
IF profiles_sin_inventory > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '❌ PROFILES SIN COMODINES_INVENTORY DETECTADOS:';
FOR rec IN
SELECT p.id, p.email, p.role
FROM auth_management.profiles p
LEFT JOIN gamification_system.comodines_inventory ci ON p.id = ci.user_id
WHERE ci.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin')
LOOP
RAISE NOTICE ' - % (%, %)', rec.email, rec.role, rec.id;
END LOOP;
END IF;
END $$;
-- =====================================================
-- SECCIÓN 5: Validación de gamification_system.user_ranks
-- =====================================================
\echo ''
\echo '========================================'
\echo 'VALIDACIÓN 5: gamification_system.user_ranks'
\echo '========================================'
SELECT
'5.1. Total user_ranks' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '❌ ERROR: Menos de 16 user_ranks'
END AS resultado
FROM gamification_system.user_ranks;
SELECT
'5.2. Usuarios CON profile pero SIN user_ranks (CRÍTICO)' AS validacion,
COUNT(*) AS cantidad,
CASE
WHEN COUNT(*) = 0 THEN '✅ OK (todos tienen rank)'
ELSE '❌ ERROR: Hay profiles sin rank'
END AS resultado
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_ranks ur ON p.user_id = ur.user_id
WHERE ur.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT
'5.3. user_ranks con rango Ajaw (inicial)' AS validacion,
COUNT(*) AS cantidad,
'⏭️ INFO (rango inicial)' AS resultado
FROM gamification_system.user_ranks
WHERE current_rank = 'Ajaw'::gamification_system.maya_rank;
-- Mostrar profiles sin user_ranks (si existen)
DO $$
DECLARE
profiles_sin_ranks INTEGER;
BEGIN
SELECT COUNT(*) INTO profiles_sin_ranks
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_ranks ur ON p.user_id = ur.user_id
WHERE ur.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
IF profiles_sin_ranks > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '❌ PROFILES SIN USER_RANKS DETECTADOS:';
FOR rec IN
SELECT p.id, p.email, p.role
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_ranks ur ON p.user_id = ur.user_id
WHERE ur.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin')
LOOP
RAISE NOTICE ' - % (%, %)', rec.email, rec.role, rec.id;
END LOOP;
END IF;
END $$;
-- =====================================================
-- SECCIÓN 6: Validación de progress_tracking.module_progress
-- =====================================================
\echo ''
\echo '========================================'
\echo 'VALIDACIÓN 6: progress_tracking.module_progress'
\echo '========================================'
SELECT
'6.1. Total module_progress registros' AS validacion,
COUNT(*) AS cantidad,
'⏭️ INFO (depende de módulos publicados)' AS resultado
FROM progress_tracking.module_progress;
SELECT
'6.2. Estudiantes CON module_progress' AS validacion,
COUNT(DISTINCT mp.user_id) AS cantidad,
CASE
WHEN COUNT(DISTINCT mp.user_id) >= 16 THEN '✅ OK (mínimo 16 esperados)'
ELSE '⚠️ WARNING: Menos de 16 estudiantes con progreso'
END AS resultado
FROM progress_tracking.module_progress mp
INNER JOIN auth_management.profiles p ON mp.user_id = p.id
WHERE p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT
'6.3. Módulos publicados disponibles' AS validacion,
COUNT(*) AS cantidad,
'⏭️ INFO' AS resultado
FROM educational_content.modules
WHERE is_published = true AND status = 'published';
-- Mostrar estudiantes sin module_progress (si existen)
DO $$
DECLARE
profiles_sin_progress INTEGER;
BEGIN
SELECT COUNT(*) INTO profiles_sin_progress
FROM auth_management.profiles p
LEFT JOIN progress_tracking.module_progress mp ON p.id = mp.user_id
WHERE mp.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin');
IF profiles_sin_progress > 0 THEN
RAISE NOTICE '';
RAISE NOTICE '⚠️ PROFILES SIN MODULE_PROGRESS DETECTADOS:';
FOR rec IN
SELECT p.id, p.email, p.role
FROM auth_management.profiles p
LEFT JOIN progress_tracking.module_progress mp ON p.id = mp.user_id
WHERE mp.user_id IS NULL
AND p.role IN ('student', 'admin_teacher', 'super_admin')
LOOP
RAISE NOTICE ' - % (%, %)', rec.email, rec.role, rec.id;
END LOOP;
END IF;
END $$;
-- =====================================================
-- SECCIÓN 7: Resumen Final
-- =====================================================
\echo ''
\echo '========================================'
\echo 'RESUMEN FINAL'
\echo '========================================'
DO $$
DECLARE
total_users INTEGER;
total_profiles INTEGER;
total_stats INTEGER;
total_inventory INTEGER;
total_ranks INTEGER;
total_progress_users INTEGER;
usuarios_sin_profile INTEGER;
profiles_sin_stats INTEGER;
profiles_sin_inventory INTEGER;
profiles_sin_ranks INTEGER;
profiles_sin_progress INTEGER;
errores_criticos INTEGER := 0;
BEGIN
-- Contar totales
SELECT COUNT(*) INTO total_users FROM auth.users;
SELECT COUNT(*) INTO total_profiles FROM auth_management.profiles;
SELECT COUNT(*) INTO total_stats FROM gamification_system.user_stats;
SELECT COUNT(*) INTO total_inventory FROM gamification_system.comodines_inventory;
SELECT COUNT(*) INTO total_ranks FROM gamification_system.user_ranks;
SELECT COUNT(DISTINCT mp.user_id) INTO total_progress_users
FROM progress_tracking.module_progress mp;
-- Contar problemas
SELECT COUNT(*) INTO usuarios_sin_profile
FROM auth.users u
LEFT JOIN auth_management.profiles p ON u.id = p.user_id
WHERE p.id IS NULL;
SELECT COUNT(*) INTO profiles_sin_stats
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_stats us ON p.user_id = us.user_id
WHERE us.user_id IS NULL AND p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT COUNT(*) INTO profiles_sin_inventory
FROM auth_management.profiles p
LEFT JOIN gamification_system.comodines_inventory ci ON p.id = ci.user_id
WHERE ci.user_id IS NULL AND p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT COUNT(*) INTO profiles_sin_ranks
FROM auth_management.profiles p
LEFT JOIN gamification_system.user_ranks ur ON p.user_id = ur.user_id
WHERE ur.user_id IS NULL AND p.role IN ('student', 'admin_teacher', 'super_admin');
SELECT COUNT(*) INTO profiles_sin_progress
FROM auth_management.profiles p
LEFT JOIN progress_tracking.module_progress mp ON p.id = mp.user_id
WHERE mp.user_id IS NULL AND p.role IN ('student', 'admin_teacher', 'super_admin');
-- Calcular errores críticos
errores_criticos := usuarios_sin_profile + profiles_sin_stats +
profiles_sin_inventory + profiles_sin_ranks;
-- Mostrar resumen
RAISE NOTICE '';
RAISE NOTICE 'TOTALES:';
RAISE NOTICE ' - auth.users: %', total_users;
RAISE NOTICE ' - auth_management.profiles: %', total_profiles;
RAISE NOTICE ' - gamification_system.user_stats: %', total_stats;
RAISE NOTICE ' - gamification_system.comodines_inventory: %', total_inventory;
RAISE NOTICE ' - gamification_system.user_ranks: %', total_ranks;
RAISE NOTICE ' - progress_tracking.module_progress (usuarios únicos): %', total_progress_users;
RAISE NOTICE '';
RAISE NOTICE 'PROBLEMAS DETECTADOS:';
RAISE NOTICE ' - Usuarios sin profile: %', usuarios_sin_profile;
RAISE NOTICE ' - Profiles sin user_stats: %', profiles_sin_stats;
RAISE NOTICE ' - Profiles sin comodines_inventory: %', profiles_sin_inventory;
RAISE NOTICE ' - Profiles sin user_ranks: %', profiles_sin_ranks;
RAISE NOTICE ' - Profiles sin module_progress: % (WARNING)', profiles_sin_progress;
RAISE NOTICE '';
IF errores_criticos = 0 THEN
RAISE NOTICE '========================================';
RAISE NOTICE '✅ VALIDACIÓN EXITOSA';
RAISE NOTICE '========================================';
RAISE NOTICE 'Todos los usuarios están completamente inicializados.';
IF profiles_sin_progress > 0 THEN
RAISE NOTICE '⚠️ WARNING: Hay % usuarios sin module_progress', profiles_sin_progress;
RAISE NOTICE ' (Esto puede ser esperado si no hay módulos publicados)';
END IF;
ELSE
RAISE NOTICE '========================================';
RAISE NOTICE '❌ VALIDACIÓN FALLIDA';
RAISE NOTICE '========================================';
RAISE NOTICE 'Se detectaron % errores críticos.', errores_criticos;
RAISE NOTICE 'Revisa las secciones anteriores para más detalles.';
END IF;
RAISE NOTICE '';
END $$;
-- =====================================================
-- FIN DEL SCRIPT
-- =====================================================
\echo ''
\echo 'Validación completa. Revisa los resultados arriba.'
\echo ''