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
229 lines
6.5 KiB
Markdown
229 lines
6.5 KiB
Markdown
# 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):**
|
|
```typescript
|
|
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):**
|
|
```typescript
|
|
/**
|
|
* 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```sql
|
|
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
|
|
|
|
```bash
|
|
cd apps/backend && npx tsc --noEmit
|
|
```
|
|
|
|
### Paso 4: Probar endpoints manualmente
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```sql
|
|
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:
|
|
|
|
```typescript
|
|
// 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:
|
|
```sql
|
|
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
|