workspace-v1/orchestration/analisis/PLAN-FIX-GAMIFICATION-SUMMARY-2026-01-10.md
rckrdmrd e56e927a4d [MAINT-001] docs(orchestration): Actualizacion directivas SIMCO, perfiles y documentacion
Cambios incluidos:
- INDICE-DIRECTIVAS-WORKSPACE.yml actualizado
- Perfiles de agentes: PERFIL-ML.md, PERFIL-SECURITY.md
- Directivas SIMCO actualizadas:
  - SIMCO-ASIGNACION-PERFILES.md
  - SIMCO-CCA-SUBAGENTE.md
  - SIMCO-CONTEXT-ENGINEERING.md
  - SIMCO-CONTEXT-RESOLUTION.md
  - SIMCO-DELEGACION-PARALELA.md
- Inventarios actualizados: DEVENV-MASTER, DEVENV-PORTS
- Documentos de analisis agregados:
  - Analisis y planes de fix student portal
  - Analisis scripts BD
  - Analisis achievements, duplicados, gamification
  - Auditoria documentacion gamilit
  - Backlog discrepancias NEXUS
  - Planes maestros de resolucion
- Reportes de ejecucion agregados
- Knowledge base gamilit README actualizado
- Referencia submodulo gamilit actualizada (commit beb94f7)

Validaciones:
- Plan validado contra directivas SIMCO-GIT
- Dependencias verificadas
- Build gamilit: EXITOSO
2026-01-10 04:51:28 -06:00

6.5 KiB

PLAN DE CORRECCION - ERRORES GAMIFICATION SUMMARY

Fecha: 2026-01-10 Proyecto: Gamilit Estado: EN PLANEACION Referencia: ANALISIS-ERRORES-GAMIFICATION-SUMMARY-2026-01-10.md Conventional Commits: fix(gamification): correct profile lookup by id instead of user_id


0. RESUMEN EJECUTIVO

Problema

Error 500 y 404 en endpoints de gamificación /summary debido a búsqueda incorrecta de profile.

Causa Raíz

El método validateProfileExists busca por profiles.user_id (FK a auth.users) en lugar de profiles.id (PK referenciado por user_stats FK).

Solución

Cambiar la búsqueda de { user_id: userId } a { id: userId } en user-stats.service.ts:52.

Impacto

  • Backend: 1 archivo, 1 línea de código
  • Base de datos: Ninguno
  • Frontend: Ninguno

1. ARCHIVOS A MODIFICAR

1.1 Cambio Principal

ID Archivo Línea Cambio
CORR-GAM-001 apps/backend/src/modules/gamification/services/user-stats.service.ts 52 Cambiar user_id por id

1.2 Código Actual vs Nuevo

ANTES (líneas 50-62):

private async validateProfileExists(userId: string): Promise<Profile> {
  const profile = await this.profileRepo.findOne({
    where: { user_id: userId },  // INCORRECTO
  });

  if (!profile) {
    throw new NotFoundException(
      `Profile not found for user ${userId}. User may not be properly initialized. ` +
      `Please ensure the user registration process completed successfully.`
    );
  }

  return profile;
}

DESPUÉS (líneas 50-67):

/**
 * P0-001: Verifica que el perfil existe antes de operaciones de gamificación
 *
 * CORR-GAM-001: Corregido para buscar por profiles.id (PK) en lugar de
 * profiles.user_id (FK a auth.users). La FK user_stats_user_id_fkey
 * referencia profiles(id), no profiles(user_id).
 *
 * @param userId - El ID del profile (profiles.id), NO el ID de auth.users
 * @returns Profile si existe
 * @throws NotFoundException si el perfil no existe
 */
private async validateProfileExists(userId: string): Promise<Profile> {
  // CORR-GAM-001: Buscar por id (PK) no por user_id (FK a auth.users)
  const profile = await this.profileRepo.findOne({
    where: { id: userId },
  });

  if (!profile) {
    throw new NotFoundException(
      `Profile not found for id ${userId}. User may not be properly initialized. ` +
      `Please ensure the user registration process completed successfully.`
    );
  }

  return profile;
}

2. DEPENDENCIAS VERIFICADAS

2.1 Archivos que llaman validateProfileExists

# Grep realizado - Solo 1 llamada:
user-stats.service.ts:86 → this.validateProfileExists(userId)

Conclusión: Solo el método create() usa validateProfileExists, no hay otros consumidores.

2.2 Archivos que serán corregidos automáticamente

Una vez que validateProfileExists funcione correctamente, los siguientes endpoints funcionarán:

Endpoint Archivo Estado Actual Estado Post-Fix
GET /users/:id/summary user-stats.controller.ts 500 200 OK
GET /users/:id/achievements/summary achievements.controller.ts 404 200 OK
GET /users/:id/stats user-stats.controller.ts 404 200 OK
GET /users/:id/rank user-stats.controller.ts 404 200 OK

2.3 Base de Datos

Objeto Cambio Requerido
user_stats tabla Ninguno - DDL correcto
user_stats_user_id_fkey FK Ninguno - apunta a profiles(id) correctamente
profiles tabla Ninguno - estructura correcta

2.4 Frontend

Archivo Cambio Requerido
gamificationAPI.ts Ninguno - envía profile.id correcto
gamification.api.ts Ninguno - envía profile.id correcto
useUserGamification.ts Ninguno
AchievementsPage.tsx Ninguno

3. PLAN DE EJECUCION

Paso 1: Validar que profile existe en BD

SELECT id, user_id, email, display_name, role
FROM auth_management.profiles
WHERE id = 'cccccccc-cccc-cccc-cccc-cccccccccccc';

Paso 2: Aplicar corrección CORR-GAM-001

Modificar apps/backend/src/modules/gamification/services/user-stats.service.ts:

  • Línea 52: { user_id: userId }{ id: userId }
  • Agregar comentario explicativo con ID CORR-GAM-001

Paso 3: Verificar compilación TypeScript

cd apps/backend && npx tsc --noEmit

Paso 4: Probar endpoints manualmente

# Endpoint 1: Summary
curl -X GET http://localhost:3006/api/v1/gamification/users/cccccccc-cccc-cccc-cccc-cccccccccccc/summary \
  -H "Authorization: Bearer <token>"

# Endpoint 2: Achievements Summary
curl -X GET http://localhost:3006/api/v1/gamification/users/cccccccc-cccc-cccc-cccc-cccccccccccc/achievements/summary \
  -H "Authorization: Bearer <token>"

4. VALIDACION POST-CORRECCION

4.1 Verificar user_stats creado

SELECT id, user_id, level, total_xp, ml_coins, current_rank
FROM gamification_system.user_stats
WHERE user_id = 'cccccccc-cccc-cccc-cccc-cccccccccccc';

Resultado esperado: 1 fila con valores iniciales (level=1, total_xp=0, ml_coins=100)

4.2 Verificar respuesta de endpoints

Endpoint Código Esperado Respuesta Esperada
/summary 200 { userId, level, totalXP, mlCoins, rank, ... }
/achievements/summary 200 { total_available, completed, completion_percentage, unclaimed_rewards }

5. ROLLBACK

Si algo sale mal:

// Revertir línea 52 de user-stats.service.ts
where: { id: userId }  // → revertir a:
where: { user_id: userId }

Y eliminar el registro de user_stats creado:

DELETE FROM gamification_system.user_stats
WHERE user_id = 'cccccccc-cccc-cccc-cccc-cccccccccccc';

6. MENSAJE DE COMMIT

fix(gamification): correct profile lookup by id instead of user_id

CORR-GAM-001: The validateProfileExists method was searching for profiles
using profiles.user_id (FK to auth.users) instead of profiles.id (PK).

The FK user_stats_user_id_fkey references profiles(id), so when creating
user_stats records, we must validate the profile exists by its PK (id),
not by its FK to auth.users (user_id).

This fixes:
- Error 500 on GET /gamification/users/:userId/summary
- Error 404 on GET /gamification/users/:userId/achievements/summary

Refs: ANALISIS-ERRORES-GAMIFICATION-SUMMARY-2026-01-10.md

Elaborado por: Claude (Arquitecto Técnico) Fecha: 2026-01-10 Próximo paso: FASE 4 - Validación del Plan