- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
136 lines
5.0 KiB
SQL
136 lines
5.0 KiB
SQL
-- =====================================================
|
|
-- Migration: Backfill module_progress for existing users
|
|
-- Date: 2025-11-24
|
|
-- Priority: CRITICAL
|
|
-- Reason: Bug fix - initialize_user_stats() didn't create module_progress records
|
|
--
|
|
-- ISSUE: The trigger gamilit.initialize_user_stats() was incomplete.
|
|
-- It created user_stats, comodines_inventory, and user_ranks,
|
|
-- but NEVER created progress_tracking.module_progress records.
|
|
-- This caused new users to see "no modules available" errors.
|
|
--
|
|
-- IMPACT: All users registered before 2025-11-24 are missing module_progress.
|
|
-- This migration backfills those records.
|
|
--
|
|
-- SAFETY: This script is idempotent and safe to run multiple times.
|
|
-- Uses ON CONFLICT DO NOTHING to prevent duplicates.
|
|
-- =====================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
v_affected_users INTEGER;
|
|
v_affected_records INTEGER;
|
|
v_total_users INTEGER;
|
|
v_users_needing_fix INTEGER;
|
|
BEGIN
|
|
RAISE NOTICE '================================================';
|
|
RAISE NOTICE 'Migration: Backfill module_progress';
|
|
RAISE NOTICE 'Started at: %', NOW();
|
|
RAISE NOTICE '================================================';
|
|
|
|
-- Count total users with gamification roles
|
|
SELECT COUNT(*)
|
|
INTO v_total_users
|
|
FROM auth_management.profiles
|
|
WHERE role IN ('student', 'admin_teacher', 'super_admin')
|
|
AND deleted_at IS NULL;
|
|
|
|
RAISE NOTICE 'Total users with gamification: %', v_total_users;
|
|
|
|
-- Count users who are missing module_progress records
|
|
SELECT COUNT(DISTINCT p.id)
|
|
INTO v_users_needing_fix
|
|
FROM auth_management.profiles p
|
|
WHERE p.role IN ('student', 'admin_teacher', 'super_admin')
|
|
AND p.deleted_at IS NULL
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM progress_tracking.module_progress mp
|
|
WHERE mp.user_id = p.id -- FIXED: Use p.id (profiles.id) not p.user_id
|
|
);
|
|
|
|
RAISE NOTICE 'Users missing module_progress: %', v_users_needing_fix;
|
|
|
|
-- Insert module_progress for users who don't have any
|
|
-- This matches the logic in the fixed initialize_user_stats() function
|
|
-- IMPORTANT: module_progress.user_id references profiles.id (NOT auth.users.id)
|
|
INSERT INTO progress_tracking.module_progress (
|
|
user_id,
|
|
module_id,
|
|
status,
|
|
progress_percentage,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
SELECT
|
|
p.id, -- FIXED: Use p.id (profiles.id) not p.user_id (auth.users.id)
|
|
m.id as module_id,
|
|
'not_started'::progress_tracking.progress_status,
|
|
0,
|
|
NOW(),
|
|
NOW()
|
|
FROM auth_management.profiles p
|
|
CROSS JOIN educational_content.modules m
|
|
WHERE p.role IN ('student', 'admin_teacher', 'super_admin')
|
|
AND p.deleted_at IS NULL
|
|
AND m.is_published = true
|
|
AND m.status = 'published'
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM progress_tracking.module_progress mp
|
|
WHERE mp.user_id = p.id -- FIXED: Use p.id (profiles.id) not p.user_id
|
|
AND mp.module_id = m.id
|
|
)
|
|
ON CONFLICT (user_id, module_id) DO NOTHING;
|
|
|
|
GET DIAGNOSTICS v_affected_records = ROW_COUNT;
|
|
|
|
-- Count how many users now have module_progress
|
|
SELECT COUNT(DISTINCT p.id)
|
|
INTO v_affected_users
|
|
FROM auth_management.profiles p
|
|
WHERE p.role IN ('student', 'admin_teacher', 'super_admin')
|
|
AND p.deleted_at IS NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM progress_tracking.module_progress mp
|
|
WHERE mp.user_id = p.id -- FIXED: Use p.id (profiles.id) not p.user_id
|
|
);
|
|
|
|
RAISE NOTICE '================================================';
|
|
RAISE NOTICE 'Migration Results:';
|
|
RAISE NOTICE ' - Total module_progress records created: %', v_affected_records;
|
|
RAISE NOTICE ' - Users affected: %', v_users_needing_fix;
|
|
RAISE NOTICE ' - Users now with module_progress: %', v_affected_users;
|
|
RAISE NOTICE ' - Completed at: %', NOW();
|
|
RAISE NOTICE '================================================';
|
|
|
|
-- Validation check
|
|
IF v_affected_users < v_total_users THEN
|
|
RAISE WARNING 'Some users still missing module_progress! Check: % of %',
|
|
v_total_users - v_affected_users, v_total_users;
|
|
ELSE
|
|
RAISE NOTICE 'SUCCESS: All users now have module_progress records!';
|
|
END IF;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
RAISE EXCEPTION 'Migration failed: % - %', SQLERRM, SQLSTATE;
|
|
END $$;
|
|
|
|
-- =====================================================
|
|
-- Verification Query (Run after migration)
|
|
-- =====================================================
|
|
-- SELECT
|
|
-- p.id, -- FIXED: Use p.id (profiles.id) for grouping
|
|
-- p.email,
|
|
-- p.role,
|
|
-- COUNT(mp.id) as module_count
|
|
-- FROM auth_management.profiles p
|
|
-- LEFT JOIN progress_tracking.module_progress mp ON mp.user_id = p.id -- FIXED: Use p.id
|
|
-- WHERE p.role IN ('student', 'admin_teacher', 'super_admin')
|
|
-- AND p.deleted_at IS NULL
|
|
-- GROUP BY p.id, p.email, p.role -- FIXED: Use p.id
|
|
-- ORDER BY module_count ASC, p.email;
|
|
-- =====================================================
|