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
30 KiB
ANÁLISIS DETALLADO: PÁGINA DE ACHIEVEMENTS - STUDENT PORTAL
Fecha: 2026-01-10 Proyecto: Gamilit Componente: /achievements (Student Portal) Estado: EN ANÁLISIS
ÍNDICE
- Resumen Ejecutivo
- Arquitectura del Sistema
- Análisis Frontend
- Análisis Backend
- Análisis Base de Datos
- Análisis de Tipos e Interfaces
- Flujo de Datos Completo
- Problemas Identificados
- Dependencias y Relaciones
- Seeds e Integración
- Recomendaciones
1. RESUMEN EJECUTIVO
1.1 Descripción General
El sistema de Achievements es una funcionalidad de gamificación que permite a los estudiantes:
- Ver todos los logros disponibles en el sistema
- Rastrear su progreso hacia cada logro
- Reclamar recompensas (ML Coins, XP) al completar logros
- Filtrar y buscar logros por categoría, rareza y estado
1.2 Rutas y Archivos Principales
| Capa | Ruta Principal |
|---|---|
| Página Frontend | /home/isem/workspace-v1/projects/gamilit/apps/frontend/src/pages/AchievementsPage.tsx |
| Componentes Student | /home/isem/workspace-v1/projects/gamilit/apps/frontend/src/apps/student/components/achievements/ |
| Controller Backend | /home/isem/workspace-v1/projects/gamilit/apps/backend/src/modules/gamification/controllers/achievements.controller.ts |
| Service Backend | /home/isem/workspace-v1/projects/gamilit/apps/backend/src/modules/gamification/services/achievements.service.ts |
| DDL Achievements | /home/isem/workspace-v1/projects/gamilit/apps/database/ddl/schemas/gamification_system/tables/03-achievements.sql |
| DDL User Achievements | /home/isem/workspace-v1/projects/gamilit/apps/database/ddl/schemas/gamification_system/tables/04-user_achievements.sql |
| Seeds Dev | /home/isem/workspace-v1/projects/gamilit/apps/database/seeds/dev/gamification_system/ |
1.3 Endpoints API
| Método | Endpoint | Descripción |
|---|---|---|
| GET | /api/v1/gamification/achievements |
Obtener todos los achievements |
| GET | /api/v1/gamification/achievements/:id |
Obtener achievement específico |
| GET | /api/v1/gamification/users/:userId/achievements |
Obtener achievements del usuario |
| GET | /api/v1/gamification/users/:userId/achievements/summary |
Resumen estadístico |
| POST | /api/v1/gamification/users/:userId/achievements/:achievementId/claim |
Reclamar recompensas |
2. ARQUITECTURA DEL SISTEMA
2.1 Diagrama de Capas
┌─────────────────────────────────────────────────────────────────────────┐
│ FRONTEND (React + Vite) │
├─────────────────────────────────────────────────────────────────────────┤
│ pages/AchievementsPage.tsx │
│ ├── GamifiedHeader │
│ ├── AchievementFilter │
│ ├── AchievementCard (grid) │
│ └── AchievementModal │
├─────────────────────────────────────────────────────────────────────────┤
│ Hooks │ Store (Zustand) │
│ ├── useAuth │ └── achievementsStore.ts │
│ ├── useUserGamification │ ├── achievements[] │
│ └── useAchievementsEnhanced │ ├── stats │
│ │ └── actions │
├─────────────────────────────────────────────────────────────────────────┤
│ API Layer │
│ ├── achievementsAPI.ts (features/gamification) │
│ └── gamificationApi (shared services) │
└─────────────────────────────────────────────────────────────────────────┘
│
▼ HTTP
┌─────────────────────────────────────────────────────────────────────────┐
│ BACKEND (NestJS) │
├─────────────────────────────────────────────────────────────────────────┤
│ Controllers │
│ └── achievements.controller.ts │
├─────────────────────────────────────────────────────────────────────────┤
│ Services │
│ └── achievements.service.ts │
│ ├── findAll() │
│ ├── getAllUserAchievements() │
│ ├── grantAchievement() │
│ ├── claimRewards() │
│ └── meetsConditions() │
├─────────────────────────────────────────────────────────────────────────┤
│ Entities │
│ ├── achievement.entity.ts │
│ ├── user-achievement.entity.ts │
│ └── user-stats.entity.ts │
└─────────────────────────────────────────────────────────────────────────┘
│
▼ TypeORM
┌─────────────────────────────────────────────────────────────────────────┐
│ DATABASE (PostgreSQL) │
├─────────────────────────────────────────────────────────────────────────┤
│ Schema: gamification_system │
│ ├── achievements (tabla maestra) │
│ ├── user_achievements (progreso usuario) │
│ ├── achievement_categories (metadatos UI) │
│ └── user_stats (estadísticas gamificación) │
├─────────────────────────────────────────────────────────────────────────┤
│ Funciones SQL │
│ ├── check_and_award_achievements() │
│ └── claim_achievement_reward() │
├─────────────────────────────────────────────────────────────────────────┤
│ Triggers │
│ └── trg_achievement_unlocked (otorga XP/coins, crea notificación) │
└─────────────────────────────────────────────────────────────────────────┘
3. ANÁLISIS FRONTEND
3.1 AchievementsPage.tsx - Componente Principal
Ubicación: /apps/frontend/src/pages/AchievementsPage.tsx
Estados Gestionados
| Estado | Tipo | Propósito |
|---|---|---|
allAchievements |
Achievement[] |
Lista de todos los logros del sistema |
userAchievements |
UserAchievement[] |
Progreso del usuario en cada logro |
summary |
`AchievementSummary | null` |
isLoadingAchievements |
boolean |
Loading para logros del sistema |
isLoadingUserData |
boolean |
Loading para datos del usuario |
error |
`string | null` |
filter |
AchievementFilterType |
Filtros activos (categoría, estado, búsqueda, orden) |
selectedAchievement |
`Achievement | null` |
isModalOpen |
boolean |
Control de visibilidad del modal |
Hooks Utilizados
const { user, logout } = useAuth();
const { gamificationData } = useUserGamification(user?.id);
Llamadas a API
-
Carga inicial de achievements:
useEffect(() => { const data = await gamificationApi.getAllAchievements(); setAllAchievements(data); }, []); -
Carga de datos del usuario:
useEffect(() => { const [userAchData, summaryData] = await Promise.all([ gamificationApi.getUserAchievements(user.id), gamificationApi.getAchievementSummary(user.id).catch(() => null), ]); }, [user?.id]); -
Reclamar recompensas:
const handleClaimRewards = async (achievementId: string) => { const updatedAchievement = await gamificationApi.claimAchievement(user.id, achievementId); // Update optimista del estado local };
Lógica de Negocio (useMemo)
- Combinación de datos: Merge de
allAchievements+userAchievementsusando Map - Filtrado: Por categoría → estado → búsqueda (case-insensitive)
- Ordenamiento: Por nombre, progreso, fecha o rareza
- Separación: Achievements visibles vs. ocultos (isHidden && status === 'locked')
- Cálculo de Summary: Fallback local si API no devuelve summary
3.2 Componentes del Student Portal
| Componente | Archivo | Propósito |
|---|---|---|
AchievementsPageHeader |
AchievementsPageHeader.tsx |
Hero section con estadísticas visuales |
AchievementFilters |
AchievementFilters.tsx |
Controles de filtrado (categoría, rareza, estado, búsqueda) |
AchievementGrid |
AchievementGrid.tsx |
Grid responsivo de cards |
AchievementStatistics |
AchievementStatistics.tsx |
Panel de analytics y breakdown |
AchievementDetailModal |
AchievementDetailModal.tsx |
Modal de detalle con navegación |
AchievementCard |
features/gamification/social/components/ |
Card individual reutilizable |
3.3 Hook useAchievementsEnhanced
Ubicación: /apps/frontend/src/apps/student/hooks/useAchievementsEnhanced.ts
Proporciona:
- Filtrado avanzado con debounce (300ms)
- Ordenamiento múltiple
- Navegación entre achievements (prev/next)
- Persistencia de filtros en localStorage
- Cálculo de estadísticas detalladas
4. ANÁLISIS BACKEND
4.1 achievements.controller.ts
Ubicación: /apps/backend/src/modules/gamification/controllers/achievements.controller.ts
Endpoints Implementados
| Decorador | Ruta | Método Service |
|---|---|---|
@Get('achievements') |
/api/v1/gamification/achievements |
findAll(includeSecret) |
@Get('achievements/:id') |
/api/v1/gamification/achievements/:id |
findById(id) |
@Get('users/:userId/achievements') |
/api/v1/gamification/users/:userId/achievements |
getAllUserAchievements(userId) |
@Get('users/:userId/achievements/summary') |
/api/v1/gamification/users/:userId/achievements/summary |
getUserAchievementStats(userId) |
@Post('users/:userId/achievements/:achievementId') |
POST grant | grantAchievement(userId, dto) |
@Post('users/:userId/achievements/:achievementId/claim') |
POST claim | claimRewards(userId, achievementId) |
@Patch('achievements/:id') |
PATCH toggle | updateAchievementStatus(id, isActive) |
4.2 achievements.service.ts
Ubicación: /apps/backend/src/modules/gamification/services/achievements.service.ts
Métodos Principales
| Método | Descripción |
|---|---|
findAll(includeSecret) |
Obtiene achievements activos (opcionalmente secretos) |
findById(id) |
Obtiene achievement por ID con NotFoundException |
getAllUserAchievements(userId) |
Obtiene todos los achievements con progreso del usuario |
grantAchievement(userId, dto) |
Otorga/actualiza progreso de un achievement |
claimRewards(userId, achievementId) |
Reclama recompensas (valida completado y no reclamado) |
meetsConditions(userId, userStats, conditions) |
Evalúa si se cumplen condiciones de un achievement |
detectAndGrantEarned(userId) |
Detecta y otorga automáticamente achievements |
getUserAchievementStats(userId) |
Calcula estadísticas de achievements del usuario |
Tipos de Condiciones Soportadas (meetsConditions)
| Tipo | Evaluación |
|---|---|
exercise_completion |
userStats.exercises_completed >= requirements.exercises_completed |
streak |
userStats.current_streak >= requirements.consecutive_days |
module_completion |
Query a progress_tracking.module_progress |
all_modules_completion |
modules_completed >= X && average_score >= Y |
perfect_score |
userStats.perfect_scores >= requirements.perfect_exercises |
skill_mastery |
userStats.perfect_scores >= 10 |
exploration |
`modules_completed > 0 |
social |
Query a social_features.classroom_members/friendships |
special |
first_login check |
module_first_exercise |
Query por module_code |
exercise_score |
Query por exercise_type y min_score |
exercise_repetition |
Conteo de ejercicios con score mínimo |
exercise_speed |
Tiempo de completación |
content_analysis |
Análisis de contenido |
module_average_score |
Promedio por módulo |
5. ANÁLISIS BASE DE DATOS
5.1 Tabla: gamification_system.achievements
Ubicación DDL: /apps/database/ddl/schemas/gamification_system/tables/03-achievements.sql
Columnas Principales
| Columna | Tipo | Default | Descripción |
|---|---|---|---|
id |
UUID | gen_random_uuid() |
PK |
tenant_id |
UUID | NULL | Multi-tenant |
name |
TEXT | - | Nombre del achievement |
description |
TEXT | NULL | Descripción |
icon |
TEXT | 'trophy' |
Icono/emoji |
category |
ENUM | - | achievement_category |
rarity |
TEXT | 'common' |
common/rare/epic/legendary |
difficulty_level |
ENUM | 'beginner' |
Nivel de dificultad |
conditions |
JSONB | {type, requirements} |
Condiciones para desbloquear |
rewards |
JSONB | {xp, ml_coins, badge} |
Recompensas |
ml_coins_reward |
INTEGER | 0 | ML Coins (duplicado de rewards) |
is_secret |
BOOLEAN | false | Si está oculto |
is_active |
BOOLEAN | true | Si está activo |
is_repeatable |
BOOLEAN | false | Si es repetible |
order_index |
INTEGER | 0 | Orden en UI |
points_value |
INTEGER | 0 | XP (duplicado de rewards) |
Índices
idx_achievements_active- WHERE is_active = trueidx_achievements_category- Por categoríaidx_achievements_conditions_gin- GIN para JSONBidx_achievements_secret- WHERE is_secret = true
5.2 Tabla: gamification_system.user_achievements
Ubicación DDL: /apps/database/ddl/schemas/gamification_system/tables/04-user_achievements.sql
Columnas Principales
| Columna | Tipo | Default | Descripción |
|---|---|---|---|
id |
UUID | gen_random_uuid() |
PK |
user_id |
UUID | - | FK a profiles |
achievement_id |
UUID | - | FK a achievements |
progress |
INTEGER | 0 | Progreso actual |
max_progress |
INTEGER | 100 | Progreso máximo |
is_completed |
BOOLEAN | false | Si está completado |
completion_percentage |
NUMERIC(5,2) | 0.00 | Porcentaje (0-100) |
completed_at |
TIMESTAMPTZ | NULL | Fecha de completación |
notified |
BOOLEAN | false | Si se notificó |
viewed |
BOOLEAN | false | Si se vio la notificación |
rewards_claimed |
BOOLEAN | false | Si reclamó recompensas |
rewards_received |
JSONB | {} |
Detalle de recompensas |
progress_data |
JSONB | {} |
Datos de progreso |
milestones_reached |
TEXT[] | NULL | Hitos alcanzados |
Constraints
UNIQUE (user_id, achievement_id)- Un usuario no puede duplicar logroFK user_id → auth_management.profiles(id) ON DELETE CASCADEFK achievement_id → gamification_system.achievements(id) ON DELETE CASCADE
5.3 ENUM: achievement_category
Valores: progress, streak, completion, social, special, mastery, exploration, collection, hidden
5.4 Trigger: trg_achievement_unlocked
Evento: AFTER INSERT OR UPDATE en user_achievements
Acciones:
- Verifica si
is_completed = true - Otorga XP a
user_stats.total_xp - Otorga ML Coins con row lock
- Crea notificación en
notifications.notifications - Marca
notified = true
6. ANÁLISIS DE TIPOS E INTERFACES
6.1 Tipos Canónicos (SSOT)
Ubicación: /apps/frontend/src/shared/types/achievement.types.ts
type AchievementCategory = 'progress' | 'streak' | 'completion' | 'social' |
'special' | 'mastery' | 'exploration' | 'collection' | 'hidden'
type AchievementStatus = 'locked' | 'in_progress' | 'earned' | 'claimed'
enum AchievementType {
BADGE = 'badge',
MILESTONE = 'milestone',
SPECIAL = 'special',
RANK_PROMOTION = 'rank_promotion',
}
interface Achievement {
id: string;
name: string;
description: string;
icon: string;
category: AchievementCategory;
type: AchievementType;
conditions: AchievementConditionsType;
rewards: AchievementReward;
isHidden: boolean;
rarity?: 'common' | 'rare' | 'epic' | 'legendary';
// ... más campos
}
interface UserAchievement {
id: string;
userId: string;
achievementId: string;
progress: number;
earnedAt?: string;
claimedAt?: string;
achievement: Achievement;
status: AchievementStatus;
}
6.2 Mapeo Backend → Frontend
| Backend (snake_case) | Frontend (camelCase) | Transformación |
|---|---|---|
name |
title |
Mapeo directo |
ml_coins_reward |
mlCoinsReward |
rewards?.ml_coins ?? ml_coins_reward |
points_value |
xpReward |
rewards?.xp ?? points_value |
is_secret |
isHidden |
Mapeo + categoría |
is_completed |
isUnlocked |
Mapeo directo |
completed_at |
unlockedAt |
Parse a Date |
completion_percentage |
Parseado | parseFloat() - ¡Backend devuelve string! |
7. FLUJO DE DATOS COMPLETO
Usuario abre /achievements
│
▼
┌────────────────────────────────────────────┐
│ AchievementsPage.tsx - useEffect (mount) │
│ ├── gamificationApi.getAllAchievements() │
│ └── gamificationApi.getUserAchievements() │
│ gamificationApi.getAchievementSummary()│
└────────────────────────────────────────────┘
│
▼ HTTP GET
┌────────────────────────────────────────────┐
│ achievements.controller.ts │
│ ├── @Get('achievements') │
│ └── @Get('users/:userId/achievements') │
└────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ achievements.service.ts │
│ ├── findAll() - QueryBuilder │
│ └── getAllUserAchievements() - Repository │
└────────────────────────────────────────────┘
│
▼ TypeORM
┌────────────────────────────────────────────┐
│ PostgreSQL │
│ ├── gamification_system.achievements │
│ └── gamification_system.user_achievements │
└────────────────────────────────────────────┘
│
▼ Response
┌────────────────────────────────────────────┐
│ Frontend - Transformación │
│ ├── mapToFrontendAchievement() │
│ └── useMemo combinedAchievements │
└────────────────────────────────────────────┘
│
▼ Render
┌────────────────────────────────────────────┐
│ UI Components │
│ ├── AchievementCard (grid) │
│ ├── AchievementModal (detalle) │
│ └── AchievementStatistics (analytics) │
└────────────────────────────────────────────┘
8. PROBLEMAS IDENTIFICADOS
8.1 CRÍTICOS 🔴
| ID | Problema | Ubicación | Impacto |
|---|---|---|---|
| P1 | Función claim_achievement_reward() usa columnas inexistentes (reward_claimed_at) |
DDL functions | Función SQL falla al ejecutarse |
| P2 | Store usa || en lugar de ?? para recompensas (0 es falsy) |
achievementsStore.ts:172 | Recompensas de 0 podrían fallar |
| P3 | Backend completion_percentage es STRING, no se parsea en Store |
achievementsStore | Tipo incorrecto en runtime |
8.2 IMPORTANTES 🟡
| ID | Problema | Ubicación | Impacto |
|---|---|---|---|
| P4 | Duplicación de ml_coins_reward (columna y JSONB rewards) |
DDL + Backend | Inconsistencia potencial |
| P5 | Duplicación de points_value (columna) vs rewards.xp |
DDL + Backend | Inconsistencia potencial |
| P6 | Alias conflictivo Achievement en achievementsTypes.ts |
Types | Confusión de tipos |
| P7 | unlockedAt es string vs Date inconsistente |
Múltiples archivos | Bugs de tipo |
| P8 | Category mapping incompleto (falta 'streak', 'exploration') | achievementsAPI.ts | Categorías mal mapeadas |
| P9 | ENUM vs Tabla para categorías (2 valores no en tabla) | DDL | Integridad referencial |
8.3 MENORES 🟢
| ID | Problema | Ubicación | Impacto |
|---|---|---|---|
| P10 | rarity es TEXT no ENUM |
DDL achievements | Podría tener valores inválidos |
| P11 | Múltiples timestamps (earnedAt, claimedAt, unlockedAt) | Types | Documentación faltante |
9. DEPENDENCIAS Y RELACIONES
9.1 Dependencias de Tablas
gamification_system.achievements
├── FK created_by → auth_management.profiles(id)
└── FK tenant_id → auth_management.tenants(id)
gamification_system.user_achievements
├── FK user_id → auth_management.profiles(id)
└── FK achievement_id → gamification_system.achievements(id)
gamification_system.user_stats
└── FK user_id → auth_management.profiles(id)
9.2 Dependencias de Servicios (Backend)
El AchievementsService realiza queries cruzadas a:
progress_tracking.module_progressprogress_tracking.exercise_submissionseducational_content.moduleseducational_content.exercisessocial_features.classroom_memberssocial_features.friendships
9.3 Dependencias Frontend
AchievementsPage
├── useAuth (auth context)
├── useUserGamification (React Query)
├── gamificationApi (axios client)
├── GamifiedHeader (shared component)
├── AchievementFilter (student component)
├── AchievementCard (feature component)
└── AchievementModal (shared component)
10. SEEDS E INTEGRACIÓN
10.1 Seeds de Achievement Categories
Archivo: /apps/database/seeds/dev/gamification_system/01-achievement_categories.sql
| Nombre | Icono | Orden |
|---|---|---|
| Progreso | 🎯 | 1 |
| Racha | 🔥 | 2 |
| Completación | ✅ | 3 |
| Maestría | 👑 | 4 |
| Exploración | 🔍 | 5 |
| Social | 👥 | 6 |
| Especial | ⭐ | 7 |
10.2 Seeds de Achievements
Archivo: /apps/database/seeds/dev/gamification_system/04-achievements.sql
Total: 20 achievements de demostración
| Categoría | Cantidad | Ejemplo |
|---|---|---|
| Progress | 5 | "Primeros Pasos" (1 ejercicio) → "Maestro de Lectura" (200 ejercicios) |
| Streak | 3 | "Racha 3 Días" → "Racha 30 Días" |
| Completion | 4 | "Módulo 1 Completado" → "Completista Total" |
| Mastery | 3 | "Perfeccionista" (10 ejercicios 100%) |
| Exploration | 2 | "Explorador Curioso" |
| Social | 2 | "Compañero de Aula" |
| Special | 1 | "Primera Visita" |
10.3 Seeds de User Achievements
Archivo: /apps/database/seeds/dev/gamification_system/08-user_achievements.sql
Usuarios de Demo: 7 usuarios con achievements pre-asignados para testing
11. RECOMENDACIONES
11.1 Correcciones Críticas (Inmediato)
-
Reparar función SQL
claim_achievement_reward():- Cambiar
reward_claimed_atporrewards_claimed(boolean) - Usar
completed_atpara timestamp
- Cambiar
-
Corregir Store con nullish coalescing:
// ANTES mlCoinsReward: ach.rewards?.ml_coins || ach.ml_coins_reward || 0, // DESPUÉS mlCoinsReward: ach.rewards?.ml_coins ?? ach.ml_coins_reward ?? 0, -
Parsear completion_percentage en Store:
completionPercentage: typeof ach.completion_percentage === 'string' ? parseFloat(ach.completion_percentage) : ach.completion_percentage,
11.2 Mejoras de Consistencia (Corto Plazo)
-
Unificar fuente de recompensas:
- Definir
rewardsJSONB como SSOT - Deprecar columnas
ml_coins_rewardypoints_value
- Definir
-
Estandarizar timestamps:
- Definir
unlockedAtcomo campo canónico - Siempre como ISO string en API responses
- Definir
-
Completar mapeo de categorías:
const categoryMap = { 'streak': 'streak', 'exploration': 'exploration', 'collection': 'collection', // ... completar };
11.3 Mejoras Estructurales (Mediano Plazo)
- Convertir
raritya ENUM - Sincronizar ENUM achievement_category con tabla achievement_categories
- Agregar índices para queries comunes del frontend
- Documentar flujo de datos end-to-end
APÉNDICE A: ARCHIVOS ANALIZADOS
Frontend
/apps/frontend/src/pages/AchievementsPage.tsx/apps/frontend/src/apps/student/components/achievements/*.tsx/apps/frontend/src/apps/student/hooks/useAchievementsEnhanced.ts/apps/frontend/src/features/gamification/social/api/achievementsAPI.ts/apps/frontend/src/features/gamification/social/store/achievementsStore.ts/apps/frontend/src/shared/types/achievement.types.ts
Backend
/apps/backend/src/modules/gamification/controllers/achievements.controller.ts/apps/backend/src/modules/gamification/services/achievements.service.ts/apps/backend/src/modules/gamification/entities/achievement.entity.ts/apps/backend/src/modules/gamification/entities/user-achievement.entity.ts/apps/backend/src/modules/gamification/dto/achievements/*.ts
Database
/apps/database/ddl/schemas/gamification_system/tables/03-achievements.sql/apps/database/ddl/schemas/gamification_system/tables/04-user_achievements.sql/apps/database/ddl/schemas/gamification_system/tables/10-achievement_categories.sql/apps/database/ddl/schemas/gamification_system/enums/achievement_category.sql/apps/database/ddl/schemas/gamification_system/functions/check_and_award_achievements.sql/apps/database/ddl/schemas/gamification_system/functions/claim_achievement_reward.sql/apps/database/ddl/schemas/gamification_system/triggers/01-trg_achievement_unlocked.sql/apps/database/seeds/dev/gamification_system/*.sql
Documento generado: 2026-01-10 Analista: Claude (Arquitecto Técnico) Siguiente Fase: Planeación basada en análisis detallado