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
11 KiB
PLAN DE IMPLEMENTACIÓN: CORRECCIONES ACHIEVEMENTS PAGE
Fecha: 2026-01-10 Proyecto: Gamilit Componente: /achievements (Student Portal) Basado en: ANALISIS-ACHIEVEMENTS-PAGE-2026-01-10.md Estado: EN PLANEACIÓN
RESUMEN DE PROBLEMAS IDENTIFICADOS
Críticos (Deben corregirse)
| ID | Problema | Prioridad |
|---|---|---|
| P1 | Función SQL claim_achievement_reward() usa columnas inexistentes |
🔴 CRÍTICO |
| P2 | Store usa || en lugar de ?? para recompensas |
🔴 CRÍTICO |
| P3 | completion_percentage es STRING, no se parsea en Store |
🔴 CRÍTICO |
Importantes (Deberían corregirse)
| ID | Problema | Prioridad |
|---|---|---|
| P4 | Duplicación de ml_coins_reward |
🟡 IMPORTANTE |
| P5 | Duplicación de points_value vs rewards.xp |
🟡 IMPORTANTE |
| P6 | Alias conflictivo Achievement en achievementsTypes.ts |
🟡 IMPORTANTE |
| P7 | unlockedAt es string vs Date inconsistente |
🟡 IMPORTANTE |
| P8 | Category mapping incompleto | 🟡 IMPORTANTE |
PLAN DE CORRECCIONES
FASE A: Correcciones Críticas de Base de Datos
A.1 Reparar función claim_achievement_reward()
Archivo: /apps/database/ddl/schemas/gamification_system/functions/claim_achievement_reward.sql
Cambios requeridos:
- Cambiar referencia a
v_user_achievement.reward_claimed_atporv_user_achievement.rewards_claimed - Usar
v_user_achievement.completed_atpara verificar timestamp - Extraer XP de
v_achievement.rewards->>'xp'en lugar dev_achievement.xp_reward
Verificación:
- Función compila sin errores
- Test de reclamar recompensa funciona
- No se puede reclamar dos veces
FASE B: Correcciones Críticas de Frontend
B.1 Corregir achievementsStore.ts - Operador nullish
Archivo: /apps/frontend/src/features/gamification/social/store/achievementsStore.ts
Líneas a modificar: ~165-180
Cambios:
// ANTES
mlCoinsReward: ach.rewards?.ml_coins || ach.ml_coins_reward || 0,
xpReward: ach.rewards?.xp || 0,
// DESPUÉS
mlCoinsReward: ach.rewards?.ml_coins ?? ach.ml_coins_reward ?? 0,
xpReward: ach.rewards?.xp ?? ach.points_value ?? 0,
Verificación:
- Achievements con 0 ML Coins muestran correctamente
- Achievements con 0 XP muestran correctamente
- No hay errores en consola
B.2 Parsear completion_percentage en Store
Archivo: /apps/frontend/src/features/gamification/social/store/achievementsStore.ts
Cambios:
// Agregar transformación al mapear achievements
completionPercentage: typeof ach.completion_percentage === 'string'
? parseFloat(ach.completion_percentage)
: ach.completion_percentage ?? 0,
Verificación:
- Porcentaje se muestra correctamente como número
- Progress bars funcionan con valores decimales
FASE C: Mejoras de Consistencia de Tipos
C.1 Completar mapeo de categorías
Archivo: /apps/frontend/src/features/gamification/social/api/achievementsAPI.ts
Función: mapCategory()
Cambios:
function mapCategory(backendCategory: string): FrontendCategory {
const categoryMap: Record<string, FrontendCategory> = {
'educational': 'progress',
'progress': 'progress',
'streak': 'streak', // ← AGREGAR
'mastery': 'mastery',
'skill': 'mastery',
'social': 'social',
'hidden': 'hidden',
'special': 'hidden',
'exploration': 'exploration', // ← AGREGAR
'collection': 'collection', // ← AGREGAR
'completion': 'completion', // ← AGREGAR
'missions': 'progress',
};
return categoryMap[backendCategory.toLowerCase()] ?? 'progress';
}
Verificación:
- Todas las categorías de la BD se mapean correctamente
- Filtros de categoría funcionan
- Badges de categoría muestran correctamente
C.2 Estandarizar timestamp unlockedAt
Archivos a revisar:
/apps/frontend/src/features/gamification/social/types/achievementsTypes.ts/apps/frontend/src/shared/types/achievement.types.ts
Cambios:
- Definir
unlockedAtcomo campo canónico (siemprestring | undefined) - Eliminar duplicados (
earnedAt,claimedAtsi no se usan) - Documentar en comentarios
Verificación:
- TypeScript no muestra errores de tipo
- Fechas se formatean correctamente en UI
FASE D: Validación de Seeds
D.1 Verificar consistencia de seeds con DDL
Archivos a verificar:
/apps/database/seeds/dev/gamification_system/01-achievement_categories.sql/apps/database/seeds/dev/gamification_system/04-achievements.sql/apps/database/seeds/dev/gamification_system/08-user_achievements.sql
Checklist:
- Todas las columnas insertadas existen en DDL
- Tipos de datos coinciden
- FKs apuntan a registros existentes
- Valores de ENUM son válidos
- Estructura de JSONB
conditionses correcta - Estructura de JSONB
rewardses correcta
D.2 Validar datos de user_achievements
Verificar:
user_idexiste enauth_management.profilesachievement_idexiste engamification_system.achievementsprogress<=max_progresscompletion_percentage=(progress / max_progress) * 100- Si
is_completed = true, entoncescompleted_atno es NULL
FASE E: Testing End-to-End
E.1 Verificar flujo completo de achievements
Test 1: Carga inicial
- GET /achievements retorna lista correcta
- GET /users/:id/achievements retorna progreso
- GET /users/:id/achievements/summary retorna estadísticas
Test 2: Filtrado y ordenamiento
- Filtro por categoría funciona
- Filtro por estado funciona
- Búsqueda por nombre funciona
- Ordenamiento por todos los criterios funciona
Test 3: Reclamar recompensas
- POST claim funciona para achievements completados
- ML Coins se suman al usuario
- XP se suma al usuario
- No se puede reclamar dos veces
Test 4: UI/UX
- Cards muestran información correcta
- Modal de detalle muestra progreso
- Achievements ocultos no se muestran si locked
- Achievements ocultos se muestran si unlocked
MATRIZ DE ARCHIVOS A MODIFICAR
| Archivo | Fase | Cambio |
|---|---|---|
claim_achievement_reward.sql |
A | Reparar columnas |
achievementsStore.ts |
B | ?? operator + parseFloat |
achievementsAPI.ts |
C | Category mapping |
achievementsTypes.ts |
C | Estandarizar timestamps |
achievement.types.ts |
C | Documentar campos canónicos |
DEPENDENCIAS ENTRE CORRECCIONES
┌─────────────────────────────────────────────────────────────┐
│ FASE A (Base de Datos) │
│ claim_achievement_reward.sql │
└─────────────────────────────────────────────────────────────┘
│
│ (Debe completarse primero para que el backend funcione)
▼
┌─────────────────────────────────────────────────────────────┐
│ FASE B (Frontend Store) │
│ achievementsStore.ts - nullish coalescing │
│ achievementsStore.ts - parseFloat │
└─────────────────────────────────────────────────────────────┘
│
│ (Store corregido antes de tipos)
▼
┌─────────────────────────────────────────────────────────────┐
│ FASE C (Tipos y API) │
│ achievementsAPI.ts - category mapping │
│ achievementsTypes.ts - estandarizar timestamps │
└─────────────────────────────────────────────────────────────┘
│
│ (Código corregido antes de validar seeds)
▼
┌─────────────────────────────────────────────────────────────┐
│ FASE D (Seeds) │
│ Verificar consistencia de datos │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FASE E (Testing) │
│ Validación end-to-end │
└─────────────────────────────────────────────────────────────┘
CRITERIOS DE ACEPTACIÓN
Para considerar correcciones COMPLETADAS:
-
Base de Datos:
- Función
claim_achievement_reward()ejecuta sin errores - Trigger
trg_achievement_unlockedfunciona correctamente
- Función
-
Backend:
- Todos los endpoints responden correctamente
- Tipos de datos son correctos en responses
-
Frontend:
- No hay errores en consola del navegador
- TypeScript compila sin errores
- Datos se muestran correctamente en UI
-
Seeds:
- Datos de prueba cargan sin errores
- Relaciones FK son válidas
-
Testing:
- Flujo completo de achievements funciona
- Reclamar recompensas funciona
- Filtros y búsqueda funcionan
NOTAS IMPORTANTES
Decisiones de Diseño
-
Fuente única de verdad para recompensas:
- Se usará
rewardsJSONB como SSOT - Las columnas
ml_coins_rewardypoints_valuese mantienen por compatibilidad - Frontend debe leer primero de
rewards, luego de columnas
- Se usará
-
Timestamp canónico:
unlockedAt(frontend) =completed_at(backend)- Siempre como string ISO 8601
-
Category mapping:
- Backend puede enviar cualquier string
- Frontend mapea a categorías conocidas
- Default: 'progress'
Riesgos Identificados
-
Función SQL rota: Actualmente
claim_achievement_reward()no funciona. Reclamar recompensas via SQL fallará. -
Datos legacy: Pueden existir registros con
completion_percentagecomo string. El frontend debe manejar ambos tipos. -
Categorías desconocidas: Si el backend agrega nuevas categorías, el frontend las mostrará como 'progress' hasta actualizar el mapeo.
Documento generado: 2026-01-10 Siguiente Fase: Validación de planeación contra requisitos