Prestashop : Restreindre un transporteur par code postal

Ce tutoriel est compatible avec les versions de Prestashop suivantes :
1.6 1.7 1.7.8 8.0 +
Cet article est assez ancien, malgré toute l'attention que j' apporte à mes contenus il est possible que celui-ci ne soit plus d'actualité.
N'hésitez pas à me le signaler si nécessaire via le formulaire de contact.

On pourrait également compléter le titre également par : « Ville / Nom … « 

C’est une demande qui revient assez régulièrement et qui est d’autant plus d’actualité avec le confinement actuel.
Comment restreindre un transporteur à un certain code postal ?

Ceci permets par exemple de créer un transporteur de clic and collect délimité à certains codes postaux.

C’est très facile à faire dans Prestashop, mais cela nécessite la création ou l’achat d’un module.

Nous allons voir comment procéder techniquement pour faire cela.
Ce tutoriel est valide à la fois pour les versions 1.6.x et 1.7.x de prestashop

Principe de fonctionnement général

Dans Prestashop les activations ou prix des transporteurs sont définis par zones géographiques :
Celles-ci sont visibles dans l’administration via « International / Zones Géographique »

Zones de livraisons

Il est ensuite possible de voir la corrélation entre les 2 lorsque nous allons éditer un transporteur.
Via « Livraison / Transporteur » , éditer un transporteur et dans l’onglet « Destination d’expéditions et coûts »
Par exemple le transporteur de la capture ci-dessous est actif uniquement pour les zones « Europe » et « Amérique du Nord »

Zones de livraison sur un transporteur

Comme le nom des zones est très explicite on peut aisément comprendre que les clients habitant en France feront automatiquement partie de la zone Europe , et c’est bien le cas dans la configuration de prestashop

 

La France est bien en zone Europe

Cependant il existe une possibilité disponible uniquement via le code qui est d’assigner automatiquement une zone à une adresse en fonction de ses paramètres.
Cette fonctionnalité est gérée via le hook actionGetIDZoneByAddressID

Mise en œuvre concrète

Maintenant que le fonctionnement global est connu c’est parti pour un exemple concret d’implémentation.
L’objectif va être le suivant :
Créer un nouveau transporteur « Clic and collect » et le rendre disponible uniquement pour les clients qui habitent dans dans le bas-rhin ( donc un code postal qui commence par 67 )

Pour commencer il faut donc créer :
– une nouvelle zone géographique « Click and Collect » en allant dans le menu « Internationnal / Zones géographique » et récupérer son identifiant technique qu’on va réutiliser plus tard
– créer un nouveau transporteur « Click and collect » qui est uniquement actif sur la zone « click and collect »

C’est parti ensuite pour la création d’un module qui va gérer le rattachement de la zone.
Nous allons l’appeler hh_clicandcollectdelivery

Pour ce module nous allons nous concentrer sur l’essentiel uniquement, toute la logique sera codée en dur pour expliquer le principe.
Le point  essentiel est l’implémentation du hook actionGetIDZoneByAddressID que je détaille ici

     /**
     * Récupération de l'identifiant de la zone
     * @see classes/Address.php:282
     * @param array $params
     * @return mixed
     */
    public function hookActionGetIDZoneByAddressID($params)
    {
	//Chargement de l'objet adresse à partir de son identifiant
	$address = new Address($params['id_address']);
 
        //Identifiant de la zone géographique clic and collect
        $id_zone = 9;
 
        //Dans mon cas je veux que la zone soit renvoyée uniquement pour les codes postaux du type
        // 67xxx (bas-rhin )    
	if (preg_match('#^67[0-9]{3}$#', $address->postcode)) {
			return $id_zone; //L'important est de retourner la zone ici
	}
 
	//Par contre ici vous avez accès à l'ensemble des champs de l'adresse
	//Du coup vous pouvez conditionner la zone à n'importe quel champ
	//Par exemple si la ville (city = 'Paris', le nom  = 'Hervé' ) ect ...
 
    }

Si on test en tant que client on peut voir que c’est bien fonctionnel :
Code postal qui commence par 67000
(Note : Comme vous le voyez les autres transporteurs ne sont pas disponibles , il faut penser à les activer également pour cette nouvelle zone )

Code postal qui commence par autre chose , seuls les autres transporteurs sont affichés.

Module basique

Voici donc le code le plus basique du module qui permets de gérer ça.

    class Hh_clicandcollectdelivery extends Module
{
 
    public function __construct()
    {
        $this->name = 'hh_clicandcollectdelivery';
        $this->tab = 'others';
        $this->version = '0.1.0';
        $this->author = 'hhennes';
        $this->bootstrap = true;
        parent::__construct();
 
        $this->displayName = $this->l('Hh Clic and collect delivery');
        $this->description = $this->l('Allow clic and collect to certain postcode');
    }
 
    /**
     * Installation du module
     * @return bool
     */
    public function install()
    {
        if (
            !parent::install()
            || !$this->registerHook('actionGetIDZoneByAddressID')
        ) {
            return false;
        }
 
        return true;
    } 
 
    /**
     * Récupération de l'identifiant de la zone
     * @see classes/Address.php:282
     * @param array $params
     * @return mixed
     */
    public function hookActionGetIDZoneByAddressID($params)
    {
	//Chargement de l'objet adresse à partir de son identifiant
	$address = new Address($params['id_address']);
 
        //Identifiant de la zone géographique clic and collect
        $id_zone = 9;
 
        //Dans mon cas je veux que la zone soit renvoyée uniquement pour les codes postaux du type
        // 67xxx (bas-rhin )    
	if (preg_match('#^67[0-9]{3}$#', $address->postcode)) {
			return $id_zone; //L'important est de retourner la zone ici
	}
 
	//Par contre ici vous avez accès à l'ensemble des champs de l'adresse
	//Du coup vous pouvez conditionner la zone à n'importe quel champ
	//Par exemple si la ville (city = 'Paris', le nom  = 'Hervé' ) ect ...
 
    }
}

Module plus complet

C’est fonctionnel mais j’en conviens ce n’est pas vraiment adapté à une utilisation directement en production.
Car un peu trop manuel, vous pouvez donc télécharger ci-dessous un module un peu plus complet qui va ajouter les fonctionnalités suivantes :

  • Création automatique de la nouvelle zone lors de l’installation du module
  • Configuration de la plage de code postal directement depuis l’administration ( via une expression régulière )

Télécharger le module complet ( et gratuit ) sur la boutique

Le but de ce module reste très basique, pour des besoins plus complet allez voir sur addons il existe pleins de modules qui gèrent très bien ce sujet, dans le cas ou il est nécessaire d’avoir plus de règles !

29 réflexions sur “Prestashop : Restreindre un transporteur par code postal”

    1. Bonjour Cédric,

      Oui c’est possible mais pas de manière très intuitive car la condition est réalisé via une expression régulière 🙂
      Vous pouvez les tester sur ce site https://regex101.com/ .
      Par exemple pour autoriser les codes postaux qui commencent par 67 ou 68 l’expression serait sous cette forme ^6[7-8][0-9]{3}$

      Cordialement,
      Hervé

      1. Bonjour merci pour la réponse, j’ai essayé de l’adapter à mon cas mais je n’y suis pas parvenu, je voudrais autoriser spécifiquement les codes postaux 33400 33170 et 33600, est-ce possible ? Merci encore pour ce super module gratuit 🙂

    1. Bonjour Felipe,

      La configuration du module semble bonne.
      Après la configuration des transporteur est l’élément principal.
      Il ne faut activer les transporteurs que pour cette zone, sinon effectivement ils seront affichés partout.

      Cordialement,
      Hervé

  1. Bonjour,

    Comment faire pour rentrer 2 codes postaux différents qui ne commencent pas par le même chiffre ?

    Je souhaite rentrer 91,92,93,94,95 donc je rentre ^9 ça fonctionne très bien, mais comment rajouter 75 en plus ?

    Merci.

      1. Merci beaucoup Hervé ça fonctionne nickel !

        Encore une question, les clients avec un code postal 91,92,93,94,95 et 75 peuvent voir le transporteur spécifique pour leur zone, mais ils ne peuvent plus voir les autres, comment faire pour qu’il puisse voir ce transporteur spécifique pour l’Ile de France, mais aussi les autres transporteurs de base pour qu’ils puissent faire un choix entre tous ?

        Merci d’avance !

        1. Bonjour,

          Il faut penser également à activer les autres transporteurs et leur définir les mêmes tarifs sur la nouvelle zone de livraison.
          Si rien n’est défini ils ne seront effectivement pas disponibles.

          Cordialement,
          Hervé

  2. Bonjour et surtout merci pour ce code très précieux.
    En effet j’ai un client qui ne veut livrer que dans certaines villes et certains codes postaux.
    Car vous le savez, certaines villes ont le même code postale ce qui complique bien la chose 😉
    Deux petites questions, (j’ai certainement pas vu) où est ce qu’on doit saisir le code que tu as mentionné plus haut ?
    Et ma deuxième question, si je prends l’exemple suivant
    le code postal : 51500 correspond aux villes suivantes : Villers Allerand, Taissy, Sillery, Rilly la montagne, Mailly en champagne
    Si je veux ne prendre en compte que le CP : 51500 et les villes : Taissy et Sillery quel serait le code ?
    C’est histoire de me mettre le pied à l’étrier après je pourrai me débrouiller 🙂

    Merci d’avance

    1. Bonjour Xavier,

      Téléchargez ou créer le module et dans la fonction hookActionGetIDZoneByAddressID il vous suffira ensuite de vérifier également la ville
      Via un code du type

      //Dans mon cas je veux que la zone soit renvoyée uniquement pour les codes postaux du type
      // 67xxx (bas-rhin )
      if (preg_match('#^67[0-9]{3}$#', $address->postcode)) {
      //Rajout de conditions supplémentaires si le code postal matche
      if ( strtolower($address->city == 'ma ville a verif') || strtolower($address->city == 'autre ville'){
      return $id_zone; //L'important est de retourner la zone ici
      }
      }

      Cordialement,
      Hervé

        1. Hmmm désolé je dois être bête mais je ne vois pas dans quel fichier je dois mettre ce code (code du module basique avec votre modif)…
          J’avais l’habitude de programmer en PHP entre autre par le passé mais j’avoue que Prestashop est un grand mystère avec d’innombrables fichiers partout :/

          Pourriez-vous m’indiquer quel fichier je dois modifier ?
          J’aurais bien installé votre module, mais si j’ai bien compris, il ne prends pas en compte les villes (comme dans mon besoin très spécifique) snif

          Merci d’avance 🙂

          1. Bonjour,

            Désolé mais je peux difficilement être plus spécifique,si vous téléchargez le module éditez le fichier hh_clicandcollectdelivery.php
            Et faites la modification demandée dedans.
            Il n’y a rien de plus à faire 😉

            Cordialement,
            Hervé

  3. Bonjour Hervé,
    merci pour ces conseils.
    Y a-t-il un moyen de ne pas passer par un module?
    si oui, comment ?
    Car il y a déjà beaucoup de modules sous PrestaShop.
    merci pour ces informations

    1. Bonjour Manu,

      Les modules sont la solution sont la seule solution pour répondre à ce besoin.
      Un module bien fait ne pose pas de problème de performances 😉
      Du coup avoir beaucoup de module n’est pas un soucis.

      Cordialement,
      Hervé

  4. Bonjour,
    Je tente de configurer votre module mais je bloque ! Un p’tit coup de pouce svp 🙂
    Je souhaite donc proposer (comme vu plus haut) le Click & Collect pour villes alentours. Lorsque je configure cela, j’ai effectivement le Click & collect proposé mais l’activation du module désactive les 2 autres possibilité de livraisons : à) savoir à domicile et en point relais.
    Je ne saisi pas trop comment pouvoit remédier à cela. Je vsouhaiterais, si cela est possible avec ce module afficher :
    – Clcik n Collect (que pour l’expression régulière)
    – A domicile (tout le temps)
    -En point relais (tout le temps)
    Je vous remercie par avance pour votre aide
    Aurel

    1. Bonjour,

      Comme précisé en fin d’article, pour que vos autres transporteurs soit disponibles il faut également les activer et leur définir des tarifs sur la zone « Clic and collect »
      C’est juste de la configuration 🙂

      Cordialement,
      Hervé

      1. Merci pour votre retour rapide….
        J’ai eu un peu de mal à comprendre la config. Du coup j’ai dans chaque transporteur indiqué dans la plage : « zone clic and collect » les mêmes montant que dans la plage « France » etc etc…
        Cela semble fonctionner correctement.
        Cdt
        Aurel

  5. Bonjour Monsieur Hennes,
    Merci pour cet excellent module.
    Pourriez-vous me dire comment faire pour afficher 2 séries de codes postaux à 2 zones différentes ?
    Exemple :
    – zone 1 = ^(10101|10102|10103|)*$
    – zone 2 = ^(40803|40901|40902)*$

    Merci

  6. Bonjour,
    Je viens de configurer votre module en tapant les expressions régulières comme indiqué dans les commentaires.
    Cependant, cela ne fonctionne pas pour les CP sur 4 digit comme la Suisse.
    Exemple pour Lausanne : 1003, 1004, 1005, 1006, 1007 et Pully 1009
    Je traduit par ^(1003|1004|1005|1006|1007|1009)*$ et le module m’indique : Il n’y a malheureusement aucun transporteur pouvant livrer à votre adresse.
    Vous pouvez éclairer ma lanterne ?

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *