workspace/projects/gamilit/docs/sistema-recompensas/00-INVENTARIO-CAMBIOS.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- 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>
2025-12-08 10:44:23 -06:00

14 KiB

📋 INVENTARIO DE CAMBIOS - SISTEMA DE RECOMPENSAS Y PROGRESO

Versión: v2.8.0 Fecha: 2025-11-29 Estado: COMPLETO Y VERIFICADO


📊 Resumen Ejecutivo

Categoría Archivos Modificados Archivos Creados Total
Base de Datos 1 función 2 (función + trigger) 3
Backend 3 controllers + 1 service 0 4
Frontend 1 page 2 hooks 3
Documentación 6 archivos 8 archivos nuevos 14
TOTAL 11 12 23

🆕 CAMBIOS v2.8.0 - Sistema de Misiones earn_xp (2025-11-29)

Problema Resuelto

Las misiones de tipo earn_xp no se actualizaban cuando los ejercicios eran calificados vía exercise_submissions. Solo se actualizaban desde exercise_attempts.

Nuevos Objetos de Base de Datos

gamilit.update_user_stats_on_submission_graded() (NUEVA)

Archivo: apps/database/ddl/schemas/gamilit/functions/27-update_user_stats_on_submission_graded.sql

Propósito: Actualiza user_stats cuando una submission es calificada correctamente.

Cambios:

  • Valida status IN ('graded', 'reviewed')
  • Valida is_correct = true
  • Valida xp_earned > 0
  • Evita re-disparos con IS DISTINCT FROM
  • Patrón UPSERT para crear user_stats si no existe
  • SECURITY DEFINER para permisos cross-schema

trg_update_user_stats_on_submission (NUEVO)

Archivo: apps/database/ddl/schemas/progress_tracking/triggers/31-trg_update_user_stats_on_submission.sql

Evento: AFTER UPDATE ON exercise_submissions Condición WHEN: status IN ('graded','reviewed') AND is_correct = true AND estado cambió

Cambios en Backend

ExerciseAttemptService.updateMissionsProgress()

Archivo: apps/backend/src/modules/progress/services/exercise-attempt.service.ts

Cambios:

  • Línea 80: Agregado parámetro savedAttempt.xp_earned
  • Línea 644: Nueva firma con xpEarned: number = 0
  • Líneas 682-702: Nueva lógica para actualizar misiones earn_xp

Cadena de Triggers Completada

FLUJO A (Autocorregibles):
exercise_attempts INSERT → trigger 21 → user_stats → trigger 27 → misiones earn_xp ✅

FLUJO B (Revisión Manual - NUEVO):
exercise_submissions UPDATE → trigger 31 → user_stats → trigger 27 → misiones earn_xp ✅

Arquitectura BD-First

  • Triggers como fuente de verdad
  • Backend como capa de redundancia
  • Modificaciones directas en BD disparan triggers

🗄️ 1. CAMBIOS EN BASE DE DATOS

1.1 Funciones Modificadas

gamilit.update_user_stats_on_exercise_complete()

Archivo: apps/database/ddl/schemas/gamilit/functions/14-update_user_stats_on_exercise_complete.sql

Cambios Realizados:

  • Línea 26: coins_earnedml_coins_earned (fix en lectura de columna)
  • Línea 37: ml_coins_balanceml_coins (fix en actualización)
  • Línea 38: Agregado ml_coins_earned_total para tracking total
  • Línea 50: ml_coins_balanceml_coins (fix en INSERT)
  • Línea 51: Agregado ml_coins_earned_total en INSERT
  • Línea 58: Balance inicial corregido: 100 + v_coins_earned

Motivo: Desajuste entre nombres de columnas en tabla vs función. El trigger estaba fallando silenciosamente.

Impacto:

  • Trigger ahora funciona correctamente
  • Recompensas se otorgan y actualizan user_stats
  • Balance inicial correcto (100 ML Coins + rewards del primer ejercicio)

Estado: Aplicado en base de datos y archivo DDL actualizado


1.2 Triggers (Sin Cambios)

trg_update_user_stats_on_exercise

Archivo: apps/database/ddl/schemas/progress_tracking/triggers/21-trg_update_user_stats_on_exercise.sql

Estado: Funcionando correctamente (no requirió cambios) Uso: Se dispara AFTER INSERT en progress_tracking.exercise_attempts


1.3 Tablas Involucradas (Sin Cambios en Esquema)

progress_tracking.exercise_attempts

  • Uso: Almacena intentos de ejercicios con recompensas calculadas
  • Campos clave: xp_earned, ml_coins_earned, is_correct, score
  • Trigger: Dispara update_user_stats_on_exercise_complete()

progress_tracking.exercise_submissions

  • Uso: Workflow de submissions (draft → submitted → graded)
  • Estado: Integrado con exercise_attempts

gamification_system.user_stats

  • Uso: Estadísticas acumuladas del usuario
  • Campos clave: total_xp, ml_coins, ml_coins_earned_total, exercises_completed
  • Estado: Actualizado automáticamente por trigger

💻 2. CAMBIOS EN BACKEND

2.1 Controllers Modificados

ExercisesController

Archivo: apps/backend/src/modules/educational/controllers/exercises.controller.ts

Métodos Modificados:

GET /exercises

Líneas: 59-138

Cambios:

  • Agregado @UseGuards(JwtAuthGuard) (línea 60)
  • Agregado parámetro @Request() req: any (línea 63)
  • Extracción de userId desde req.user.id (línea 64)
  • Obtención de submissions del usuario (línea 70)
  • Creación de Map de ejercicios completados (líneas 73-78)
  • Agregado campo completed a cada ejercicio (líneas 81-84)

Nuevo Retorno:

{
  ...exercise,
  completed: completedExercisesMap.get(exercise.id) || false
}
GET /exercises/:id

Líneas: 127-239

Cambios:

  • Agregado @UseGuards(JwtAuthGuard) (línea 128)
  • Agregado NotFoundException a imports
  • Agregado parámetro @Request() req: any (línea 133)
  • Extracción de userId (línea 134)
  • Verificación de ejercicio (líneas 137-141)
  • Verificación de submission del usuario (línea 144)
  • Cálculo de completed (línea 145)
  • Retorno con campo completed (líneas 148-151)

Estado: Compilado y funcionando


ModulesController

Archivo: apps/backend/src/modules/educational/controllers/modules.controller.ts

Métodos Modificados:

GET /modules

Líneas: 60-148

Cambios:

  • Agregado imports: Request, UseGuards, ExercisesService, ExerciseSubmissionService, JwtAuthGuard
  • Actualizado constructor para inyectar nuevos servicios (líneas 36-40)
  • Agregado @UseGuards(JwtAuthGuard) (línea 61)
  • Agregado parámetro @Request() req: any (línea 68)
  • Extracción de userId (línea 69)
  • Obtención de submissions del usuario (línea 75)
  • Creación de Map de ejercicios completados (líneas 78-83)
  • Obtención de todos los ejercicios (línea 86)
  • Agrupación de ejercicios por módulo (líneas 89-95)
  • Cálculo de progreso por módulo (líneas 98-111)

Nuevo Retorno por Módulo:

{
  ...module,
  total_exercises: number,
  completed_exercises: number,
  progress: number (0-100%),
  completed: boolean
}

Estado: Compilado y funcionando


2.2 Services (Sin Cambios)

ExerciseAttemptService

Archivo: apps/backend/src/modules/progress/services/exercise-attempt.service.ts

Estado: Funcionando correctamente (no requirió cambios)

  • Calcula xp_earned y ml_coins_earned correctamente
  • No sobrescribe valores con 0
  • Aplica penalizaciones por hints/powerups

🎨 3. CAMBIOS EN FRONTEND

3.1 Pages Modificadas

ModuleDetailPage.tsx

Archivo: apps/frontend/src/apps/student/pages/ModuleDetailPage.tsx

Cambios:

  • Línea 165: Agregado logout a destructuring de useAuth()
  • Líneas 212-216: Actualizado handler de onLogout (3 ocurrencias)

Cambio en onLogout:

// ANTES
onLogout={() => navigate('/login')}

// DESPUÉS
onLogout={async () => {
  await logout();
  // No need to navigate - performLogout() handles redirect
}}

Estado: Compilado y funcionando (el hook useModuleDetail ya existía conceptualmente)


3.2 Hooks Creados

useModules.ts (NUEVO)

Archivo: apps/frontend/src/shared/hooks/useModules.ts

Propósito: Hook para obtener detalles de módulo y sus ejercicios con estado de completado

Funcionalidad:

  • Fetch de módulo: GET /api/educational/modules/:id
  • Fetch de ejercicios: GET /api/educational/exercises (con campo completed)
  • Filtrado de ejercicios por module_id
  • Ordenamiento por order_index
  • Autenticación con JWT token
  • Estados: loading, error

Retorno:

{
  module: Module | null,
  exercises: Exercise[],  // con campo completed
  loading: boolean,
  error: string | null
}

Estado: Creado y funcionando

index.ts (NUEVO)

Archivo: apps/frontend/src/shared/hooks/index.ts

Propósito: Export index para hooks compartidos

Contenido:

export { useModuleDetail } from './useModules';

Estado: Creado


📚 4. DOCUMENTACIÓN CREADA

4.1 Documentación de Base de Datos

14-update_user_stats_on_exercise_complete.sql

Actualizado: 2025-11-12 Cambios:

  • Código actualizado con correcciones
  • Changelog agregado (líneas 141-155)
  • Notas de implementación actualizadas

4.2 Documentación del Sistema

00-INVENTARIO-CAMBIOS.md (ESTE ARCHIVO)

Ubicación: docs/sistema-recompensas/00-INVENTARIO-CAMBIOS.md Contenido: Inventario completo de todos los cambios realizados

01-ARQUITECTURA-SISTEMA.md

Ubicación: docs/sistema-recompensas/01-ARQUITECTURA-SISTEMA.md Contenido: Arquitectura completa del sistema de recompensas

02-FLUJO-END-TO-END.md

Ubicación: docs/sistema-recompensas/02-FLUJO-END-TO-END.md Contenido: Diagrama y explicación del flujo completo

03-API-ENDPOINTS.md

Ubicación: docs/sistema-recompensas/03-API-ENDPOINTS.md Contenido: Documentación de endpoints modificados

04-DATABASE-SCHEMA.md

Ubicación: docs/sistema-recompensas/04-DATABASE-SCHEMA.md Contenido: Esquema de base de datos y trigger

05-TEST-RESULTS.md

Ubicación: docs/sistema-recompensas/05-TEST-RESULTS.md Contenido: Resultados de pruebas end-to-end


🔍 5. TRAZABILIDAD DE CAMBIOS

5.1 Commits Git

# Ver cambios en base de datos
git log --oneline apps/database/ddl/schemas/gamilit/functions/14-update_user_stats_on_exercise_complete.sql

# Ver cambios en backend
git log --oneline apps/backend/src/modules/educational/controllers/exercises.controller.ts
git log --oneline apps/backend/src/modules/educational/controllers/modules.controller.ts

# Ver cambios en frontend
git log --oneline apps/frontend/src/shared/hooks/useModules.ts
git log --oneline apps/frontend/src/apps/student/pages/ModuleDetailPage.tsx

5.2 Archivos Afectados por Path

apps/database/ddl/schemas/
├── gamilit/functions/
│   └── 14-update_user_stats_on_exercise_complete.sql (MODIFICADO)
└── progress_tracking/triggers/
    └── 21-trg_update_user_stats_on_exercise.sql (sin cambios)

apps/backend/src/modules/
├── educational/controllers/
│   ├── exercises.controller.ts (MODIFICADO)
│   └── modules.controller.ts (MODIFICADO)
└── progress/services/
    └── exercise-attempt.service.ts (sin cambios, pero verificado)

apps/frontend/src/
├── shared/hooks/
│   ├── useModules.ts (CREADO)
│   └── index.ts (CREADO)
└── apps/student/pages/
    └── ModuleDetailPage.tsx (MODIFICADO - logout handler)

docs/sistema-recompensas/
├── 00-INVENTARIO-CAMBIOS.md (CREADO)
├── 01-ARQUITECTURA-SISTEMA.md (CREADO)
├── 02-FLUJO-END-TO-END.md (CREADO)
├── 03-API-ENDPOINTS.md (CREADO)
├── 04-DATABASE-SCHEMA.md (CREADO)
└── 05-TEST-RESULTS.md (CREADO)

6. VERIFICACIÓN Y TESTING

6.1 Tests Ejecutados

Test Resultado Fecha
Trigger actualiza user_stats PASS 2025-11-12
Endpoint GET /exercises retorna completed PASS 2025-11-12
Endpoint GET /modules retorna progress PASS 2025-11-12
Hook useModuleDetail funciona PASS 2025-11-12
Test end-to-end completo PASS 2025-11-12

6.2 Métricas de Prueba

  • Ejercicios completados: 1/5
  • XP otorgado: 200
  • ML Coins otorgados: 50
  • Progreso módulo: 20%
  • Estado ejercicio: completed: true

🚀 7. ESTADO DEL SISTEMA

Componente Estado Observaciones
Base de Datos PROD Trigger funcionando
Backend PROD Compilado sin errores
Frontend PROD Hook creado y funcionando
Tests PASS End-to-end verificado
Documentación COMPLETA 6 archivos creados

📋 8. PRÓXIMOS PASOS (Opcional)

Mejoras Futuras

  1. Agregar cache de submissions en frontend
  2. Implementar WebSocket para actualización en tiempo real de stats
  3. Agregar analytics de progreso por módulo
  4. Dashboard de progreso del estudiante

Última actualización: 2025-11-29 09:30 GMT-6 Responsable: Claude Code (Sistema Automatizado) Versión del documento: 2.8.0