FOX - Currency Switcher for WooCommerce

Cómo corregir los informes de WooCommerce Analytics para tiendas con múltiples monedas

Si estás usando una tienda WooCommerce con múltiples monedas con WOOCS y tus informes de WooCommerce Analytics muestran totales incorrectos, esta guía te ayudará a solucionarlo.

El problema

Síntoma: WooCommerce Analytics muestra cifras de ventas incorrectas cuando tienes pedidos en múltiples monedas. Ejemplo:
  • Pedido #1: $100 USD
  • Pedido #2: €100 EUR
  • Pedido #3: £100 GBP
Lo que muestra WooCommerce Analytics:
Total Sales: $300
¡Esto es INCORRECTO! WooCommerce está sumando diferentes monedas sin convertirlas: 100 USD + 100 EUR + 100 GBP ≠ 300 USD El cálculo correcto debería ser:
$100 USD + €100 EUR ($109) + £100 GBP ($127) = $336 USD

Por qué sucede esto

WooCommerce Analytics no admite de forma nativa múltiples monedas. Simplemente suma todos los totales de pedidos sin verificar la moneda, tratando todos los números como si estuvieran en tu moneda base. Informes afectados:
  • Informes de ingresos
  • Ventas por fecha
  • Analíticas de ventas de productos
  • Informes de impuestos
  • Informes de envíos
Esto afecta:
  • Decisiones empresariales basadas en datos incorrectos
  • Cálculos de impuestos
  • Informes financieros
  • Análisis de ROI

La solución

Este código convierte todos los pedidos a tu moneda base al mostrar los informes de WooCommerce Analytics, brindándote totales precisos.

Paso 1: Agregar código a tu sitio

Agrega este código al functions.php de tu tema hijo o usa el plugin Code Snippets. Código completo:
/**
 * Fix WooCommerce Analytics for multi-currency stores (WOOCS)
 * Converts all orders to base currency for accurate reporting
 */
// Clear WooCommerce reports cache (run once, then remove this)
add_action('init', function () {
    if (current_user_can('manage_woocommerce')) {
        global $wpdb;
        $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '%_wc_report_%'");
        $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '%wc_admin_report_%'");
    }
});

// Disable Analytics cache to force real-time conversion
add_filter('woocommerce_analytics_enable_cache', '__return_false');

// Convert order totals to base currency in Analytics queries
add_filter('woocommerce_analytics_orders_select_query', function ($results, $args) {
    if (!$results || !isset($results->data) || empty($results->data)) {
        return $results;
    }

    $base_currency = get_woocommerce_currency();

    foreach ($results->data as $key => $order_data) {
        $order_id = $order_data['order_id'];
        $order_currency = get_post_meta($order_id, '_order_currency', true);

        // Only convert if order currency differs from base currency
        if ($order_currency AND $order_currency !== $base_currency) {
            // Get exchange rate from order meta (rate at time of purchase)
            $exchange_rate = get_post_meta($order_id, '_woocs_order_rate', true);

            // Fallback to current rate if historical rate not found
            if (!$exchange_rate) {
                $exchange_rate = woocs_get_exchange_rate($order_currency, $base_currency);
            }

            // Convert all monetary values
            if (isset($order_data['net_total'])) {
                $results->data[$key]['net_total'] = floatval($order_data['net_total']) * floatval($exchange_rate);
            }

            if (isset($order_data['total_sales'])) {
                $results->data[$key]['total_sales'] = floatval($order_data['total_sales']) * floatval($exchange_rate);
            }

            if (isset($order_data['tax_total'])) {
                $results->data[$key]['tax_total'] = floatval($order_data['tax_total']) * floatval($exchange_rate);
            }

            if (isset($order_data['shipping_total'])) {
                $results->data[$key]['shipping_total'] = floatval($order_data['shipping_total']) * floatval($exchange_rate);
            }
        }
    }

    return $results;
}, 10, 2);

/**
 * Helper function to get exchange rate between currencies
 */
function woocs_get_exchange_rate($from_currency, $to_currency) {
    global $WOOCS;

    if (!isset($WOOCS) || !$WOOCS) {
        return 1;
    }

    $currencies = $WOOCS->get_currencies();

    if (isset($currencies[$from_currency]) AND isset($currencies[$to_currency])) {
        $from_rate = floatval($currencies[$from_currency]['rate']);
        $to_rate = floatval($currencies[$to_currency]['rate']);

        if ($from_rate > 0) {
            return $to_rate / $from_rate;
        }
    }

    return 1;
}
 

Paso 2: Verificar resultados

  1. Ve a WooCommerce → Analytics → Revenue
  2. Verifica tus totales de ventas
  3. Compara con los datos anteriores (incorrectos)
  4. Los totales ahora deberían ser precisos, convertidos a la moneda base

Cómo funciona

Parte 1: Limpieza de caché

add_action('init', function () {
    global $wpdb;
    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '%_wc_report_%'");
    ...
});
Qué hace: Limpia los informes almacenados en caché antiguos que contienen datos incorrectos Este código se ejecuta solo para usuarios administradores

Parte 2: Deshabilitar caché de Analytics

add_filter('woocommerce_analytics_enable_cache', '__return_false');
Qué hace: Obliga a WooCommerce Analytics a recalcular los datos en cada vista en lugar de usar valores almacenados en caché Compensación: Los informes pueden cargar un poco más lento, pero los datos siempre serán precisos

Parte 3: Convertir totales de pedidos

add_filter('woocommerce_analytics_orders_select_query', function ($results, $args) {
    // Convert each order to base currency
    ...
});
Qué hace:
  • Intercepta las consultas a la base de datos de Analytics
  • Verifica la moneda de cada pedido
  • Si es diferente de la moneda base, convierte usando la tasa de cambio
  • Devuelve los valores convertidos a Analytics

Parte 4: Función de tasa de cambio

function woocs_get_exchange_rate($from_currency, $to_currency) {
    // Calculate conversion rate between currencies
    ...
}
Qué hace:
  • Obtiene las tasas de cambio actuales de WOOCS
  • Calcula la tasa de conversión entre dos monedas
  • Se usa como respaldo si no se encuentra la tasa histórica

Notas importantes

Tasas de cambio históricas vs. actuales

El código usa tasas históricas cuando es posible:
$exchange_rate = get_post_meta($order_id, '_woocs_order_rate', true);
Por qué es importante:
  • Pedido de hace 6 meses: Se usó la tasa de cambio de esa fecha
  • Informes financieros más precisos
  • Refleja los ingresos reales en el momento de la venta
Respaldo: Si la tasa histórica no está disponible, usa la tasa actual de WOOCS.

Impacto en el rendimiento

Qué cambia:
  • ✅ Informes precisos con múltiples monedas
  • ❌ Los informes pueden cargar 0.5-2 segundos más lento (sin caché)
  • ❌ Aumento de consultas a la base de datos
Recomendación:
  • Tiendas pequeñas (< 1,000 pedidos/mes): Impacto insignificante
  • Tiendas medianas (1,000-10,000 pedidos/mes): Una leve ralentización es aceptable por la precisión
  • Tiendas grandes (10,000+ pedidos/mes): Monitorear el rendimiento, considerar optimización

Caché deshabilitada

add_filter('woocommerce_analytics_enable_cache', '__return_false');
Esto es necesario porque los informes almacenados en caché mostrarían monedas mezcladas. La conversión ocurre en tiempo real en cada vista del informe. Enfoque alternativo para tiendas grandes:
  • Eliminar la línea de deshabilitación de caché
  • Limpiar la caché manualmente cuando las tasas de cambio cambien significativamente
  • Aceptar una ligera imprecisión para un mejor rendimiento

Solución de problemas

Los informes aún muestran totales incorrectos

Problema: Los números no cambiaron después de agregar el código Soluciones:
  1. Caché no limpiada
    • Asegúrate de que el código de limpieza de caché se ejecutó
    • Visita el panel de administración mientras inicias sesión como administrador
    • Verifica si tienes la capacidad manage_woocommerce
  2. Código no activo
    • Verifica que el código esté en functions.php (tema hijo)
    • O verifica que el plugin Code Snippets tenga el fragmento activado
    • Revisa si hay errores PHP en el registro de depuración
  3. Moneda base incorrecta
    • Verifica la moneda base en WooCommerce → Ajustes → General
    • Asegúrate de que WOOCS muestre la misma moneda base

Los informes cargan lentamente

Problema: Analytics tarda 5-10+ segundos en cargar Causas:
  • Base de datos de pedidos grande (10,000+ pedidos)
  • Se necesitan muchas conversiones de moneda
  • Recursos del servidor limitados
Soluciones: Solución 1: Limitar el rango de fechas
// Only convert recent orders (last 12 months)
add_filter('woocommerce_analytics_orders_select_query', function ($results, $args) {
    if (!$results || !isset($results->data)) {
        return $results;
    }
    
    $twelve_months_ago = strtotime('-12 months');
    
    foreach ($results->data as $key => $order_data) {
        $order_date = strtotime($order_data['date_created']);
        
        // Skip old orders
        if ($order_date < $twelve_months_ago) {
            continue;
        }
        
        // ... conversion code ...
    }
    
    return $results;
}, 10, 2);
Solución 2: Reactivar caché para informes específicos Elimina la línea de deshabilitación de caché y limpia la caché manualmente cuando sea necesario. Solución 3: Usar informes externos Considera plugins de análisis dedicados para tiendas grandes.

Tasas de cambio no encontradas

Problema: Algunos pedidos muestran la moneda original, no convertida Causa: Falta el meta _woocs_order_rate en el pedido y WOOCS ya no tiene esa moneda Solución: Agregar mapeo de tasa predeterminado:
function woocs_get_exchange_rate($from_currency, $to_currency) {
    global $WOOCS;
    
    if (!isset($WOOCS) || !$WOOCS) {
        // Fallback rates if WOOCS not available
        $fallback_rates = [
            'EUR' => 1.09,  // EUR to USD
            'GBP' => 1.27,  // GBP to USD
            'CAD' => 0.74,  // CAD to USD
            'AUD' => 0.66,  // AUD to USD
        ];
        
        if (isset($fallback_rates[$from_currency])) {
            return $fallback_rates[$from_currency];
        }
        
        return 1;
    }
    
    $currencies = $WOOCS->get_currencies();
    
    if (isset($currencies[$from_currency]) AND isset($currencies[$to_currency])) {
        $from_rate = floatval($currencies[$from_currency]['rate']);
        $to_rate = floatval($currencies[$to_currency]['rate']);
        
        if ($from_rate > 0) {
            return $to_rate / $from_rate;
        }
    }
    
    return 1;
}

Las conversiones se ven incorrectas

Problema: Los montos convertidos no coinciden con los valores esperados Verificar:
  1. ¿Las tasas de cambio de WOOCS son precisas?
    • Ve a la configuración de WOOCS
    • Verifica que las tasas de cambio estén actualizadas
    • Actualiza las tasas si es necesario
  2. ¿El pedido usó una tasa diferente?
    • Los pedidos usan la tasa de la fecha de compra
    • No la tasa actual
    • Este es el comportamiento correcto
  3. ¿Moneda base correcta?
    // Add debug to see what's happening
       error_log('Order: ' . $order_id);
       error_log('Currency: ' . $order_currency);
       error_log('Rate: ' . $exchange_rate);
       error_log('Original: ' . $order_data['total_sales']);
       error_log('Converted: ' . ($order_data['total_sales'] * $exchange_rate));
     

El código rompe el sitio

Problema: Pantalla blanca o errores después de agregar el código Causa: Error de sintaxis PHP o conflicto Solución:
  1. Accede al sitio mediante FTP
  2. Renombra functions.php a functions.php.backup
  3. El sitio se recupera
  4. Revisa el código en busca de errores de sintaxis
  5. Revisa el registro de errores para el mensaje de error específico

Mejores prácticas

  1. Usa un tema hijo
    • Siempre agrega código al tema hijo
    • Las actualizaciones del tema padre no borrarán el código
  2. Prueba primero
    • Agrega el código primero en un sitio de prueba
    • Verifica que los totales coincidan con las expectativas
    • Luego aplícalo en producción
  3. Monitorea el rendimiento
    • Revisa el tiempo de carga de Analytics antes/después
    • Si es demasiado lento, considera optimizaciones
  4. Mantén actualizadas las tasas de WOOCS
    • Los informes son tan precisos como las tasas de cambio
    • Actualiza las tasas regularmente
    • Considera la función de actualización automática
  5. Documenta los cambios
    • Anota cuándo agregaste este código
    • Mantén una copia de seguridad de functions.php
    • Facilita la solución de problemas

Soluciones alternativas

Para tiendas muy grandes

Si tienes 50,000+ pedidos y esta solución es demasiado lenta, considera:
  1. Tabla de base de datos personalizada
    • Almacena valores convertidos en una tabla personalizada
    • Actualiza cuando se realiza un pedido
    • Consulta la tabla personalizada para informes
  2. Conversión programada
    • Convierte pedidos diariamente mediante cron
    • Almacena en metadatos del pedido
    • Informes rápidos con datos preconvertidos
  3. Análisis externos
    • Exporta a Google Analytics con manejo adecuado de moneda
    • Usa una plataforma de análisis de comercio electrónico dedicada
    • Plugins de informes de WooCommerce de terceros

Para tiendas con pocas monedas

Si solo usas 2-3 monedas, puedes simplificar:
// Hardcoded rates for specific currencies
add_filter('woocommerce_analytics_orders_select_query', function ($results, $args) {
    if (!$results || !isset($results->data)) {
        return $results;
    }
    
    $rates = [
        'EUR' => 1.09,
        'GBP' => 1.27,
        'USD' => 1.00,  // Base currency
    ];
    
    foreach ($results->data as $key => $order_data) {
        $order_id = $order_data['order_id'];
        $order_currency = get_post_meta($order_id, '_order_currency', true);
        
        if (isset($rates[$order_currency])) {
            $rate = $rates[$order_currency];
            $results->data[$key]['total_sales'] = $order_data['total_sales'] * $rate;
            // ... convert other fields
        }
    }
    
    return $results;
}, 10, 2);
Esto es más rápido pero requiere actualizaciones manuales de tasas.

Resumen

El problema: WooCommerce Analytics suma diferentes monedas sin convertirlas, mostrando totales incorrectos. La solución: Agrega código que convierta todos los pedidos a la moneda base usando las tasas de cambio de WOOCS. Compensaciones:
  • ✅ Informes precisos con múltiples monedas
  • ✅ Usa tasas de cambio históricas
  • ❌ Informes 0.5-2 segundos más lentos (sin caché)
  • ❌ No apto para tiendas muy grandes (50,000+ pedidos)
Resultado: WooCommerce Analytics mostrará datos de ingresos precisos con todos los pedidos convertidos a tu moneda base.