# FASE 4: VALIDACIÓN DE PLAN - DUPLICADOS ACHIEVEMENTS **Fecha:** 2026-01-10 **Proyecto:** Gamilit **Basado en:** PLAN-DUPLICADOS-ACHIEVEMENTS-2026-01-10.md **Estado:** VALIDACIÓN COMPLETADA --- ## 1. HALLAZGO CRÍTICO: TRIPLE DISTRIBUCIÓN DE RECOMPENSAS ### 1.1 Descubrimiento Se identificó que las recompensas de achievements se distribuyen **TRES VECES**: | # | Momento | Función/Trigger | Da XP | Da Coins | Registra Trans. | |---|---------|-----------------|-------|----------|-----------------| | 1 | Desbloqueo | `check_and_grant_achievements` | ✅ | ✅ | ✅ | | 2 | Auto-trigger | `fn_on_achievement_unlocked` (trigger) | ✅ | ✅ | ✅ | | 3 | Reclamar | `claim_achievement_reward` | ✅ | ✅ | ✅ | ### 1.2 Flujo Actual (PROBLEMÁTICO) ``` Usuario completa misión │ ▼ grant_mission_completion_rewards() │ ├──► check_and_grant_achievements() │ │ │ ├──► INSERT user_achievements (is_completed = true) │ │ │ │ │ └──► [TRIGGER] fn_on_achievement_unlocked() │ │ │ │ │ ├──► UPDATE user_stats (XP + Coins) ⚠️ PRIMER PAGO │ │ └──► INSERT ml_coins_transactions │ │ │ ├──► UPDATE user_stats (XP + Coins) ⚠️ SEGUNDO PAGO │ └──► INSERT ml_coins_transactions │ ▼ Usuario hace click "Reclamar" │ ▼ claim_achievement_reward() │ ├──► UPDATE user_stats (XP + Coins) ⚠️ TERCER PAGO └──► INSERT ml_coins_transactions ``` ### 1.3 Impacto Económico Si un achievement da 100 XP y 50 ML Coins: - **Usuario recibe:** 300 XP y 150 ML Coins (3x lo esperado) - **Inflación:** Sistema de economía completamente roto --- ## 2. VALIDACIÓN DE DEPENDENCIAS ### 2.1 achievementsAPI.ts | Consumer | Archivo | Método Usado | Impacto de Deprecar | |----------|---------|--------------|---------------------| | Store | `achievementsStore.ts:16` | `getUserAchievements` | ⚠️ Requiere migrar a gamification.api | | Test | `achievementsStore.test.ts` | Mock completo | 🟡 Actualizar mocks | | Test | `DashboardIntegration.test.tsx` | Mock completo | 🟡 Actualizar mocks | | Test | `AchievementsIntegration.test.tsx` | Mock completo | 🟡 Actualizar mocks | **Conclusión:** El store usa `getUserAchievements` de achievementsAPI.ts. Al deprecar, debe migrarse a `gamificationApi.getUserAchievements`. ### 2.2 Root Hook /hooks/useAchievements.ts | Consumer | Archivo | Impacto | |----------|---------|---------| | Ninguno | N/A | ✅ SAFE - No tiene importadores | **Conclusión:** El hook raíz de 450 líneas NO está siendo usado. SAFE to deprecate. ### 2.3 gamificationApi.claimAchievement | Consumer | Archivo | Línea | Impacto | |----------|---------|-------|---------| | AchievementsPage | `AchievementsPage.tsx` | 274 | 🟡 Depende del fix backend | **Conclusión:** Solo un consumidor. Cambios en backend afectarán esta página. ### 2.4 check_and_grant_achievements SQL | Consumer | Archivo | Línea | Contexto | |----------|---------|-------|----------| | `grant_mission_completion_rewards` | `06-update_mission_progress.sql` | 77 | Llamado al completar misión | **Conclusión:** Esta función ES usada. Cambios deben ser cuidadosos. ### 2.5 Trigger fn_on_achievement_unlocked | Tabla | Evento | Impacto | |-------|--------|---------| | `user_achievements` | INSERT or UPDATE (is_completed) | Activa distribución automática | **Conclusión:** Este trigger ES la fuente de duplicación. Decisión arquitectónica requerida. --- ## 3. DECISIÓN ARQUITECTÓNICA REVISADA ### 3.1 Opción A: Auto-Earn (Recompensas Automáticas) **Modelo:** Recompensas se dan automáticamente al desbloquear **Cambios Requeridos:** 1. ✅ Mantener trigger `fn_on_achievement_unlocked` 2. ❌ Remover distribución de `check_and_grant_achievements` 3. ❌ Remover distribución de `claim_achievement_reward` 4. ⚠️ `claim_achievement_reward` solo marca flag `rewards_claimed` **Pros:** - Flujo más simple - Usuario ve recompensas inmediatamente **Cons:** - Sin "ceremonia" de reclamar - Menos engagement UX ### 3.2 Opción B: Claim-to-Earn (Reclamar para Ganar) - RECOMENDADA **Modelo:** Recompensas solo se dan al hacer click "Reclamar" **Cambios Requeridos:** 1. ❌ Desactivar trigger `fn_on_achievement_unlocked` (solo notificación, no rewards) 2. ❌ Remover distribución de `check_and_grant_achievements` 3. ✅ `claim_achievement_reward` es única fuente de rewards **Pros:** - UX de "reclamar" más satisfactoria - Usuario tiene control - Consistente con misiones y ejercicios **Cons:** - Más código para mantener - Usuario podría olvidar reclamar ### 3.3 DECISIÓN: Opción B (Claim-to-Earn) **Justificación:** - Misiones ya usan modelo claim-to-earn (`mission-claim.service.ts`) - Ejercicios usan modelo claim-to-earn (`exercise-rewards.service.ts`) - Consistencia en toda la plataforma --- ## 4. PLAN REVISADO ### 4.1 Fase A: SQL (Base de Datos) | Orden | Archivo | Cambio | Prioridad | |-------|---------|--------|-----------| | A.1 | `check_and_award_achievements.sql` | Remover UPDATE user_stats y INSERT ml_coins_transactions | 🔴 CRÍTICO | | A.2 | `fn_on_achievement_unlocked` (trigger function) | Remover distribución de XP/Coins, mantener solo notificación | 🔴 CRÍTICO | | A.3 | `claim_achievement_reward.sql` | ✅ Ya corregida - es la única fuente | ✅ LISTO | ### 4.2 Fase B: Backend (NestJS) | Orden | Archivo | Cambio | Prioridad | |-------|---------|--------|-----------| | B.1 | `achievements.service.ts` | `claimRewards()` debe llamar SQL function | 🔴 CRÍTICO | | B.2 | `achievements.controller.ts` | Actualizar response con xp/coins granted | 🟡 IMPORTANTE | | B.3 | `admin-progress.service.ts` | Fix schema mismatch | 🟢 MENOR | ### 4.3 Fase C: Frontend (React) | Orden | Archivo | Cambio | Prioridad | |-------|---------|--------|-----------| | C.1 | `achievementsStore.ts` | Migrar de achievementsAPI a gamificationApi | 🟡 IMPORTANTE | | C.2 | `achievementsAPI.ts` | Deprecar métodos duplicados | 🟡 IMPORTANTE | | C.3 | `/hooks/useAchievements.ts` | Agregar @deprecated notice | 🟢 MENOR | --- ## 5. ARCHIVOS A MODIFICAR (ACTUALIZADO) ### 5.1 Base de Datos | Archivo | Acción | Líneas Afectadas | |---------|--------|------------------| | `check_and_award_achievements.sql` | Remover rewards distribution | 102-132 | | `triggers/fn_on_achievement_unlocked.sql` | Remover rewards, mantener notificación | 19-87 | ### 5.2 Backend | Archivo | Acción | Líneas Afectadas | |---------|--------|------------------| | `achievements.service.ts` | Llamar SQL function | 745-759 | | `achievements.controller.ts` | Update response type | TBD | | `admin-progress.service.ts` | Fix field names | TBD | ### 5.3 Frontend | Archivo | Acción | Líneas Afectadas | |---------|--------|------------------| | `achievementsStore.ts` | Change import | 16 | | `achievementsAPI.ts` | Add deprecation | Multiple | | `/hooks/useAchievements.ts` | Add @deprecated | 1-20 | --- ## 6. TESTS AFECTADOS | Test File | Cambio Requerido | |-----------|------------------| | `achievementsStore.test.ts` | Update mock imports | | `DashboardIntegration.test.tsx` | Update mock imports | | `AchievementsIntegration.test.tsx` | Update mock imports | --- ## 7. CHECKLIST DE VALIDACIÓN ### 7.1 Pre-requisitos Verificados - [x] Base de datos recreada exitosamente - [x] Función `claim_achievement_reward` corregida y desplegada - [x] Dependencias de archivos identificadas - [x] Triple distribución de rewards identificada ### 7.2 Plan Validado Contra Requisitos - [x] P-DUP-001: Backend no distribuye → Fix: Llamar SQL function - [x] P-DUP-002: SQL doble reward → Fix: Remover de check_and_grant + trigger - [x] P-DUP-003: Hook hardcoded → Fix: Deprecar - [x] P-DUP-004: APIs duplicadas → Fix: Consolidar en gamificationApi - [x] P-DUP-005: Transformers inconsistentes → Fix: Usar transformer externo - [x] P-DUP-006: Admin schema mismatch → Fix: Actualizar query ### 7.3 Impacto Evaluado - [x] Ningún archivo crítico sin backup plan - [x] Tests identificados para actualización - [x] Rollback plan definido --- ## 8. RECOMENDACIÓN **PROCEDER CON FASE 5 (Refinamiento) y FASE 6 (Ejecución)** El plan ha sido validado y las dependencias están claras. El hallazgo de triple distribución hace aún más urgente la corrección. **Orden de ejecución recomendado:** 1. **PRIMERO:** Corregir SQL (A.1 y A.2) - Detiene la triple distribución 2. **SEGUNDO:** Corregir Backend (B.1) - Habilita claim-to-earn 3. **TERCERO:** Corregir Frontend (C.1-C.3) - Cleanup y consistencia --- **Validado por:** Claude (Arquitecto Técnico) **Fecha:** 2026-01-10 **Estado:** FASE 4 COMPLETADA - Listo para FASE 5 (Refinamiento)