# RF-INIT-001: Inicialización Automática de Usuario

**Proyecto:** GAMILIT
**Épica:** EAI-001 - Fundamentos
**Versión:** 1.1
**Fecha de creación:** 2025-11-24
**Última actualización:** 2025-11-24
**Estado:** ✅ Implementado
**Prioridad:** Crítica

---

## 📋 Información del Requerimiento

| Atributo | Valor |
|----------|-------|
| **ID** | RF-INIT-001 |
| **Tipo** | Requerimiento Funcional |
| **Categoría** | Sistema / Inicialización |
| **Epic** | EAI-001 - Fundamentos |
| **Relacionado con** | US-FUND-001 (Autenticación), US-FUND-002 (Perfiles) |
| **Prioridad** | Crítica (P0) |
| **Complejidad** | Media |
| **Documentado en** | ADR-012, ET-INIT-001 |

---

## 🎯 Descripción

El sistema GAMILIT **debe inicializar automáticamente** todos los componentes necesarios de gamificación, progreso y configuración cuando un nuevo usuario se registra en la plataforma. Esta inicialización debe ocurrir de forma transparente, inmediata y sin intervención manual.

**Contexto de Negocio:**

Cuando un estudiante o profesor se registra en GAMILIT, el sistema debe estar listo inmediatamente para su uso. Esto significa que el usuario debe tener:
- Estadísticas de gamificación inicializadas (puntos, monedas)
- Rango Maya inicial asignado
- Inventario de comodines creado
- Progreso de módulos educativos configurado para todos los módulos publicados

Sin esta inicialización automática, los usuarios verían errores o pantallas vacías al acceder por primera vez al sistema.

---

## 📐 Alcance

### Incluido en este requerimiento:

1. ✅ Inicialización automática de 4 componentes:
   - Estadísticas de usuario (user_stats)
   - Inventario de comodines (comodines_inventory)
   - Rango Maya (user_ranks)
   - Progreso de módulos (module_progress)

2. ✅ Trigger automático al momento del registro

3. ✅ Valores iniciales predeterminados:
   - 100 ML Coins (monedas de bienvenida)
   - Rango Maya: Ajaw (rango inicial)
   - Progreso de módulos: 0% en todos los módulos publicados
   - Inventario de comodines: vacío pero creado

4. ✅ Manejo de idempotencia (evitar duplicados)

5. ✅ Aplicable a roles: student, admin_teacher, super_admin

### Explícitamente excluido:

- ❌ Inicialización de misiones (BUG FIX #3: pendiente implementación)
- ❌ Asignación de logros iniciales
- ❌ Configuración personalizada de parámetros de gamificación
- ❌ Notificaciones de bienvenida
- ❌ Roles sin gamificación (ej: viewer, auditor)

---

## 🔍 Requerimientos Funcionales Detallados

### RF-INIT-001.1: Trigger Automático de Inicialización

**Descripción:** El sistema debe disparar automáticamente el proceso de inicialización cuando se crea un nuevo perfil de usuario.

**Reglas de Negocio:**
- La inicialización se dispara DESPUÉS de insertar el registro en `auth_management.profiles`
- La inicialización es asíncrona desde la perspectiva del registro
- Si el registro falla, la inicialización NO se ejecuta
- Si la inicialización falla, el registro NO se revierte (pero se debe logear el error)

**Criterios de Aceptación:**
- [ ] La inicialización se ejecuta automáticamente para cada nuevo usuario
- [ ] La inicialización ocurre en menos de 1 segundo
- [ ] No se requiere intervención manual
- [ ] Se logean errores si algo falla

---

### RF-INIT-001.2: Inicialización de Estadísticas de Usuario

**Descripción:** El sistema debe crear un registro de estadísticas de gamificación para cada nuevo usuario.

**Reglas de Negocio:**
- Tabla: `gamification_system.user_stats`
- FK Reference: `user_id` → `auth.users.id` (NO profiles.id)
- Valores iniciales:
  - `ml_coins = 100` (monedas de bienvenida)
  - `ml_coins_earned_total = 100`
  - `total_xp = 0`
  - `level = 1`
  - Tenant heredado del perfil
- Estrategia de idempotencia: `ON CONFLICT (user_id) DO NOTHING`

**Criterios de Aceptación:**
- [ ] Se crea exactamente 1 registro por usuario
- [ ] El registro se crea incluso si otros componentes fallan
- [ ] Los valores iniciales son correctos
- [ ] No se crean duplicados si el trigger se ejecuta múltiples veces

---

### RF-INIT-001.3: Inicialización de Inventario de Comodines

**Descripción:** El sistema debe crear un inventario vacío de comodines para cada nuevo usuario.

**Reglas de Negocio:**
- Tabla: `gamification_system.comodines_inventory`
- FK Reference: `user_id` → `profiles.id` (NO auth.users.id)
- Valores iniciales:
  - Inventario vacío (todas las cantidades en 0)
- Estrategia de idempotencia: `ON CONFLICT (user_id) DO NOTHING`

**Criterios de Aceptación:**
- [ ] Se crea exactamente 1 registro por usuario
- [ ] El usuario puede empezar a ganar comodines inmediatamente
- [ ] No se crean duplicados

---

### RF-INIT-001.4: Inicialización de Rango Maya

**Descripción:** El sistema debe asignar el rango Maya inicial a cada nuevo usuario.

**Reglas de Negocio:**
- Tabla: `gamification_system.user_ranks`
- FK Reference: `user_id` → `auth.users.id` (NO profiles.id)
- Rango inicial: `Ajaw` (rango más bajo en la jerarquía Maya)
- Estrategia de idempotencia: `WHERE NOT EXISTS` (tabla sin unique constraint en user_id)
- Tenant heredado del perfil

**Criterios de Aceptación:**
- [ ] Se crea exactamente 1 registro por usuario
- [ ] El rango inicial es siempre 'Ajaw'
- [ ] No se crean duplicados (validado con WHERE NOT EXISTS)
- [ ] El usuario puede progresar a rangos superiores

---

### RF-INIT-001.5: Inicialización de Progreso de Módulos

**Descripción:** El sistema debe crear registros de progreso para TODOS los módulos educativos publicados.

**Reglas de Negocio:**
- Tabla: `progress_tracking.module_progress`
- FK Reference: `user_id` → `profiles.id` (NO auth.users.id)
- FK Reference: `module_id` → `educational_content.modules.id`
- Se crean registros solo para módulos con:
  - `is_published = true`
  - `status = 'published'`
- Valores iniciales por módulo:
  - `status = 'not_started'`
  - `progress_percentage = 0`
  - `created_at = NOW()`
  - `updated_at = NOW()`
- Estrategia de idempotencia: `ON CONFLICT (user_id, module_id) DO NOTHING`

**Criterios de Aceptación:**
- [ ] Se crean N registros donde N = número de módulos publicados
- [ ] Si hay 5 módulos publicados, se crean 5 registros
- [ ] El usuario ve inmediatamente los módulos disponibles en su dashboard
- [ ] No se crean duplicados
- [ ] Si se publica un nuevo módulo después del registro, NO se crea automáticamente (requiere migración manual)

**Nota Importante (BUG FIX #1 - GAP-003):**
Esta funcionalidad fue el objetivo del fix GAP-003. Antes de 2025-11-24, los usuarios NO tenían `module_progress` inicializado, causando "No modules available" en el dashboard. Ver ADR-012 para detalles.

---

### RF-INIT-001.6: Restricción por Rol

**Descripción:** La inicialización solo aplica a roles que participan en gamificación.

**Reglas de Negocio:**
- Roles incluidos: `'student'`, `'admin_teacher'`, `'super_admin'`
- Roles excluidos: Cualquier otro rol futuro sin gamificación

**Criterios de Aceptación:**
- [ ] La inicialización se ejecuta solo para roles especificados
- [ ] Los roles excluidos NO tienen registros de gamificación
- [ ] La lógica de filtrado está en la función de inicialización, NO en el trigger

---

## 🔗 Dependencias

### Dependencias de Entrada (Pre-requisitos)

| Objeto | Tipo | Descripción |
|--------|------|-------------|
| `auth.users` | Tabla | Usuario debe existir en auth (Supabase) |
| `auth_management.profiles` | Tabla | Perfil debe ser creado ANTES de inicialización |
| `auth_management.tenants` | Tabla | Tenant debe existir para multi-tenancy |
| `educational_content.modules` | Tabla | Módulos publicados deben existir |
| `gamification_system.maya_rank` | Enum | Enum de rangos Maya debe estar definido |
| `progress_tracking.progress_status` | Enum | Enum de estados de progreso debe estar definido |

### Dependencias de Salida (Objetos que dependen de este)

| Objeto | Tipo | Descripción |
|--------|------|-------------|
| `DashboardPage.tsx` | Componente | Dashboard requiere module_progress para mostrar módulos |
| `GET /api/modules/progress` | API | Endpoint requiere module_progress existente |
| `ProfileService.getProgress()` | Servicio | Backend requiere user_stats existente |
| `GamificationService.*` | Servicios | Múltiples servicios asumen user_stats existe |

---

## 🎨 Casos de Uso

### Caso de Uso 1: Registro Exitoso de Estudiante

**Actor:** Nuevo estudiante

**Flujo Principal:**
1. Estudiante completa formulario de registro
2. Backend valida datos y crea usuario en `auth.users`
3. Backend crea perfil en `auth_management.profiles` con rol='student'
4. ⚡ **Trigger se dispara automáticamente**
5. Función `gamilit.initialize_user_stats()` se ejecuta:
   - 5.1. Crea registro en `user_stats` (100 ML Coins)
   - 5.2. Crea registro en `comodines_inventory`
   - 5.3. Crea registro en `user_ranks` (Ajaw)
   - 5.4. Crea 5 registros en `module_progress` (uno por módulo)
6. Backend retorna token JWT al frontend
7. Estudiante es redirigido a dashboard
8. **Dashboard carga exitosamente mostrando 5 módulos disponibles**

**Resultado:** ✅ Usuario listo para usar la plataforma inmediatamente

---

### Caso de Uso 2: Registro con Fallo Parcial de Inicialización

**Actor:** Nuevo estudiante

**Flujo Alternativo:**
1. Pasos 1-4 iguales a Caso 1
2. Función de inicialización comienza:
   - 5.1. Crea `user_stats` ✅
   - 5.2. Crea `comodines_inventory` ✅
   - 5.3. Crea `user_ranks` ✅
   - 5.4. **FALLA** al crear `module_progress` (ej: módulos no publicados) ❌
3. Función completa pero logea error
4. Backend retorna token JWT (registro exitoso)
5. Usuario accede a dashboard
6. Dashboard muestra error "No modules available"

**Resultado:** ⚠️ Usuario registrado pero experiencia degradada

**Mitigación:**
- Error se logea para investigación
- Script de reparación puede ejecutarse: `SELECT gamilit.initialize_user_stats_for_user(user_id)`
- Monitoreo debe alertar sobre fallos de inicialización

---

### Caso de Uso 3: Intento de Re-inicialización (Idempotencia)

**Actor:** Script de migración / Administrador

**Flujo:**
1. Administrador ejecuta script de re-inicialización para usuario existente
2. Script llama a función `gamilit.initialize_user_stats()`
3. Función intenta crear registros:
   - 3.1. `user_stats`: Conflicto detectado → DO NOTHING ✅
   - 3.2. `comodines_inventory`: Conflicto detectado → DO NOTHING ✅
   - 3.3. `user_ranks`: WHERE NOT EXISTS = false → Skip ✅
   - 3.4. `module_progress`: Conflictos detectados → DO NOTHING ✅
4. Función completa sin errores
5. **NO se crean duplicados**

**Resultado:** ✅ Función es idempotente, puede ejecutarse múltiples veces de forma segura

---

## 🧪 Criterios de Validación

### Validación Funcional

**Query de Validación Post-Registro:**
```sql
-- Verificar que usuario tiene TODAS las inicializaciones
WITH user_initialization_check AS (
    SELECT
        p.id as profile_id,
        p.email,
        COUNT(DISTINCT us.user_id) as has_user_stats,
        COUNT(DISTINCT ci.user_id) as has_comodines,
        COUNT(DISTINCT ur.user_id) as has_ranks,
        COUNT(DISTINCT mp.user_id) as has_module_progress,
        COUNT(mp.id) as module_count
    FROM auth_management.profiles p
    LEFT JOIN gamification_system.user_stats us ON us.user_id = p.user_id
    LEFT JOIN gamification_system.comodines_inventory ci ON ci.user_id = p.id
    LEFT JOIN gamification_system.user_ranks ur ON ur.user_id = p.user_id
    LEFT JOIN progress_tracking.module_progress mp ON mp.user_id = p.id
    WHERE p.id = '<USER_ID>'
    GROUP BY p.id, p.email
)
SELECT * FROM user_initialization_check;

-- Resultado esperado:
-- has_user_stats = 1
-- has_comodines = 1
-- has_ranks = 1
-- has_module_progress = 1
-- module_count = N (número de módulos publicados)
```

**Criterios de Aceptación Global:**
- [ ] 100% de usuarios nuevos tienen `has_user_stats = 1`
- [ ] 100% de usuarios nuevos tienen `has_comodines = 1`
- [ ] 100% de usuarios nuevos tienen `has_ranks = 1`
- [ ] 100% de usuarios nuevos tienen `has_module_progress = 1`
- [ ] module_count debe ser igual al número de módulos publicados

---

## 📊 Métricas y Monitoreo

### KPIs de Inicialización

| Métrica | Objetivo | Medición |
|---------|----------|----------|
| **Tasa de inicialización completa** | 100% | % usuarios con 4/4 componentes |
| **Tiempo de inicialización** | < 1 segundo | Tiempo promedio del trigger |
| **Tasa de error** | < 0.1% | % de inicializaciones con fallo |
| **Usuarios sin module_progress** | 0 usuarios | COUNT de usuarios sin progreso |

### Alertas Recomendadas

1. ⚠️ **Alerta Alta:** Más de 5 usuarios sin module_progress en última hora
2. ⚠️ **Alerta Media:** Tiempo de inicialización > 2 segundos
3. ⚠️ **Alerta Baja:** Tasa de error > 0.5% en último día

---

## 🔧 Consideraciones de Implementación

### Estrategia de Idempotencia

**Problema:** ¿Qué pasa si el trigger se ejecuta múltiples veces?

**Solución:**
1. `user_stats`, `comodines_inventory`, `module_progress`: Usan `ON CONFLICT (user_id) DO NOTHING`
2. `user_ranks`: Usa `WHERE NOT EXISTS` (tabla sin unique constraint en user_id)

**Beneficio:** La función puede ejecutarse N veces sin crear duplicados.

### FK References: ¿auth.users.id o profiles.id?

**Regla Mnemotécnica:**

| Schema | FK Reference | Razón |
|--------|--------------|-------|
| `gamification_system` | → `auth.users.id` | Gamificación es multi-tenant, necesita user_id de Supabase |
| Otros schemas | → `profiles.id` | Necesitan profile_id local con tenant_id |

**Excepción:** `comodines_inventory` y `module_progress` usan `profiles.id` porque necesitan el contexto de tenant local.

### Manejo de Errores

**Filosofía:** La inicialización NO debe bloquear el registro.

- Si `user_stats` falla → El registro continúa (pero se logea error)
- Si `module_progress` falla → El registro continúa (pero usuario tiene experiencia degradada)
- El sistema debe ser **resiliente** y permitir **recuperación manual**

---

## 🐛 Historial de Bugs

### BUG FIX #1 - GAP-003: Module Progress Missing

**Fecha:** 2025-11-24
**Severidad:** Crítica
**Problema:** Los usuarios registrados NO tenían `module_progress` inicializado, causando "No modules available" en dashboard.

**Causa Raíz:** La función `gamilit.initialize_user_stats()` solo creaba 3 de 4 componentes (faltaba module_progress).

**Solución:** Se agregó la inicialización de `module_progress` en la función (líneas 60-82 del DDL).

**Evidencia:** Ver `orchestration/agentes/architecture-analyst/analisis-estado-proyecto-2025-11-24/VALIDACION-GAP-003-MODULE-PROGRESS.md`

**Métricas:**
- Antes del fix: 0% usuarios con module_progress (0/3 usuarios)
- Después del fix: 100% usuarios con module_progress (5/5 usuarios)

**Lecciones Aprendidas:**
1. ✅ Validación exhaustiva pre-corrección previene duplicados
2. ✅ Tests end-to-end deben validar inicialización completa
3. ✅ Monitoreo de inicialización debe ser proactivo

---

## 📚 Referencias

### Documentación Relacionada

- **ADR-012:** `docs/97-adr/ADR-012-automatic-user-initialization-trigger.md` - Decisión arquitectónica
- **ET-INIT-001:** `docs/01-fase-alcance-inicial/EAI-001-fundamentos/especificaciones/ET-INIT-001-trigger-inicializacion.md` - Especificación técnica
- **FLUJO-INICIALIZACION:** `docs/90-transversal/FLUJO-INICIALIZACION-USUARIO.md` - Flujo end-to-end
- **DIAGRAMA-DEPENDENCIAS:** `docs/90-transversal/DIAGRAMA-DEPENDENCIAS-INITIALIZE-USER-STATS.md` - Mapa de dependencias
- **TRACEABILITY:** `docs/01-fase-alcance-inicial/EAI-001-fundamentos/implementacion/TRACEABILITY.yml` - Trazabilidad completa

### Código Fuente

- **Función:** `apps/database/ddl/schemas/gamilit/functions/04-initialize_user_stats.sql`
- **Trigger:** `apps/database/ddl/schemas/auth_management/triggers/04-trg_initialize_user_stats.sql`

### Reportes de Validación

- **VALIDACION-GAP-003:** `orchestration/agentes/architecture-analyst/analisis-estado-proyecto-2025-11-24/VALIDACION-GAP-003-MODULE-PROGRESS.md`
- **VALIDACION-FINAL:** `orchestration/agentes/architecture-analyst/analisis-estado-proyecto-2025-11-24/VALIDACION-FINAL-EXHAUSTIVA.md`

---

**Fin del Requerimiento RF-INIT-001**

**Autor:** Architecture-Analyst
**Fecha de creación:** 2025-11-24
**Versión:** 1.1
**Estado:** ✅ Implementado y Validado
