FOX - WooCommerce Currency Switcher Professional

Arrondir les prix convertis dans WooCommerce : .99, entiers et paliers

Un taux de change transforme un joli 49,00 en 45,37 ou en 4 083,12, et peu de boutiques veulent afficher cela. FOX n'a pas de réglage d'arrondi, parce que chaque boutique veut un schéma différent, mais il vous donne deux filtres pour arrondir les prix convertis dans WooCommerce comme vous le souhaitez : nombres entiers, terminaisons .99 ou .95, paliers de 5, 10, 100 ou 1000, devise par devise. La plupart des snippets qui « ne fonctionnent pas » échouent pour l'une de quelques raisons : un seul des deux filtres est utilisé, la devise de base est arrondie elle aussi, les taxes sont ajoutées après l'arrondi, ou le code ne s'exécute pas dans la requête qui redessine les prix. Ce guide les passe toutes en revue.

Deux filtres, et pourquoi il vous faut les deux

FOX convertit les prix à deux endroits, et chacun a son propre filtre :

  • woocs_raw_woocommerce_price reçoit chaque prix converti : produits simples, chaque variation et, avec Plusieurs devises autorisées (Is multiple allowed) = Non (No), chaque montant affiché dans la devise sélectionnée.
  • woocs_woocommerce_variation_prices reçoit les prix que WooCommerce rassemble pour un produit variable afin de construire sa fourchette de prix, le « 45,37 – 61,20 » sous le titre. Il est utilisé avec Plusieurs devises autorisées (Is multiple allowed) = Oui (Yes) ; avec Non (No), la fourchette est affichée via le premier filtre.

Avec le premier filtre seul, un produit variable affiche une fourchette non arrondie, puis un prix arrondi dès qu'une variation est sélectionnée. Avec le second seul, la fourchette est arrondie et la variation sélectionnée ne l'est pas. Rattachez la même fonction aux deux.

Pour une devise convertie, les deux filtres reçoivent une chaîne numérique avec un point comme séparateur décimal, déjà arrondie selon le réglage Décimales (Decimal) de l'onglet Devises (Currencies). Les deux s'exécutent aussi pour la devise de base, sans conversion : c'est donc à la fonction de décider quelles devises elle touche.

Une fonction d'arrondi pour démarrer

/*
 * Round converted prices per currency.
 * Child theme functions.php, or a snippets plugin set to run everywhere.
 */
function myshop_woocs_round_price($price) {
    global $WOOCS;
    if (!isset($WOOCS) || !is_numeric($price) || (float) $price <= 0) {
        return $price; // keep empty and free prices as they are
    }
    $p = (float) $price;

    switch ($WOOCS->current_currency) {
        case 'EUR':
        case 'GBP':
            $p = ceil($p) - 0.01;      // 45.37 -> 45.99
            break;
        case 'JPY':
            $p = ceil($p / 100) * 100; // 4,083 -> 4,100
            break;
        default:
            return $price;             // the base currency and all others stay exact
    }
    return $p > 0 ? $p : $price;
}
add_filter('woocs_raw_woocommerce_price', 'myshop_woocs_round_price');
add_filter('woocs_woocommerce_variation_prices', 'myshop_woocs_round_price');

Remplacez les codes de devise et les formules par les vôtres. Il est important de laisser la devise de base en dehors du switch : sans cela, les prix que vous avez saisis dans vos produits sont arrondis eux aussi, et le montant que vous avez saisi n'est plus le montant que vous facturez.

Recettes d'arrondi

Placez l'une de ces formules à la place des lignes du switch ; $p est le prix converti.

RésultatFormule45,37 devient
Nombre entier le plus procheround($p)45
Nombre entier, toujours au-dessus / en dessousceil($p) / floor($p)46 / 45
Terminaison .99, vers le hautceil($p) - 0.0145,99
Terminaison .99, la plus procheround($p + 0.01) - 0.0144,99
Terminaison .95, vers le hautceil($p) - 0.0545,95
0,50 le plus procheround($p * 2) / 245,50
Jusqu'au multiple de 5 suivantceil($p / 5) * 550
10 / 100 / 1000 le plus procheround($p, -1) / -2 / -350 / 0 / 0
Vers le haut, se terminant par 9 (49, 149, 1 999)ceil($p / 10) * 10 - 149

Les paliers de 100 ou de 1000 n'ont de sens que pour les devises où les prix sont aussi élevés ; le zéro du tableau est là pour vous avertir. Pour les terminaisons comme .99, la devise doit afficher deux décimales : avec Décimales (Decimal) réglé sur 0, le résultat s'affiche comme un nombre entier. Les courtes FAQ sur 99 centimes, 50 centimes, les nombres entiers et les paliers de 500 présentent des versions pour une seule devise.

Deux choses qui ressemblent à de l'arrondi n'en sont pas. Masquer les centimes (Hide cents) dans l'onglet Devises (Currencies) retire les centimes du prix affiché mais les conserve dans le total du panier : un produit affiché à 45 est donc facturé 45,37. Prix sans centimes (Prices without cents) dans l'onglet Options recalcule les devises listées avec zéro décimale, ce qui est un véritable arrondi à l'entier ; sa propre description vous demande de tester la commande après l'avoir activé, y compris avec une commande utilisant un coupon en pourcentage.

Les prix fixes que vous saisissez par devise passent eux aussi par woocs_raw_woocommerce_price. Une formule laisse inchangé un prix qui respecte déjà son schéma : un prix fixe de 19,99 reste donc 19,99 avec la règle .99, mais un prix fixe de 20 devient 19,99. Excluez du switch les devises dont les prix fixes doivent rester tels que saisis.

Arrondi et taxes

woocs_raw_woocommerce_price s'exécute sur le prix du produit avant que WooCommerce n'ajoute ou ne retire la taxe. woocs_woocommerce_variation_prices est différent : lorsque la boutique affiche les prix taxes comprises, la fourchette du produit variable qu'il reçoit contient déjà la taxe. Ce que cela implique dépend des réglages Prix saisis avec taxe (Prices entered with tax) et Afficher les prix dans la boutique (Display prices in the shop) sous WooCommerce → Réglages → Taxes.

Prix saisis hors taxe, affichés taxes comprises

WooCommerce ajoute la taxe à votre prix net arrondi : 45,99 plus 20 % s'affiche donc 55,19, tandis que la fourchette du produit variable, arrondie après taxe, se termine en .99. Pour que chaque prix vu par le client se termine en .99, arrondissez le montant TTC dans le premier filtre et reconvertissez-le avec votre taux, et gardez la formule simple dans le second. Cela fonctionne lorsqu'un seul taux de taxe s'applique à vos clients :

/*
 * .99 endings on prices shown with 20% tax. Child theme functions.php.
 */
add_filter('woocs_raw_woocommerce_price', function ($price) {
    global $WOOCS;
    if (!isset($WOOCS) || !is_numeric($price) || (float) $price <= 0
        || $WOOCS->current_currency === $WOOCS->default_currency) {
        return $price;
    }
    $tax = 1.20; // your tax rate
    return (ceil((float) $price * $tax) - 0.01) / $tax; // net price, shown with tax as .99
});

add_filter('woocs_woocommerce_variation_prices', function ($price) {
    global $WOOCS;
    if (!isset($WOOCS) || !is_numeric($price) || (float) $price <= 0
        || $WOOCS->current_currency === $WOOCS->default_currency) {
        return $price;
    }
    return ceil((float) $price) - 0.01; // the range already includes tax
});

Prix saisis taxes comprises

Les deux filtres reçoivent alors des prix TTC, et les clients taxés au taux de votre pays de base voient le prix arrondi inchangé. Pour un client d'un pays avec un autre taux, WooCommerce retire votre taxe de base et ajoute la sienne : 45,99 avec 20 % chez vous devient ainsi 44,84 à 17 %. Si vous voulez un seul prix TTC partout, WooCommerce dispose d'un filtre prévu exactement pour cela ; la marge varie alors selon le pays :

add_filter('woocommerce_adjust_non_base_location_prices', '__return_false');

Lorsque la devise elle-même ne change pas, il s'agit du comportement fiscal standard de WooCommerce, qui est le même avec FOX désactivé.

Totaux du panier, livraison et prix approximatifs

Avec Plusieurs devises autorisées (Is multiple allowed) = Oui (Yes), le panier est calculé à partir des prix de produits arrondis : les totaux de ligne et le total du panier concordent donc avec ce que le client a vu. Avec Non (No), les montants convertis n'existent qu'à l'écran : woocs_raw_woocommerce_price reçoit chaque montant affiché, y compris les sous-totaux du panier, la livraison et les lignes de taxe, et arrondit chacun séparément, de sorte que les lignes peuvent ne plus s'additionner au total. La page de paiement affiche alors la devise de base, que la fonction ci-dessus laisse intacte. Si les lignes de panier arrondies vous gênent, renvoyez $price inchangé lorsque is_cart() est vrai.

Les frais de livraison ne sont pas des prix de produits et demandent leur propre filtre. Avec Plusieurs devises autorisées (Is multiple allowed) = Oui (Yes), FOX convertit les tarifs de livraison sur woocommerce_package_rates avec la priorité 9999 ; l'arrondi doit donc s'exécuter plus tard :

/*
 * Round converted shipping costs up to whole units, after FOX has converted them.
 * Child theme functions.php.
 */
add_filter('woocommerce_package_rates', function ($rates, $package) {
    global $WOOCS;
    if (!isset($WOOCS) || $WOOCS->current_currency === $WOOCS->default_currency) {
        return $rates;
    }
    foreach ($rates as $rate) {
        $cost = (float) $rate->get_cost();
        if ($cost <= 0) {
            continue; // free shipping stays free
        }
        $cost = ceil($cost);
        $rate->set_cost($cost);
        if (wc_tax_enabled() && !empty($rate->get_taxes()) && !WC()->customer->is_vat_exempt()) {
            $rate->set_taxes(WC_Tax::calc_shipping_tax($cost, WC_Tax::get_shipping_tax_rates()));
        }
    }
    return $rates;
}, 10000, 2);

WooCommerce stocke les tarifs calculés dans la session du client : modifiez donc le contenu du panier ou l'adresse pour voir les nouveaux coûts pendant vos tests.

Les montants approximatifs de Afficher le prix approximatif (Show approx. price) et Afficher le montant approximatif (Show approximate amount) sont calculés directement à partir des taux et ne passent pas par ces filtres ; ils restent donc non arrondis.

Quand l'arrondi ne s'affiche pas

  • Anciens prix sur les produits variables. WooCommerce met en cache les fourchettes de prix des produits variables. Après avoir ajouté ou modifié le code, videz-les dans WooCommerce → État → Outils → Transients WooCommerce (WooCommerce transients), ou enregistrez le produit, puis purgez le cache de page.
  • Arrondi au premier chargement, non arrondi un instant plus tard. Avec J'utilise un plugin de cache sur mon site (I am using cache plugin on my site) activé, FOX redessine les prix via admin-ajax.php. Un plugin de snippets réglé pour ne s'exécuter que sur le front office ne s'exécute pas dans cette requête. Réglez le snippet pour qu'il s'exécute partout, ou placez le code dans le functions.php du thème enfant.
  • Rien ne change du tout. Faites un instant renvoyer à la fonction une constante telle que 777. Si les prix n'affichent pas 777, le code n'est pas chargé ou autre chose définit les prix : un modèle de prix tiers, un plugin de tarification dynamique ou des prix fixes.
  • Erreur fatale après le collage. Le code copié depuis des pages web contient souvent un tiret typographique à la place du signe moins, des guillemets courbes, ou &gt; au lieu de >. Retapez ces caractères à la main. Cannot redeclare signifie que le même nom de fonction a été collé deux fois ; gardez une seule copie.
  • Des prix arrondis que vous n'avez pas arrondis. Un autre snippet ou plugin utilise le même filtre. Recherchez woocs_raw_woocommerce_price dans le thème et dans les snippets.

Checklist

  • Une seule fonction rattachée à la fois à woocs_raw_woocommerce_price et à woocs_woocommerce_variation_prices.
  • La devise de base, et toute devise dont les prix fixes doivent rester exacts, laissées de côté.
  • Configuration des taxes vérifiée : arrondi sur le montant TTC ou woocommerce_adjust_non_base_location_prices si nécessaire.
  • Livraison arrondie séparément, avec une priorité supérieure à 9999.
  • Transients WooCommerce et caches de page vidés, code exécuté dans les requêtes AJAX.

Si les prix ne sont toujours pas arrondis avec un thème par défaut et seulement WooCommerce et FOX actifs, publiez votre snippet et un lien vers un produit sur le forum de support de FOX, et nous l'examinerons.