Contrôle PrestaShop post-modification : checklist tunnel de commande et règles panier

Guide pratique pour tester le tunnel de commande PrestaShop et valider les règles panier après déploiement, avec contrôles front, DB, logs et tests E2E.

Écrans d'ordinateur affichant une checklist détaillant la sécurité, la performance, les tests et les modifications postérieures de PrestaShop.

Table des matières :

  1. Périmètre de contrôle : ce qui doit déclencher une revue checkout/cart rules
  2. Checklist tunnel de commande : contrôles fonctionnels (front) réellement utiles
  3. Règles panier (CartRule) : validation métier + vérification de l’implémentation
  4. Contrôles techniques côté serveur : logs, exceptions, cache, routes, données
  5. Automatiser la non-régression : Playwright/Cypress + assertions métier
  6. Post-déploiement : métriques, alertes et plan de rollback sur le checkout

Après une modification (core, thème, module, override, configuration, cache), le tunnel de commande est la zone où PrestaShop casse « proprement » (aucun log visible côté client) mais où la conversion s’effondre. Et les règles panier (cart rules) sont la deuxième source d’effets de bord : calculs de TVA/arrondis, cumul interdits, restrictions (groupes, pays, transporteurs), ou simple absence d’application à cause d’un contexte shop mal propagé.

Contexte des exemples ci-dessous : PrestaShop 8.1.7 et 9.1.x, PHP 8.2/8.3, MySQL 8 ou MariaDB 10.6+. Adaptez si vous êtes en 1.7.x (structure cache/logs différente). Pré-requis minimaux : accès SSH, accès DB en lecture, un clone de prod sur staging, et un moyen de rejouer des commandes (même fictives).

Un point souvent sous-estimé : le checkout mélange front, JS, session/cookies, calculs métier, appel PSP et retours asynchrones (webhooks). Une modification « innocente » (traduction, surcharge d’un CartPresenter, ajout d’un champ adresse, changement de règles de taxes) peut casser la chaîne sans générer d’erreur “visuelle”. D’où l’intérêt d’une checklist courte mais tranchante, et d’un minimum d’automatisation.

Périmètre de contrôle : ce qui doit déclencher une revue checkout/cart rules

Une « modification » n’est pas seulement un déploiement de code. Dans PrestaShop, un changement de configuration (transporteurs, taxes, arrondis, règles panier, modes de paiement, multi-boutique), une purge de cache, une mise à jour de module de paiement, ou un simple ajustement de thème peut modifier le rendu et la logique du checkout. Il faut donc déclencher le contrôle après :

  • mise à jour PrestaShop / module (ex. paiement, livraison, taxes)
  • ajout/suppression d’override (override/classes, override/controllers)
  • modification d’un hook critique (displayShoppingCart, displayCheckoutSummary, actionValidateOrder, etc.)
  • changement de routes/URLs (souvent invisible mais destructeur si mal fait) — voir l’article sur la génération d’URL et les routes : Génération d’URL PrestaShop : Link, routes Symfony et legacylink

Ajoutez aussi, de façon pragmatique, les changements “à risque” suivants (souvent oubliés car hors code) :

  • changement de mode de calcul des taxes (adresse de livraison vs facturation), modification de groupes de taxes / règles de taxes
  • modification de zones/pays/états (ex. activation d’un État/Province obligatoire) qui rend des adresses existantes invalides
  • ajustement des devises (arrondis, taux) ou activation d’une nouvelle devise
  • changement de config cookies / reverse proxy (ex. attribut SameSite, HTTPS forcé), qui peut casser les retours de paiement redirigés

Le bon réflexe est de définir un baseline avant changement : 3 scénarios de commande et 3 scénarios de règles panier que vous savez fonctionner. Sans baseline, vous ne faites pas de non-régression, vous faites de l’exploration. Martin Fowler résume bien l’enjeu CI : « Continuous Integration is a software development practice where members of a team integrate their work frequently » (Martin Fowler, “Continuous Integration”, martinfowler.com/articles/continuousIntegration.html). Plus vous intégrez souvent, plus les contrôles doivent être rapides et automatisables.

Pour rendre ce baseline exploitable, documentez-le comme une “fiche” (même dans un README interne) :

  • produits utilisés (IDs + attributs + taxes + poids)
  • adresses (pays/état/cp) et contexte (B2C/B2B si applicable)
  • transporteurs (un domicile + un point relais si vous en avez)
  • paiements (au moins un offline type virement/chèque si dispo + un PSP redirigé)
  • règles panier (codes + restrictions + cumul + dates)

Enfin, si vous testez sur production « parce que c’est plus simple », vous acceptez un risque direct sur le chiffre. Baymard rappelle que l’abandon panier est structurellement élevé : « The average documented online shopping cart abandonment rate is 70.19% » (Baymard cart abandonment rate). Une régression checkout qui ajoute juste une friction (un champ adresse mal validé, un bouton qui “freeze”, un total qui saute) peut suffire à empirer une métrique déjà fragile.

Un point souvent sous-estimé : le checkout mélange front, JS, session/cookies, calculs métier, appel PSP et retours asynchrones (webhooks). Une modification « innocente » (traduction, surcharge d’un CartPresenter, ajout d’un champ adresse, changement de règles de taxes) peut casser la chaîne sans générer d’erreur “visuelle”. D’où l’intérêt d’une checklist courte mais tranchante, et d’un minimum d’automatisation.

Checklist tunnel de commande : contrôles fonctionnels (front) réellement utiles

Le tunnel PrestaShop (8/9) est un hybride : contrôleurs front “legacy” + services Symfony, thèmes Twig/Smarty selon stack, modules qui injectent des étapes ou des validations. Une checklist sérieuse doit couvrir les transitions d’état du panier jusqu’à validateOrder(), pas seulement “ça affiche une page”. Travaillez avec un compte client test, un invité (guest checkout si activé), et au moins 2 adresses.

Avant même de rejouer les scénarios, faites 3 vérifications très rapides qui évitent des faux positifs :

  • Console navigateur (erreurs JS) + onglet Réseau : repérez un 500/404 sur des endpoints typiques (/order, /cart, /module/..., appels AJAX du checkout).
  • Mobile (responsive) : un checkout qui “passe” desktop peut échouer mobile (bouton masqué, modal bloquante, champs “autocomplete” qui cassent la validation).
  • Langue/devise si vous vendez en multi-langue/multi-devise : un libellé de transporteur ou une traduction manquante peut casser une étape (et certains modules utilisent des chaînes comme clés).

Scénarios minimum à rejouer (les plus rentables en termes de détection) :

1) Commande simple : 1 produit, 1 transporteur, 1 paiement. Vérifiez : ajout panier, step shipping, step payment, page de confirmation, e-mail, BO > commandes.
2) Commande avec variances : déclinaisons + quantité > stock + règle de stock (backorders) + packaging cadeau si activé.
3) Commande avec contraintes : zone géographique (pays/état), changement de transporteur (point relais vs domicile), et un paiement redirigé (PS Checkout/Stripe/PayPal) pour tester retour/callback.

Pour ajouter un peu de “réalité terrain” en contexte FR/EU sans complexifier : si votre boutique expédie au moins en France + UE, ajoutez une adresse hors France (ex. Belgique/Luxembourg) dans le scénario 3. Les écarts de TVA, de transporteurs disponibles et de formats d’adresse sont des déclencheurs fréquents de bugs (champ “State” obligatoire, restrictions transporteur par zone, règles panier limitées à un pays).

Dans chaque scénario, les points de contrôle doivent être concrets :

  • Les totaux (HT/TTC, TVA, frais de port, réductions) restent stables entre les pages (panier → checkout → paiement). Si les totaux changent, cherchez d’abord une différence de contexte (adresse de livraison vs facturation, transporteur recalculé, devise, taxe).
    Astuce de diagnostic : notez les totaux à chaque étape et le transporteur sélectionné. Une régression classique est un “reset” du transporteur (ex. module point relais) qui déclenche un recalcul de port à 0 ou à une autre tranche.
  • Les erreurs sont affichées proprement (message, pas page blanche). Si vous tombez sur du blanc ou une page tronquée, il faut basculer sur une démarche “serveur d’abord” (voir : Page vide HTML : détection d’erreurs de rendu serveur et CMS et Gestion d’erreur PHP : bonnes pratiques et configuration développement/production).
  • Le retour paiement (success/cancel) est cohérent : panier vidé au succès, panier conservé (ou restaurable) à l’annulation, et pas d’état “paiement accepté” sans transaction.
    En pratique, vérifiez aussi que l’utilisateur revient bien sur votre domaine (problèmes HTTPS/cookies) et que les redirections n’aboutissent pas sur une URL “legacy” cassée (d’où l’intérêt d’avoir cadré vos routes et Link, cf. l’article sur les routes ci-dessus).

Une mini-matrice de test simple (à mettre dans un doc interne) suffit souvent :

Scénario Adresse livraison Transporteur Paiement Règle panier Attendu clé
Simple FR (CP standard) Domicile Offline (virement) Aucune commande créée + totaux stables
Variances FR Domicile PSP % remise pas d’écarts de centimes, réduction correcte
Contraintes UE (hors FR) Point relais PSP redirigé Livraison gratuite port = 0 uniquement si éligible, retour PSP OK

Si vous utilisez un module de paiement exposé à des correctifs récents, ajoutez un contrôle “version + comportement”. Exemple concret : pour ps_checkout, une mise à jour de sécurité peut changer des endpoints, des webhooks, ou des flows d’authentification ; gardez une trace des versions déployées et validez le parcours après chaque update (référence : CVE-2025-61922 ps_checkout : mise à jour 5.0.5 et mesures).

Enfin, n’oubliez pas un contrôle “anti-régression UX” minimal mais très rentable : le bouton de validation (souvent surchargé par thème/modules) doit être cliquable, et l’utilisateur doit avoir un feedback (loading). Un checkout qui “double-clique” peut créer des doublons de tentatives de paiement ou des paniers incohérents.

Règles panier (CartRule) : validation métier + vérification de l’implémentation

Dans PrestaShop, une règle panier n’est pas “un coupon”. C’est une entité cart_rule avec des contraintes réparties dans plusieurs tables (et parfois plusieurs lignes) : restrictions par boutique, groupe, pays, transporteur, produits, catégories, dates, nombre d’utilisations, cumul, etc. La validation passe notamment par CartRule::checkValidity() et les totaux par Cart::getOrderTotal() — deux zones où les modules aiment surcharger via hooks/overrides, et où un changement de version peut casser des hypothèses.

Deux pièges classiques (qui expliquent des “ça marchait hier”) :

  • Contexte multiboutique : une règle panier active mais non liée à la boutique courante ne s’applique pas. Sur un staging qui n’a qu’une boutique, tout marche ; en prod multiboutique, la même règle devient “invisible”.
  • Restrictions transporteur : si votre transporteur est “remplacé” par un module (point relais, agrégateur), l’ID transporteur peut changer en cours de checkout. Une règle “livraison gratuite” liée à un transporteur précis ne s’appliquera plus.

Checklist fonctionnelle côté front/back-office (à faire avec des jeux de données “tranchants”, pas un panier trivial) :

  • Coupon à montant fixe (ex. 10€) avec panier juste au-dessus et juste en dessous du minimum, pour vérifier le respect de minimum_amount et l’absence de total négatif.
  • Coupon à pourcentage + produits en promo, pour vérifier l’interaction “réduction sur prix déjà réduit” et le paramètre de cumul.
  • Livraison gratuite conditionnée (transporteur, pays, seuil) : c’est la règle qui casse le plus souvent car le port est recalculé tard dans le tunnel.
  • Restrictions groupes clients et multiboutique : testez explicitement un compte d’un groupe non éligible et une boutique non assignée.
  • (Option utile si vous faites du B2B) Coupon réservé à un groupe “Pro” + adresse UE : vérifiez que la TVA/les conditions d’éligibilité ne “flip” pas au changement d’adresse (ce qui peut faire apparaître/disparaître la règle panier en cours de tunnel).

Checklist technique DB (utile après import, migration, ou modification manuelle) :

1) Détecter les règles panier “orphelines” (mauvais mapping shop) :

SELECT cr.id_cart_rule, cr.code, cr.active
FROM ps_cart_rule cr
LEFT JOIN ps_cart_rule_shop crs ON crs.id_cart_rule = cr.id_cart_rule
WHERE cr.active = 1 AND crs.id_shop IS NULL;

2) Vérifier les règles récentes avec code (utile si vous avez ajouté des règles en masse) :

SELECT id_cart_rule, code, reduction_percent, reduction_amount, date_upd
FROM ps_cart_rule
WHERE active = 1 AND code <> ''
ORDER BY date_upd DESC
LIMIT 50;

3) Contrôler la cohérence des dates et compteurs :

SELECT id_cart_rule, code, quantity, quantity_per_user, date_from, date_to
FROM ps_cart_rule
WHERE active = 1 AND (date_to < NOW() OR date_from > NOW());

4) (Très pratique) Détecter des règles panier actives mais “sur-restrictives” (liées à un pays/transporteur) lorsque votre business a évolué :

SELECT cr.id_cart_rule, cr.code, cr.active,
       COUNT(DISTINCT crc.id_country) AS nb_pays,
       COUNT(DISTINCT crca.id_carrier) AS nb_transporteurs
FROM ps_cart_rule cr
LEFT JOIN ps_cart_rule_country crc ON crc.id_cart_rule = cr.id_cart_rule
LEFT JOIN ps_cart_rule_carrier crca ON crca.id_cart_rule = cr.id_cart_rule
WHERE cr.active = 1 AND cr.code <> ''
GROUP BY cr.id_cart_rule, cr.code, cr.active
ORDER BY cr.id_cart_rule DESC
LIMIT 50;

Interprétation : nb_pays = 0 signifie “pas de restriction pays” (souvent OK), mais nb_pays > 0 ou nb_transporteurs > 0 mérite d’être comparé à vos zones/transporteurs réellement en production après une modification.

Point d’attention souvent ignoré : les arrondis. Un changement de configuration (PS_ROUND_TYPE, mode d’arrondi, précision) peut produire des écarts centimes qui bloquent certains PSP (montant signé vs montant attendu). Le symptôme typique : total affiché OK, paiement refusé “amount mismatch” ou commande validée mais paiement non rapproché. Vous devez donc tester au moins un panier avec plusieurs lignes, plusieurs TVA, et une remise, puis comparer : total panier (front) vs total dans ps_orders.total_paid_tax_incl après validation.

Action rapide “anti-écarts” : ajoutez un panier test avec 3 lignes (prix TTC différents), une remise %, et un frais de port TTC non rond (ex. 4,99). C’est typiquement ce genre de panier qui révèle un changement de mode d’arrondi.

Contrôles techniques côté serveur : logs, exceptions, cache, routes, données

Le cœur PrestaShop reste bavard… à condition d’aller lire au bon endroit. En 8/9, commencez par var/logs/ (selon configuration Monolog) et les logs serveur (Nginx/Apache + PHP-FPM). Un contrôle post-modification doit inclure :

  • montée d’erreurs 5xx sur /order, /order-confirmation, endpoints AJAX checkout
  • exceptions PHP (Fatal/TypeError) souvent liées à un override/module incompatible PHP 8.x
  • erreurs “Header already sent”, “Cannot modify header information” qui cassent les redirections paiement

Deux commandes utiles en staging (ou en prod avec précaution) pour diagnostiquer des régressions liées aux routes / contrôleurs :

php bin/console debug:router --env=prod | grep -E 'order|cart|checkout'
php bin/console about --env=prod
  • debug:router permet de repérer rapidement une route checkout “écrasée” ou absente (après un changement de module, de thème ou de configuration).
  • about donne un aperçu de l’environnement Symfony (utile pour vérifier l’env, le debug, etc.).

Côté cache, la règle est simple : si vous modifiez un template, un service Symfony, ou des fichiers de traduction, vous devez être capable de purger proprement et de reproduire. Sur PrestaShop 8/9 :

# prudence : en prod, préférez une procédure contrôlée (maintenance + warmup)
rm -rf var/cache/prod/*
php bin/console cache:clear --env=prod --no-debug

Sur des stacks à fort trafic, ajoutez si possible un warmup (même partiel) et une vérification TTFB sur les pages clé. Si votre performance se dégrade après purge (OPcache froid, cache Symfony froid), vous risquez d’attribuer à tort une baisse de conversion à un bug checkout alors que c’est un problème de temps de réponse (cf. réduction du TTFB sous 200 ms).

Ensuite, vérifiez que vos reverse proxies / caches serveur n’introduisent pas de comportement non déterministe (panier “partagé”, pages checkout servies en cache). Si vous avez Varnish/Redis/Memcached, relisez vos règles d’exclusion checkout et cookies ; sinon vous allez “valider” un tunnel en staging et casser la prod sous cache. Référence utile pour cadrer le sujet : Cache PrestaShop : Varnish, Redis, Memcached et OPcache côté serveur.

Dernier bloc : la donnée. Une modification checkout est souvent “OK” en environnement propre mais échoue en prod sur des paniers anciens, des cart rules périmées, ou des clients avec adresses incomplètes. Ajoutez donc un contrôle sur les commandes en erreur (ex. état incohérent, paiement sans commande, commande sans paiement) :

-- paiements sans commande liée (selon modules, à adapter)
SELECT op.order_reference, op.payment_method, op.amount, op.date_add
FROM ps_order_payment op
LEFT JOIN ps_orders o ON o.reference = op.order_reference
WHERE o.id_order IS NULL
ORDER BY op.date_add DESC
LIMIT 20;

Deux requêtes complémentaires (souvent révélatrices après modif de thème/checkout ou module transporteur) :

-- paniers avec adresse livraison manquante (peut bloquer taxes/transport)
SELECT c.id_cart, c.id_customer, c.id_address_delivery, c.date_add
FROM ps_cart c
WHERE c.id_address_delivery = 0
ORDER BY c.date_add DESC
LIMIT 20;
-- commandes avec transport à 0 alors qu'un transporteur est attendu (à interpréter selon votre business)
SELECT o.id_order, o.reference, o.total_shipping_tax_incl, o.total_paid_tax_incl, o.date_add
FROM ps_orders o
WHERE o.total_shipping_tax_incl = 0
ORDER BY o.date_add DESC
LIMIT 20;

L’objectif n’est pas de “tout auditer”, mais de repérer une anomalie de données qui expliquerait une régression observée côté front (ex. sélection transporteur non persistée, adresse invalidée, règle panier qui saute).

Automatiser la non-régression : Playwright/Cypress + assertions métier

Faire une checklist à la main une fois, c’est bien. Être capable de la rejouer à chaque merge, c’est ce qui vous évite le tunnel “cassé” découvert par un client. Sur PrestaShop, l’automatisation la plus rentable est un smoke test E2E (Playwright ou Cypress) qui va du panier à la confirmation sur un environnement de staging avec moyens de paiement de test.

Concrètement, votre test ne doit pas seulement cliquer : il doit asserter des invariants métier. Exemple d’assertions :

  • le total affiché dans le récap checkout = total attendu calculé à partir de fixtures
  • l’URL de chaque étape checkout répond en 200, sans redirection imprévue (utile si vous manipulez les routes/Link)
  • après paiement, existence d’une commande en base avec current_state attendu + montant attendu

Exemple très minimal en Playwright (idée : rester lisible, pas “parfait”) :

import { test, expect } from '@playwright/test';

test('Smoke checkout: panier -> confirmation', async ({ page }) => {
  await page.goto('/fr/');
  await page.goto('/fr/panier?action=show'); // ou votre URL de panier

  // Vérifie que le checkout charge
  await page.goto('/fr/commande');
  await expect(page).toHaveURL(/commande|order/);
  await expect(page.locator('.cart-summary, #js-checkout-summary')).toBeVisible();

  // Assertion métier simple : total non vide et format monétaire
  const total = await page.locator('.cart-total .value, .order-total .value').first().innerText();
  expect(total).toMatch(/\d/);
});

Même si vous gardez un PSP “complexe” pour les tests manuels, un paiement offline (virement/chèque/contre-remboursement selon modules) est souvent très utile en E2E : il permet d’aller jusqu’à la création de commande sans dépendre de redirections externes.

Pour industrialiser, ancrez ça dans votre pipeline CI/CD. Si vous faites des builds Docker reproductibles, vous pouvez injecter des fixtures SQL et un profil de config “test checkout” (transporteur unique, paiement sandbox). L’article suivant donne un cadre solide pour rendre l’environnement déterministe : Intégration continue PrestaShop : BuildKit, GitHub Actions et build reproductible.

Et si vous développez des modules, n’oubliez pas la couche “unit/integ” : tester CartRule::checkValidity() purement en PHPUnit est difficile sans boot complet, mais vous pouvez au moins isoler vos services (ex. calculs de remise) et verrouiller les régressions. Sur PrestaShop 9 (Symfony 6.4), c’est plus réaliste de tester des services Symfony propres, ce qui limite la dépendance au legacy.

Post-déploiement : métriques, alertes et plan de rollback sur le checkout

Le contrôle post-modification ne s’arrête pas au “ça passe sur staging”. Le checkout est une chaîne : front → back → PSP → webhook → BO. Vous devez monitorer en production au moins : taux de 5xx sur endpoints checkout, taux d’abandons sur étapes clés, temps de réponse (TTFB, backend), et volume d’ordres “en attente de paiement” anormal.

Concrètement, définissez 3 alertes simples (même sans gros stack observabilité) :

  • erreurs 5xx sur /order et /order-confirmation (et endpoints /module/* liés au paiement/livraison)
  • hausse des commandes “en attente de paiement” vs baseline (par exemple sur une fenêtre glissante de 30–60 minutes)
  • pente d’abandons (si vous trackez des événements étape checkout côté analytics) : un saut brutal après déploiement est un signal fort

Côté perf et UX, ne vous contentez pas de Lighthouse en local. Google définit ainsi les CWV : « Core Web Vitals are a set of real-world, user-centered metrics that quantify key aspects of the user experience » (web.dev/vitals). Sur checkout, surveillez surtout INP (interactions) et erreurs JS ; un module peut ajouter un script qui dégrade l’interactivité et fait chuter la conversion sans casser fonctionnellement. Pour cadrer les méthodes (runbooks, tests de charge, observation), vous avez une base : PrestaShop performance : monitoring, tests de charge et runbooks soldes et TTFB PrestaShop : réduire le Time To First Byte sous 200 ms.

Enfin, documentez un rollback spécifique checkout : revenir au build précédent, mais aussi revenir à la configuration précédente (cart rules, transporteurs, modes de paiement) si le problème est fonctionnel. Gardez en tête que le cœur PrestaShop ne fournit pas un mécanisme natif de “configuration versionnée” : si vous modifiez des règles panier en BO sans trace, vous compliquez la restauration.

Approche pragmatique (et rapide à mettre en place) :

  • avant changement : export SQL ciblé des tables sensibles à votre checkout (au minimum cart_rule*, carrier*, tax*, configuration, éventuellement module/hook_module selon votre pratique)
  • après changement : notez versions (core + modules paiement/livraison) et la date/heure de déploiement (pour corréler logs et anomalies)
  • runbook rollback : (1) bascule maintenance, (2) rollback applicatif, (3) purge cache contrôlée, (4) vérification rapide via le smoke test E2E, (5) sortie maintenance

Dernier garde-fou très utile : prévoyez une “porte de sortie” business côté paiement (ex. activer temporairement un moyen offline si un PSP est KO), le temps de diagnostiquer. Un checkout partiellement dégradé vaut souvent mieux qu’un checkout bloqué, tant que vous restez clair sur l’expérience client et les délais de traitement.


À lire aussi