Guía de Migración - Agregar Nueva Moneda
🎯 Objetivo
Esta guía te ayudará a agregar una nueva moneda (ej: EUR, GBP, MXN) al sistema de ThreeTrackr de manera sistemática y sin romper funcionalidad existente.
📋 Checklist de Migración
Fase 1: Backend
- [ ] Agregar moneda al enum
Currencyen GraphQL schema - [ ] Actualizar tipos generados (
apollo build) - [ ] Verificar que las queries incluyan el campo
currency - [ ] Probar creación de órdenes/productos en la nueva moneda
Fase 2: Frontend Core
- [ ] Actualizar
CurrencyDisplaycomponent - [ ] Agregar configuración de formateo
- [ ] Actualizar tasas de cambio
- [ ] Agregar lógica de conversión
- [ ] Probar conversiones bidireccionales
Fase 3: Componentes
- [ ] Verificar que todos los componentes usen
CurrencyDisplay - [ ] Probar en diferentes contextos (órdenes, productos, billing)
- [ ] Verificar responsive design
- [ ] Probar con datos reales
Fase 4: Testing
- [ ] Tests unitarios para conversiones
- [ ] Tests de integración
- [ ] Testing manual en diferentes navegadores
- [ ] Verificar accesibilidad
🚀 Proceso Paso a Paso
Paso 1: Agregar Moneda al Schema GraphQL
# En el schema de GraphQL (backend)
enum Currency {
USD
COP
EUR # ← Nueva moneda
}
Paso 2: Regenerar Tipos
# Regenerar tipos GraphQL
pnpm --filter=@packages/apollo run build
# Verificar que no hay errores
pnpm check
Paso 3: Actualizar CurrencyDisplay
// packages/ui/src/components/shared/currency.tsx
// 1. Agregar configuración de formateo
const formatConfig = useMemo(() => {
const configs = {
USD: {
locale: "en-US",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
},
COP: {
locale: "es-CO",
currency: "COP",
minimumFractionDigits: 0,
maximumFractionDigits: 0,
},
EUR: { // ← Nueva configuración
locale: "de-DE", // o "es-ES", "fr-FR", etc.
currency: "EUR",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
},
};
return configs[targetCurrency] || configs.USD;
}, [targetCurrency]);
// 2. Actualizar tasas de cambio
const defaultExchangeRates = {
USD_TO_COP: 4200,
COP_TO_USD: 1 / 4200,
USD_TO_EUR: 0.85, // ← Nueva tasa
EUR_TO_USD: 1 / 0.85, // ← Nueva tasa
COP_TO_EUR: 4200 * 0.85, // ← Tasa derivada
EUR_TO_COP: 1 / (4200 * 0.85), // ← Tasa derivada
};
// 3. Actualizar lógica de conversión
const finalValue = useMemo(() => {
if (sourceCurrency === targetCurrency) {
return value;
}
if (exchangeRate) {
return value * exchangeRate;
}
// Conversiones existentes
if (sourceCurrency === "USD" && targetCurrency === "COP") {
return value * defaultExchangeRates.USD_TO_COP;
} else if (sourceCurrency === "COP" && targetCurrency === "USD") {
return value * defaultExchangeRates.COP_TO_USD;
}
// ← Nuevas conversiones para EUR
else if (sourceCurrency === "USD" && targetCurrency === "EUR") {
return value * defaultExchangeRates.USD_TO_EUR;
} else if (sourceCurrency === "EUR" && targetCurrency === "USD") {
return value * defaultExchangeRates.EUR_TO_USD;
} else if (sourceCurrency === "COP" && targetCurrency === "EUR") {
return value * defaultExchangeRates.COP_TO_EUR;
} else if (sourceCurrency === "EUR" && targetCurrency === "COP") {
return value * defaultExchangeRates.EUR_TO_COP;
}
return value;
}, [value, sourceCurrency, targetCurrency, exchangeRate]);
Paso 4: Actualizar Configuración de Proyecto
// En páginas donde se obtiene la moneda del proyecto
const { data: projectData } = await ApolloServerSupabase.query({
query: graphql(/* GraphQL */ `
query GetProjectCurrency {
getProject {
currency # ← Este campo ya debería soportar la nueva moneda
}
}
`),
context: {
headers: {
"x-project-slug": params.projectSlug,
},
},
});
Paso 5: Testing
Test 1: Conversión Básica
// Crear orden en EUR
const order = {
totalPrice: 25.99, // €25.99
currency: "EUR"
};
// Proyecto en USD
<CurrencyDisplay
value={25.99}
sourceCurrency={Currency.Eur}
targetCurrency={Currency.Usd}
/>
// Esperado: $30.58 USD (25.99 * 1/0.85)
Test 2: Sin Conversión
// Orden EUR en proyecto EUR
<CurrencyDisplay
value={25.99}
sourceCurrency={Currency.Eur}
targetCurrency={Currency.Eur}
/>
// Esperado: €25.99 EUR (sin conversión)
Test 3: Planes de Billing
// Plan USD en proyecto EUR
<CurrencyDisplay
value={29.99}
sourceCurrency={Currency.Usd}
targetCurrency={Currency.Eur}
showDecimals={true}
/>
// Esperado: €35.28 EUR
🧪 Script de Testing
#!/bin/bash
# test-currency.sh
echo "🧪 Testing Currency System..."
# Test 1: Build
echo "1. Building Apollo types..."
pnpm --filter=@packages/apollo run build
# Test 2: Lint
echo "2. Running linter..."
pnpm check
# Test 3: Type check
echo "3. Type checking..."
pnpm --filter=app run type-check
echo "✅ All tests passed!"
📊 Matriz de Conversiones
| Desde \ Hacia | USD | COP | EUR |
|---|---|---|---|
| USD | - | ×4,200 | ×0.85 |
| COP | ÷4,200 | - | ×0.0002 |
| EUR | ÷0.85 | ×5,000 | - |
Nota: Las tasas son ejemplos. Usar tasas reales en producción.
🚨 Problemas Comunes
Problema: "Type 'EUR' is not assignable to type 'Currency'"
Solución Regenerar tipos GraphQL
pnpm --filter=@packages/apollo run build
Problema: Conversiones incorrectas
Solución Verificar tasas de cambio y lógica de conversión
// Debug: Agregar logs temporales
console.log('Conversion:', {
from: sourceCurrency,
to: targetCurrency,
value,
rate: defaultExchangeRates[`${sourceCurrency}_TO_${targetCurrency}`],
result: finalValue
});
Problema: Formateo incorrecto
Solución Verificar configuración de locale
// Verificar que el locale existe
const configs = {
EUR: {
locale: "de-DE", // ← Asegurar que existe
currency: "EUR",
// ...
}
};
Problema: No se muestra la nueva moneda en selects
Solución Actualizar componentes de selección
// En formularios de configuración
const currencyOptions = [
{ value: "USD", label: "USD - US Dollar" },
{ value: "COP", label: "COP - Colombian Peso" },
{ value: "EUR", label: "EUR - Euro" }, // ← Agregar
];
🔄 Rollback Plan
Si algo sale mal:
- Revertir cambios en el enum Currency
- Regenerar tipos
pnpm --filter=@packages/apollo run build - Verificar que todo funciona como antes
- Investigar el problema antes de reintentar
📝 Documentación
Después de agregar la nueva moneda:
- Actualizar
CURRENCY_SYSTEM.md - Actualizar
CURRENCY_EXAMPLES.md - Agregar casos de prueba
- Actualizar esta guía si es necesario
🎉 Validación Final
- [ ] ✅ Nueva moneda aparece en selects de configuración
- [ ] ✅ Conversiones funcionan correctamente (todas las direcciones)
- [ ] ✅ Formateo es correcto (locale, decimales, símbolo)
- [ ] ✅ No hay errores de TypeScript
- [ ] ✅ No hay errores de linting
- [ ] ✅ Funciona en todos los componentes (órdenes, productos, billing)
- [ ] ✅ Tests pasan
- [ ] ✅ Documentación actualizada
Nota Esta guía es un template. Adaptar los valores específicos (tasas de cambio, locales, etc.) según la moneda que se esté agregando.
Última actualización Diciembre 2024