- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| P0-000-pre-migration-backup.sh | ||
| P0-001-migrate-maya-rank-values.sql | ||
| README.md | ||
Migraciones de Base de Datos - Gamilit Backend
Este directorio contiene scripts de migración para correcciones críticas (P0) identificadas durante la migración del backend de Express a NestJS.
Estructura de Archivos
migrations/
├── README.md # Este archivo
├── P0-000-pre-migration-backup.sh # Script de backup pre-migración
├── P0-001-migrate-maya-rank-values.sql # Migración P0-1: MayaRank legacy → correcto
└── backups/ # Directorio de backups (creado automáticamente)
P0-001: Migración de MayaRank Legacy
Problema Identificado
Durante la validación del código contra la documentación (2025-11-07), se identificó que la tabla gamification_system.user_stats contiene valores legacy incorrectos para el campo current_rank:
Valores Legacy (INCORRECTOS):
NACOMBATABHOLCATTEGUERREROMERCENARIO
Valores Correctos (Jerarquía Maya Oficial):
Ajaw(Nivel 1: 0-999 XP) - Señor, líder supremoNacom(Nivel 2: 1,000-2,999 XP) - Capitán de guerraAh K'in(Nivel 3: 3,000-5,999 XP) - Sacerdote del solHalach Uinic(Nivel 4: 6,000-9,999 XP) - Hombre verdaderoK'uk'ulkan(Nivel 5: 10,000+ XP) - Serpiente emplumada
Lógica de Migración
- Basada en XP: Calcula el rango correcto según
total_xpdel usuario - Preserva Progreso: Recalcula
rank_progress(0-100%) dentro del nuevo rango - Idempotente: Puede ejecutarse múltiples veces sin efectos adversos
- Safe: Incluye validaciones y reportes antes/después
Instrucciones de Ejecución
Paso 1: Crear Backup
# Configurar variables de entorno
export DB_HOST="localhost"
export DB_PORT="5432"
export DB_NAME="gamilit_platform"
export DB_USER="gamilit_user"
export DB_PASSWORD="your_password_here"
# Ejecutar backup
chmod +x P0-000-pre-migration-backup.sh
./P0-000-pre-migration-backup.sh
Esto creará un backup en backups/user_stats_backup_YYYYMMDD_HHMMSS.sql.
Paso 2: Ejecutar Migración
# Opción A: Con psql directamente
psql -h localhost -p 5432 -U gamilit_user -d gamilit_platform -f P0-001-migrate-maya-rank-values.sql
# Opción B: Con PGPASSWORD
PGPASSWORD='your_password' psql -h localhost -p 5432 -U gamilit_user -d gamilit_platform -f P0-001-migrate-maya-rank-values.sql
Paso 3: Verificar Migración
La migración incluye validaciones automáticas que imprimirán:
- Cantidad de registros legacy antes de migración
- Cantidad de registros migrados
- Distribución de usuarios por rango
- Confirmación de éxito/errores
Verificaciones manuales adicionales:
-- 1. Verificar que no quedan valores legacy
SELECT COUNT(*)
FROM gamification_system.user_stats
WHERE current_rank IN ('NACOM', 'BATAB', 'HOLCATTE', 'GUERRERO', 'MERCENARIO');
-- Resultado esperado: 0
-- 2. Ver distribución de rangos
SELECT current_rank, COUNT(*) as usuarios
FROM gamification_system.user_stats
GROUP BY current_rank
ORDER BY
CASE current_rank
WHEN 'Ajaw' THEN 1
WHEN 'Nacom' THEN 2
WHEN 'Ah K''in' THEN 3
WHEN 'Halach Uinic' THEN 4
WHEN 'K''uk''ulkan' THEN 5
END;
-- 3. Verificar que rank_progress está en rango 0-100
SELECT user_id, current_rank, rank_progress, total_xp
FROM gamification_system.user_stats
WHERE rank_progress < 0 OR rank_progress > 100;
-- Resultado esperado: 0 filas
-- 4. Verificar coherencia XP vs Rango
SELECT
CASE
WHEN total_xp < 1000 AND current_rank != 'Ajaw' THEN 'INCOHERENTE'
WHEN total_xp >= 1000 AND total_xp < 3000 AND current_rank != 'Nacom' THEN 'INCOHERENTE'
WHEN total_xp >= 3000 AND total_xp < 6000 AND current_rank != 'Ah K''in' THEN 'INCOHERENTE'
WHEN total_xp >= 6000 AND total_xp < 10000 AND current_rank != 'Halach Uinic' THEN 'INCOHERENTE'
WHEN total_xp >= 10000 AND current_rank != 'K''uk''ulkan' THEN 'INCOHERENTE'
ELSE 'OK'
END as validacion,
COUNT(*) as cantidad
FROM gamification_system.user_stats
GROUP BY validacion;
-- Resultado esperado: Solo 'OK' con todas las filas
Rollback
Si necesitas revertir la migración:
# Restaurar desde backup
psql -h localhost -p 5432 -U gamilit_user -d gamilit_platform < backups/user_stats_backup_YYYYMMDD_HHMMSS.sql
NOTA: El rollback completo requiere:
- Eliminar todos los registros actuales
- Restaurar desde backup
- No hay forma de "deshacer" solo la migración sin afectar cambios posteriores
Funciones Helper Creadas
La migración crea dos funciones helper que se mantienen en la base de datos para uso futuro:
gamification_system.calculate_maya_rank_from_xp(xp INTEGER)
Calcula el rango maya correcto basándose en XP total.
Uso:
SELECT gamification_system.calculate_maya_rank_from_xp(5000);
-- Resultado: 'Ah K'in'
gamification_system.calculate_rank_progress(xp INTEGER, rank TEXT)
Calcula el progreso (0-100%) dentro de un rango específico.
Uso:
SELECT gamification_system.calculate_rank_progress(1500, 'Nacom');
-- Resultado: 25.00 (1500 XP = 25% de camino de Nacom a Ah K'in)
Estas funciones pueden usarse en:
- Triggers para auto-actualizar rangos al ganar XP
- Queries de leaderboard
- APIs de progreso de usuario
Actualizaciones de Código Relacionadas
Backend NestJS
src/shared/constants/enums.constants.ts:
export enum MayaRank {
AJAW = 'Ajaw', // Nivel 1
NACOM = 'Nacom', // Nivel 2
AH_KIN = 'Ah K\'in', // Nivel 3
HALACH_UINIC = 'Halach Uinic', // Nivel 4
KUKUKULKAN = 'K\'uk\'ulkan', // Nivel 5
}
Enum DEPRECATED (no usar):
// @deprecated - Legacy values, will be removed in v2.0
export enum MayaRankEnum {
NACOM = 'nacom',
BATAB = 'batab',
// ...
}
DDL Actualizado (opcional)
Si la tabla usa un ENUM de PostgreSQL en lugar de TEXT:
DROP TYPE IF EXISTS maya_rank CASCADE;
CREATE TYPE maya_rank AS ENUM (
'Ajaw',
'Nacom',
'Ah K''in',
'Halach Uinic',
'K''uk''ulkan'
);
-- Si la columna usa ENUM, alterar la tabla:
ALTER TABLE gamification_system.user_stats
ALTER COLUMN current_rank TYPE maya_rank USING current_rank::maya_rank;
Troubleshooting
Error: "password authentication failed"
- Verificar que
DB_PASSWORDesté configurado correctamente - Verificar que el usuario tenga permisos en la base de datos
Error: "relation does not exist"
- Verificar que el schema
gamification_systemexiste - Verificar que la tabla
user_statsexiste
Error: "column rank_progress does not exist"
- La estructura de la tabla no coincide con la esperada
- Verificar DDL de
user_stats
Migración completada pero quedan valores legacy
- Revisar los mensajes de error en el output
- Verificar que la función
calculate_maya_rank_from_xpse creó correctamente - Ejecutar manualmente las queries de validación
Referencias
- Issue: Discrepancia P0-3 - Reporte Final Fase 1
- Documentación:
/docs/02-especificaciones-tecnicas/apis/gamificacion-api/01-RANGOS-MAYA.md - ADR: (pendiente - ADR sobre sistema de rangos)
- Fecha de Creación: 2025-11-07
- Autor: Claude Code (Sonnet 4.5)