# RF-GAM-004: Economía de ML Coins (Maya Learning Coins)

## 📋 Metadata

| Campo | Valor |
|-------|-------|
| **ID** | RF-GAM-004 |
| **Módulo** | 02 - Gamificación |
| **Título** | Economía de ML Coins (Maya Learning Coins) |
| **Prioridad** | Alta |
| **Estado** | ✅ Implementado |
| **Versión** | 2.1 (DB-099: tenant_id support) |
| **Fecha Creación** | 2025-11-08 |
| **Última Actualización** | 2025-11-11 (DB-099) |
| **Autor** | Database Team |
| **Stakeholders** | Product Owner, UX Team, Backend Team, Frontend Team, Game Designer |

---

## 🔗 Referencias

### Implementación DDL

🗄️ **Tablas Relacionadas:**

1. **`gamification_system.user_stats`**
   - **Ubicación:** `apps/database/ddl/schemas/gamification_system/tables/user_stats.sql`
   - **Propósito:** Almacena balance actual de ML Coins y totales históricos
   - **Columnas clave:**
     - `ml_coins` (INTEGER): Balance actual de ML Coins
     - `ml_coins_earned_total` (INTEGER): Total histórico ganado
     - `ml_coins_spent_total` (INTEGER): Total histórico gastado

2. **`gamification_system.ml_coins_transactions`**
   - **Ubicación:** `apps/database/ddl/schemas/gamification_system/tables/05-ml_coins_transactions.sql`
   - **Propósito:** Registro completo de todas las transacciones de ML Coins
   - **Columnas clave:**
     - `id` (UUID): ID único de transacción
     - `user_id` (UUID): Usuario que realiza la transacción
     - `tenant_id` (UUID): ✨ **NUEVO DB-099** - ID del tenant (multi-tenancy support)
     - `amount` (INTEGER): Monto de la transacción (con multiplicador aplicado)
     - `balance_before` (INTEGER): Balance antes de la transacción
     - `balance_after` (INTEGER): Balance después de la transacción
     - `transaction_type` (ENUM): Tipo de transacción (14 tipos)
     - `multiplier` (NUMERIC): Multiplicador aplicado (ej: 1.25x por rango)
     - `metadata` (JSONB): Información adicional (base_amount, rank, etc.)
     - `created_at` (TIMESTAMPTZ): Timestamp de la transacción

🗄️ **ENUM Canónico:**
- **Ubicación:** `apps/database/ddl/schemas/gamification_system/enums/transaction_type.sql`
- **Tipo:** `gamification_system.transaction_type`
- **Valores:** 14 tipos (7 earned, 3 spent, 4 admin)

🗄️ **Funciones SQL:**

1. **`award_ml_coins(user_id, amount, transaction_type, description, reference_id, reference_type)`**
   - **Ubicación:** `apps/database/ddl/schemas/gamification_system/functions/award_ml_coins.sql`
   - **Propósito:** Otorgar ML Coins al usuario aplicando multiplicador de rango
   - **Validaciones:**
     - Obtiene rango actual del usuario
     - Aplica multiplicador según rango Maya (1.00x - 2.00x)
     - Actualiza balance con `FOR UPDATE` (previene race conditions)
     - Registra transacción con metadata completa

### Especificación Técnica

📘 **Documento ET Relacionado:**
- [ET-GAM-004: Tipos Compartidos de Gamificación](../../especificaciones/ET-GAM-004-tipos-compartidos-gamificacion.md)
- [ET-GAM-003: Rangos Maya](../../especificaciones/ET-GAM-003-rangos-maya.md) - Multiplicadores de rango
- [ET-GAM-002: Sistema de Comodines](../../especificaciones/ET-GAM-002-comodines.md) - Gastos de ML Coins

### Documentos Relacionados

- [RF-GAM-002: Sistema de Comodines](./RF-GAM-002-comodines.md) - Principal uso de ML Coins
- [RF-GAM-003: Rangos Maya](./RF-GAM-003-rangos-maya.md) - Multiplicadores por rango
- [RF-GAM-001: Sistema de Achievements](./RF-GAM-001-achievements.md) - Fuente de ML Coins

---

## 📖 Descripción General

### Propósito

El sistema de **ML Coins (Maya Learning Coins)** es la moneda virtual principal de la plataforma Gamilit. Proporciona:

- **Motivación económica**: Los estudiantes ganan coins por actividades de aprendizaje
- **Sistema de recompensas**: Progresión tangible y medible
- **Economía de recursos escasos**: Decisiones estratégicas sobre cómo gastar coins
- **Gamificación profunda**: Feedback inmediato por logros

### Contexto

Los ML Coins son el núcleo del sistema de gamificación de Gamilit:

1. **Se ganan** completando ejercicios, módulos, achievements, rachas, etc.
2. **Se multiplican** según el rango Maya del usuario (1.00x - 2.00x)
3. **Se gastan** en comodines (power-ups), pistas, reintentos
4. **Se rastrean** con historial completo de transacciones

---

## 🎯 Objetivos del Sistema

### Objetivos Primarios

1. **Incentivar el aprendizaje activo**
   - Recompensar inmediatamente actividades educativas
   - Crear ciclo de feedback positivo
   - Motivar a completar contenido

2. **Promover progresión y maestría**
   - Mayores recompensas por contenido difícil
   - Multiplicadores por rango premian veteranos
   - Balance entre nuevos y experimentados

3. **Habilitar toma de decisiones estratégicas**
   - Recursos escasos requieren planificación
   - Decisión: ¿guardar o gastar?
   - Enseña administración de recursos

### Objetivos Secundarios

1. **Crear economía sostenible**
   - Balance entre earning y spending
   - Prevenir inflación de coins
   - Evitar acumulación excesiva

2. **Facilitar análisis y métricas**
   - Trackear engagement por tipo de actividad
   - Identificar usuarios en riesgo
   - Optimizar recompensas basado en datos

---

## 📊 Flujos de ML Coins

### 1. Earning (Ganancia de Coins)

#### 1.1 Por Actividad Educativa

**Ejercicios Completados** (`earned_exercise`)
- **Monto base:** 5-50 ML Coins (según dificultad)
- **Multiplicador:** Según rango Maya (1.00x - 2.00x)
- **Trigger:** Al completar ejercicio exitosamente
- **Ejemplo:**
  - Estudiante Ajaw (1.00x) completa ejercicio medio (20 coins)
  - Recibe: 20 * 1.00 = **20 ML Coins**
  - Estudiante K'uk'ulkan (2.00x) completa mismo ejercicio
  - Recibe: 20 * 2.00 = **40 ML Coins**

**Módulos Completados** (`earned_module`)
- **Monto base:** 100-300 ML Coins (según módulo)
- **Multiplicador:** Según rango Maya
- **Trigger:** Al completar 100% de ejercicios del módulo
- **Ejemplo:**
  - Módulo "Comprensión Literal" = 150 coins base
  - Nacom (1.25x): 150 * 1.25 = **188 ML Coins**

**Achievements Desbloqueados** (`earned_achievement`)
- **Monto base:** 50-500 ML Coins (según rareza)
  - Común: 50 coins
  - Raro: 100 coins
  - Épico: 250 coins
  - Legendario: 500 coins
- **Multiplicador:** Según rango Maya
- **Trigger:** Al cumplir condiciones del achievement

#### 1.2 Por Progresión y Engagement

**Subida de Rango** (`earned_rank`)
- **Monto:** 100-1000 ML Coins (según rango alcanzado) ✅ IMPLEMENTADO
  - Ajaw → Nacom: 100 coins (al alcanzar 500 XP)
  - Nacom → Ah K'in: 250 coins (al alcanzar 1,000 XP)
  - Ah K'in → Halach Uinic: 500 coins (al alcanzar 1,500 XP)
  - Halach Uinic → K'uk'ulkan: 1,000 coins (al alcanzar 2,250 XP)
- **Multiplicador:** NO aplica (recompensa fija)
- **Trigger:** Al alcanzar XP requerido para nuevo rango

**Racha de Días** (`earned_streak`)
- **Monto:** 10-100 ML Coins (según días consecutivos)
  - 3 días: 10 coins
  - 7 días: 25 coins
  - 14 días: 50 coins
  - 30 días: 100 coins
- **Multiplicador:** Según rango Maya
- **Trigger:** Al mantener racha activa

**Login Diario** (`earned_daily`)
- **Monto:** 50 ML Coins
- **Multiplicador:** Según rango Maya
- **Trigger:** Primer login del día
- **Límite:** 1 vez por día

**Bonus Especial** (`earned_bonus`)
- **Monto:** Variable (definido por evento)
- **Multiplicador:** Según rango Maya
- **Trigger:** Eventos especiales, promociones, desafíos
- **Ejemplo:** "Semana de la Lectura" +200 coins por completar módulo

---

### 2. Spending (Gasto de Coins)

#### 2.1 Comodines (Power-ups)

**Pistas Contextuales** (`spent_powerup` - pistas)
- **Costo:** -15 ML Coins
- **Beneficio:** Muestra 2-3 pistas sobre respuesta correcta
- **Límite:** 3 por ejercicio
- **Uso estratégico:** Para ejercicios difíciles sin perder intento

**Visión Lectora** (`spent_powerup` - vision_lectora)
- **Costo:** -25 ML Coins
- **Beneficio:** Resalta pasajes clave del texto
- **Límite:** 1 por ejercicio
- **Uso estratégico:** Para textos largos y complejos

**Segunda Oportunidad** (`spent_powerup` - segunda_oportunidad)
- **Costo:** -40 ML Coins
- **Beneficio:** Permite reintento sin penalización de XP
- **Límite:** 1 por ejercicio
- **Uso estratégico:** Para ejercicios críticos

#### 2.2 Ayudas Adicionales

**Pista Simple** (`spent_hint`)
- **Costo:** -10 ML Coins
- **Beneficio:** Pista contextual individual
- **Límite:** Ilimitado (costoso)

**Reintento de Ejercicio** (`spent_retry`)
- **Costo:** -20 ML Coins
- **Beneficio:** Reiniciar ejercicio fallado
- **Límite:** Ilimitado

---

### 3. Administrativo y Sistema

**Ajuste Manual** (`admin_adjustment`)
- **Monto:** Variable (+ o -)
- **Propósito:** Correcciones, compensaciones, regalos
- **Autorización:** Solo administradores
- **Ejemplo:** Compensar bug que afectó a usuarios

**Reembolso** (`refund`)
- **Monto:** Positivo (devolución)
- **Propósito:** Devolver coins por compra errónea o bug
- **Trigger:** Solicitud de usuario o detección automática

**Bonus General** (`bonus`)
- **Monto:** Positivo
- **Propósito:** Bonos del sistema no categorizados
- **Ejemplo:** Recompensa por participar en beta testing

**Bonus de Bienvenida** (`welcome_bonus`)
- **Monto:** +100 ML Coins
- **Propósito:** Dar capital inicial a nuevos usuarios
- **Trigger:** Registro de nueva cuenta (una sola vez)

---

## 🔢 Economía y Balance

### Multiplicadores por Rango Maya

⚠️ **NOTA IMPORTANTE (2025-11-19):** Los multiplicadores ML Coins descritos aquí están **PENDIENTES DE IMPLEMENTACIÓN**.

| Rango | Nivel | Multiplicador ML Coins (Documentado) | Multiplicador XP (Implementado) | Estado |
|-------|-------|--------------------------------------|--------------------------------|--------|
| **Ajaw** | 1 | 1.00x | 1.00x | ✅ XP: Implementado |
| **Nacom** | 2 | 1.25x (+25%) | 1.10x (+10%) | ❌ ML: No implementado |
| **Ah K'in** | 3 | 1.50x (+50%) | 1.15x (+15%) | ❌ ML: No implementado |
| **Halach Uinic** | 4 | 1.75x (+75%) | 1.20x (+20%) | ❌ ML: No implementado |
| **K'uk'ulkan** | 5 | 2.00x (+100%) | 1.25x (+25%) | ❌ ML: No implementado |

**Estado Actual:**
- ✅ **Multiplicadores XP:** Implementados y funcionales (1.00x - 1.25x)
- ❌ **Multiplicadores ML Coins:** Documentados pero NO implementados en DB v2.0
- ✅ **Bonus ML Coins (único por promoción):** Implementados (100-1000 ML)

**Funcionalidad NO Implementada:**
```sql
-- ❌ Esta columna NO existe en la tabla maya_ranks:
ml_coins_multiplier NUMERIC(3,2)

-- ✅ Lo que SÍ existe:
ml_coins_bonus INTEGER  -- Bonus único al promover
xp_multiplier NUMERIC(3,2)  -- Multiplicador XP
```

**Decisión Pendiente:** Product Owner debe decidir si implementar multiplicadores ML Coins o simplificar economía manteniendo solo bonus únicos.

**Ver:**
- [ET-GAM-003: Rangos Maya](../../especificaciones/ET-GAM-003-rangos-maya.md) para multiplicadores XP implementados
- [docs/04-fase-backlog/FUNCIONALIDADES-GAMIFICACION-PENDIENTES.md](../../../../04-fase-backlog/FUNCIONALIDADES-GAMIFICACION-PENDIENTES.md) para análisis detallado

### Earning vs Spending Estimado

**Earning Típico (Usuario Activo - Ajaw 1.00x):**
- 10 ejercicios/día: 10 * 20 = 200 coins
- 1 módulo/semana: 150 coins
- 1 achievement/semana: 100 coins
- Login diario: 50 coins
- **Total semanal:** ~1,300 ML Coins

**Spending Típico:**
- 3 pistas/semana: 3 * 15 = 45 coins
- 1 visión lectora/semana: 25 coins
- 1 segunda oportunidad/semana: 40 coins
- **Total semanal:** ~110 ML Coins

**Balance:** +1,190 ML Coins/semana (positivo, permite acumulación)

**Objetivo:** Usuarios deben poder acumular coins pero sentir que son valiosos (no triviales).

---

## 📐 Reglas de Negocio

### Regla 1: No Negativos

**Descripción:** El balance de ML Coins de un usuario **nunca** puede ser negativo.

**Implementación:**
- CHECK constraint en tabla `user_stats`: `ml_coins >= 0`
- Validación en función `spend_ml_coins()` antes de restar
- Frontend previene compra si balance insuficiente

**Ejemplo:**
```
Usuario tiene: 25 ML Coins
Quiere comprar: Segunda Oportunidad (40 coins)
Resultado: ❌ Transacción rechazada "Balance insuficiente"
```

### Regla 2: Multiplicador se Aplica Solo a Earning

**Descripción:** El multiplicador de rango Maya se aplica solo a coins ganados, **no** a gastos.

**Implementación:**
- Función `award_ml_coins()` aplica multiplicador
- Función `spend_ml_coins()` usa monto exacto (sin multiplicador)

**Ejemplo:**
```
K'uk'ulkan (2.00x) gana 100 coins → Recibe 200 coins
K'uk'ulkan gasta en pista (15 coins) → Paga exactamente 15 coins
```

### Regla 3: Transacciones Atómicas

**Descripción:** Cada transacción de ML Coins debe ser atómica (todo o nada).

**Implementación:**
- Uso de `FOR UPDATE` para bloquear fila durante transacción
- Rollback automático si falla cualquier paso
- Registro de transacción solo si update exitoso

### Regla 4: Auditoría Completa

**Descripción:** Todas las transacciones deben quedar registradas permanentemente.

**Implementación:**
- Tabla `ml_coins_transactions` sin DELETE
- Metadata JSONB con detalles (base_amount, rank, multiplier)
- Columnas `balance_before` y `balance_after` para auditoría

### Regla 5: Redondeo hacia Abajo

**Descripción:** Montos con decimales se redondean hacia abajo (FLOOR).

**Implementación:**
```sql
v_final_amount := FLOOR(p_amount * v_multiplier);
```

**Ejemplo:**
```
Base: 33 coins
Multiplicador Nacom: 1.25x
Cálculo: 33 * 1.25 = 41.25
Resultado: FLOOR(41.25) = 41 coins
```

---

## 🎮 Casos de Uso

### Caso de Uso 1: Estudiante Completa Ejercicio

**Actor:** Estudiante (usuario autenticado)

**Precondiciones:**
- Usuario tiene cuenta activa
- Usuario tiene rango Maya asignado
- Ejercicio disponible y no completado previamente

**Flujo Principal:**
1. Usuario resuelve ejercicio correctamente
2. Sistema obtiene rango Maya del usuario
3. Sistema calcula monto base según dificultad del ejercicio
4. Sistema aplica multiplicador de rango
5. Sistema llama `award_ml_coins()`
6. Se actualiza balance en `user_stats`
7. Se registra transacción en `ml_coins_transactions`
8. Frontend muestra notificación: "+20 ML Coins 🪙"

**Postcondiciones:**
- Balance de ML Coins incrementado
- Transacción registrada con tipo `earned_exercise`
- Totales históricos actualizados

### Caso de Uso 2: Estudiante Compra Comodín

**Actor:** Estudiante

**Precondiciones:**
- Usuario tiene balance suficiente de ML Coins
- Comodín disponible para compra

**Flujo Principal:**
1. Usuario hace clic en "Comprar Pistas (15 coins)"
2. Frontend verifica balance >= 15
3. Sistema llama `purchase_comodin(user_id, 'pistas', quantity)`
4. Función SQL:
   - Verifica balance con `FOR UPDATE`
   - Resta 15 ML Coins del balance
   - Incrementa inventario de comodines
   - Registra transacción tipo `spent_powerup`
5. Frontend actualiza UI con nuevo balance e inventario

**Flujo Alternativo:** Balance insuficiente
1. Frontend muestra error: "ML Coins insuficientes. Necesitas 15, tienes 10"
2. Sugerencia: "Completa más ejercicios para ganar ML Coins"

### Caso de Uso 3: Usuario Sube de Rango

**Actor:** Sistema (automático)

**Precondiciones:**
- Usuario alcanzó XP requerido para nuevo rango

**Flujo Principal:**
1. Función `check_rank_promotion()` detecta promoción
2. Sistema actualiza `user_ranks` con nuevo rango
3. Sistema otorga bonus de rango:
   ```sql
   award_ml_coins(user_id, 250, 'earned_rank', 'Promoción a Ah K''in')
   ```
4. Se registra transacción (sin multiplicador - monto fijo)
5. Frontend muestra celebración: "¡Felicidades! +250 ML Coins por alcanzar Ah K'in"

---

## 📊 Métricas y KPIs

### Métricas de Usuario

1. **Balance Actual**
   - Columna: `user_stats.ml_coins`
   - Propósito: Mostrar en UI, validar compras

2. **Total Ganado Histórico**
   - Columna: `user_stats.ml_coins_earned_total`
   - Propósito: Leaderboards, achievements

3. **Total Gastado Histórico**
   - Columna: `user_stats.ml_coins_spent_total`
   - Propósito: Análisis de engagement, patrones de gasto

### Métricas del Sistema

1. **ML Coins en Circulación**
   ```sql
   SELECT SUM(ml_coins) FROM gamification_system.user_stats;
   ```
   - Propósito: Monitorear inflación, salud económica

2. **Earning por Tipo de Transacción**
   ```sql
   SELECT transaction_type, SUM(amount)
   FROM ml_coins_transactions
   WHERE transaction_type LIKE 'earned_%'
   GROUP BY transaction_type;
   ```
   - Propósito: Identificar fuentes principales de coins

3. **Spending por Tipo**
   ```sql
   SELECT transaction_type, SUM(ABS(amount))
   FROM ml_coins_transactions
   WHERE transaction_type LIKE 'spent_%'
   GROUP BY transaction_type;
   ```
   - Propósito: Entender cómo usuarios gastan coins

4. **Ratio Earning/Spending**
   ```sql
   SELECT
     SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) as total_earned,
     SUM(CASE WHEN amount < 0 THEN ABS(amount) ELSE 0 END) as total_spent,
     (SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END)::FLOAT /
      NULLIF(SUM(CASE WHEN amount < 0 THEN ABS(amount) ELSE 0 END), 0)) as ratio
   FROM ml_coins_transactions;
   ```
   - **Target:** Ratio ~5-10x (usuarios ganan mucho más de lo que gastan)
   - **Alert:** Si ratio < 3x → usuarios gastando demasiado
   - **Alert:** Si ratio > 20x → coins no tienen valor percibido

---

## 🔒 Seguridad y Prevención de Fraude

### 1. Race Conditions

**Problema:** Dos transacciones simultáneas pueden causar balance incorrecto.

**Solución:** Row-level locking con `FOR UPDATE`
```sql
SELECT ml_coins INTO v_current_balance
FROM gamification_system.user_stats
WHERE user_id = p_user_id
FOR UPDATE;
```

### 2. Balance Negativo

**Problema:** Bugs o exploits podrían permitir balance negativo.

**Solución:**
- CHECK constraint: `ml_coins >= 0`
- Validación en aplicación antes de gastar
- Transacción atómica (rollback si falla)

### 3. Duplicación de Recompensas

**Problema:** Usuario podría reclamar misma recompensa múltiples veces.

**Solución:**
- Idempotency keys en `reference_id`
- Validación de ejercicio ya completado
- Achievement solo se otorga una vez (validación en trigger)

### 4. Admin Abuse

**Problema:** Admin malintencionado otorga coins ilimitados.

**Solución:**
- Audit logging en `ml_coins_transactions`
- Alertas automáticas para transacciones admin > 1000 coins
- Revisión periódica de transacciones tipo `admin_adjustment`

---

## 🧪 Casos de Prueba

### Test 1: Award con Multiplicador Ajaw (1.00x)

**Input:**
```sql
award_ml_coins(
  user_id = 'test-user-1',
  amount = 100,
  transaction_type = 'earned_exercise',
  description = 'Test'
);
```

**Condiciones:**
- Usuario tiene rango Ajaw (1.00x)
- Balance inicial: 0

**Output Esperado:**
- Balance final: 100 ML Coins
- `ml_coins_earned_total`: 100
- Transacción registrada con `amount = 100`, `multiplier = 1.00`

### Test 2: Award con Multiplicador K'uk'ulkan (2.00x)

**Input:**
```sql
award_ml_coins(
  user_id = 'test-user-2',
  amount = 100,
  transaction_type = 'earned_module',
  description = 'Test'
);
```

**Condiciones:**
- Usuario tiene rango K'uk'ulkan (2.00x)
- Balance inicial: 50

**Output Esperado:**
- Balance final: 50 + 200 = 250 ML Coins
- `ml_coins_earned_total`: 200
- Transacción con `amount = 200`, `multiplier = 2.00`
- Metadata JSONB: `{ "base_amount": 100, "rank": "K'uk'ulkan", "multiplier": 2.00, "final_amount": 200 }`

### Test 3: Spend - Balance Suficiente

**Input:**
```sql
spend_ml_coins(
  user_id = 'test-user-3',
  amount = 15,
  transaction_type = 'spent_hint',
  description = 'Compra de pista'
);
```

**Condiciones:**
- Balance inicial: 100

**Output Esperado:**
- Balance final: 85 ML Coins
- `ml_coins_spent_total`: 15
- Transacción con `amount = -15` (negativo)

### Test 4: Spend - Balance Insuficiente

**Input:**
```sql
spend_ml_coins(
  user_id = 'test-user-4',
  amount = 50,
  transaction_type = 'spent_powerup',
  description = 'Compra de comodín'
);
```

**Condiciones:**
- Balance inicial: 20

**Output Esperado:**
- Error: "Insufficient ML Coins balance"
- Balance sin cambios: 20
- No se crea transacción

---

## 📚 Referencias Técnicas

### Base de Datos

- **Tabla principal:** `gamification_system.user_stats`
- **Tabla de transacciones:** `gamification_system.ml_coins_transactions`
- **ENUM:** `gamification_system.transaction_type`
- **Función de award:** `gamification_system.award_ml_coins()`
- **Tests:** `apps/database/ddl/schemas/gamification_system/functions/tests/test_award_ml_coins.sql`

### Backend (NestJS)

- **Service:** `apps/backend/src/modules/gamification/services/ml-coins.service.ts`
- **Entity:** `apps/backend/src/modules/gamification/entities/ml-coins-transaction.entity.ts`
- **Controller:** `apps/backend/src/modules/gamification/controllers/ml-coins.controller.ts`
- **DTOs:** `apps/backend/src/modules/gamification/dto/ml-coins/`

### Frontend (React)

- **Store:** `apps/frontend/src/features/gamification/economy/store/economyStore.ts`
- **Components:** `apps/frontend/src/features/gamification/economy/components/`
- **Hooks:** `apps/frontend/src/features/gamification/economy/hooks/useTransactions.ts`
- **API:** `apps/frontend/src/features/gamification/api/gamificationAPI.ts`

---

## 🔄 Versionado

### Versión 2.0 (2025-11-08) - ACTUAL

**Cambios:**
- ✅ Migrado `transaction_type` de 10 valores legacy a 14 valores oficiales
- ✅ Agregados: `earned_module`, `earned_streak`, `earned_daily`, `earned_bonus`, `spent_powerup`, `spent_retry`, `bonus`, `welcome_bonus`
- ✅ Consolidado multiplicadores de rango Maya (1.00x - 2.00x)
- ✅ Documentación completa creada

### Versión 1.0 (2025-10-27) - LEGACY

**Características originales:**
- 10 tipos de transacciones
- Función `award_ml_coins()` básica sin multiplicadores
- Sin documentación formal

---

## ✅ Criterios de Aceptación

1. ✅ Usuario puede ganar ML Coins por actividades educativas
2. ✅ Multiplicador de rango Maya se aplica correctamente
3. ✅ Usuario puede gastar ML Coins en comodines y ayudas
4. ✅ Balance nunca puede ser negativo
5. ✅ Todas las transacciones quedan registradas
6. ✅ Metadata JSONB contiene información completa
7. ✅ Frontend muestra balance actualizado en tiempo real
8. ✅ Tests SQL pasan al 100%

---

**Creado:** 2025-11-08
**Aprobado por:** Database Team
**Próxima revisión:** 2025-12-01
