Sur Odoo 19, il existe un module OCA pour DHL Parcel et aucun module OCA pour GLS. delivery_dhl_parcel est publié dans la branche 19.0 de OCA/l10n-spain, version 19.0.1.0.2. delivery_gls_asm va de la 12.0 à la 18.0 et n'est pas migré. Si vous comptiez passer à Odoo 19 et continuer à sortir des étiquettes GLS depuis le bon de livraison, c'est le premier chiffre à regarder.
Vérifiez par vous-même : demandez le manifeste de chaque branche et regardez le code HTTP : OCA/l10n-spain/19.0/delivery_gls_asm/__manifest__.py renvoie 404 ; la même route dans 18.0 renvoie 200 ; et celle de delivery_dhl_parcel en 19.0, 200 également.
GLS ou DHL : pourquoi ce n'est pas la même décision
GLS España, c'est du colis : petits paquets et réseau d'agences. L'intégration se gagne ou se perd sur l'étiquette et sur le statut, et sa raison d'être est le volume : cent étiquettes par jour que personne ne veut saisir à la main.
DHL dans Odoo n'est pas une marque : ce sont deux produits avec des API différentes. Le module OCA le signale dans son readme/DESCRIPTION.md : « No es válido para otras integraciones de DHL como el Express, que usan otras APIs ». Et la documentation de Odoo 19, dans son tableau de connecteurs, liste DHL Express et conclut : « Other services from DHL are not supported ».
La conséquence : si votre contrat est DHL Express, le module OCA ne vous sert à rien et le connecteur natif n'est pas fourni dans Community : dans addons/ du dépôt public odoo/odoo, en 17, 18 et 19, le seul module de transporteur est delivery_mondialrelay. Si c'est DHL Parcel España, le module OCA est la voie à suivre. C'est une question à poser d'abord à votre commercial DHL, avant votre intégrateur.
| DHL Parcel | GLS | |
|---|---|---|
| Nom technique | delivery_dhl_parcel | delivery_gls_asm |
| Branches publiées | 13.0 à 19.0 (sans 16.0) | 12.0 à 18.0. Pas de 19.0 |
| Enlèvements | Non | Oui, avec des statuts propres |
| Champs douaniers | Ils existent et sont vides | Ils n'existent pas |
Quel module OCA existe vraiment, et dans quel dépôt
La confusion commence au mauvais endroit : vous cherchez « OCA DHL Odoo » et vous atterrissez sur OCA/delivery-carrier, le dépôt de logistique de l'OCA. Il n'y est pas : aucun module DHL dans aucune branche de la 12.0 à la 19.0, et de GLS il ne reste qu'un dossier fantôme en 16.0 avec un seul fichier, static/description/index.html. Ni manifeste ni code.
Les deux modules vivants sont dans OCA/l10n-spain, et il faut ajuster les attentes : dans la branche 19.0 de OCA/delivery-carrier, le seul module qui appelle l'API d'un transporteur est delivery_correos_express ; le reste est de l'infrastructure. Et dans la 19.0 de OCA/l10n-spain, il y a trois transporteurs : delivery_dhl_parcel, delivery_mrw et delivery_seur_atlas.
Ce que couvre chaque module, lu dans son code
Chez DHL Parcel, tout sort d'une seule méthode, _prepare_dhl_parcel_shipping : un dictionnaire plat qui se lit en deux minutes.
- Étiquette en PDF, ZPL ou EPL jointe au bon de livraison, avec l'AWB et le suivi.
- Contre-remboursement à partir du total de la commande, avec répartition des frais selon l'incoterm.
- Assurance optionnelle, retours, clôture de journée par assistant et livraison avant 13 h 30.
- Trois limites écrites dans le module : il ne cote pas (son
ROADMAPindique que les envois « siempre se cotizan a 0 »), nom et adresse sont tronqués à 40 caractères, et le poids minimum transmis est 1 kg même si le colis pèse 200 g.
L'équivalent chez GLS est _prepare_gls_asm_shipping, plus long parce que l'API exige l'expéditeur et le destinataire complets à chaque appel :
- Service et créneau horaire par mode de livraison, étiquette PDF et étiquette de retour.
- Suivi avec historique complet et preuve de livraison jointe au bon de livraison.
- Enlèvements comme flux à part entière : douze codes de service marqués comme enlèvement, avec bouton et statuts distincts.
- Annulation avec garde-fou : il actualise le statut et n'annule que si l'envoi est encore « enregistré chez le transporteur » ; sinon il lève une erreur et vous renvoie vers GLS par e-mail.
- Ses limites : la référence ne peut pas dépasser 15 caractères (GLS tronque et les références entrent en collision), il ne cote pas non plus, et le pays de l'expéditeur est fixé sur l'Espagne dans le code, avec le commentaire always 34=Spain.
Douane et export : les champs que l'OCA laisse vides
Le trou a une forme précise : Odoo fournit les champs et les modules OCA ne les utilisent pas. L'information ne manque pas : elle ne part simplement pas. Ce qu'Odoo 19 a bel et bien, dans stock_delivery :
product.template.hs_code, libellé « HS Code », avec l'aide « Standardized code for international shipping and goods declaration ». C'est la position tarifaire.product.template.country_of_origin, libellé « Origin of Goods », relation versres.country.- Une classe
DeliveryCommodity(docstring littérale : « Commodities information are needed for Commercial invoices with each provider ») avec produit, quantité, valeur monétaire et pays d'origine, plus deux méthodes qui la construisent. Si le produit n'a pas de pays d'origine, on utilise celui de l'entrepôt expéditeur.
Ce que les modules OCA en font : rien. Chercher hs_code, customs, aduana, arancel, incoterm ou country_of_origin dans tout le module GLS renvoie zéro résultat. Dans celui de DHL Parcel, ils apparaissent, et c'est là que c'est intéressant, parce qu'ils apparaissent vides :
"Incoterms": self.dhl_parcel_incoterm, # CPT paid, EXW owed
"GoodsDescription": "", # [optional]
"CustomsValue": "", # [optional]
"CustomsCurrency": "", # [optional]delivery_dhl_parcel · models/delivery_carrier.py · _prepare_dhl_parcel_shipping
Trois champs prévus par l'API et les trois envoyés vides : valeur déclarée, devise et description de la marchandise. L'incoterm, lui, part, mais regardez d'où il vient (de self, du mode de livraison, pas du bon de livraison) et dans le code il n'y a que deux valeurs, CPT et EXW : une seule fixe pour tout ce transporteur. Chez GLS, l'équivalent est le champ declarado, qui part vide lui aussi. Et aucun des quatre transporteurs restants en 19.0 dans ces deux dépôts (DHL Parcel, MRW, SEUR et Correos Express) ne mentionne DeliveryCommodity, hs_code ni country_of_origin : la tuyauterie qu'Odoo a laissée prête n'est pas raccordée.
Ce qui vous manque le jour où vous exportez :
- Position tarifaire et pays d'origine, par ligne. Ils existent sur le produit, ils ne partent pas vers le transporteur.
- Valeur déclarée et sa devise. Prévue dans l'API de DHL Parcel. Envoyée vide.
- Description de la marchandise. Champ prévu. Envoyé vide.
- Document commercial. Une proforma générée depuis le bon de livraison et jointe à l'envoi. N'existe dans aucun des deux.
- Incoterm par envoi. Existe par transporteur, avec deux valeurs.
Ce n'est pas un oubli de ces deux modules : c'est la règle. delivery_schenker envoie "customsClearance": False avec le commentaire « Customs Clearance not supported for now as it needs a full customs implementation », et son ROADMAP range le dédouanement parmi ce qui n'est pas pris en charge ; ce module va jusqu'à la 18.0 et n'est pas non plus en 19.0. Quand un module OCA gère vraiment la douane, il ne le fait pas avec un champ : il ajoute un modèle propre avec position tarifaire et pays d'origine par ligne de marchandise. C'est la vraie mesure du travail.
Que se passe-t-il quand un de ces champs manque
Rien, et c'est bien le problème. Les champs sont optionnels dans l'API : le transporteur accepte l'expédition, renvoie le suivi et l'étiquette sort de l'imprimante. Dans Odoo, le bon de livraison est validé, tout au vert. L'échec survient ensuite, au dédouanement à destination : le colis s'arrête et quelqu'un de votre entreprise saisit à la main la position tarifaire, la description et la valeur que le transporteur réclame. Silencieux dans Odoo, bruyant au service client.
Il faut être précis sur les cas concernés. Pas de Barcelone à Munich : l'UE est un marché intérieur et il n'y a pas de frontière douanière. Cela s'applique à la sortie du territoire (Royaume-Uni, Suisse, Norvège, Andorre, Turquie) et, sans quitter l'Espagne, aux Canaries, à Ceuta et à Melilla. La Ley 37/1992 del IVA le dit à son article 3 : elle exclut Ceuta et Melilla « en cuanto territorios no comprendidos en la Unión Aduanera » et les Canaries « en cuanto territorios excluidos de la armonización de los impuestos sobre el volumen de negocios ».
Et n'attendez pas non plus de seuil en dessous duquel la formalité disparaît. Côté importation, que la norme espagnole détaille, le Real Decreto-ley 7/2021 (BOE-A-2021-6872) a transposé le paquet TVA du commerce électronique avec effet au 1er juillet 2021 : il a supprimé l'exonération des importations de biens de faible valeur « hasta los 22 euros de valor global de la mercancía », et explique que jusqu'à 150 euros de valeur intrinsèque « se aplica la franquicia aduanera por lo que no se exige una declaración completa ante la Aduana en el momento de la importación ». Lisez-le à l'envers : sous 150 euros, la déclaration est plus courte, pas nulle. Et celui qui doit la remplir a toujours besoin de la description, de la valeur et de la position tarifaire : précisément les champs que le module envoie vides.
Quand l'OCA suffit et quand il vous faut autre chose
Le module OCA est la bonne réponse si vous expédiez dans l'UE sans franchir de frontière douanière, si vous voulez arrêter de saisir des adresses plutôt qu'obtenir un tarif exact dans la commande, et si vous êtes sur Odoo 18 ou antérieur : ou sur la 19 avec DHL Parcel.
Il vous faut autre chose si :
- Vous exportez régulièrement, ou vous expédiez vers les Canaries, Ceuta ou Melilla. Le travail n'est pas « installer le module » : c'est renseigner
hs_codeet pays d'origine, étendre le payload et générer le document commercial. - Vous êtes sur Odoo 19 avec GLS : il n'y a aujourd'hui aucun module, donc soit on migre
delivery_gls_asm, soit on change de voie. - Votre contrat est DHL Express, ou vous expédiez avec GLS depuis l'extérieur de l'Espagne.
Une note de méthode pour finir : étendre un module OCA est la voie économique quand le trou est un champ, et cesse de l'être quand le trou est un document. Mettre la position tarifaire et le pays d'origine dans le payload, c'est hériter de _prepare_dhl_parcel_shipping et ajouter vingt lignes. Générer une proforma qui concorde avec la comptabilité, c'est déjà un module, avec modèle, tests et maintenance sur trois versions.
Questions fréquentes
Existe-t-il un module OCA DHL pour Odoo 19 ?
Oui : delivery_dhl_parcel, dans OCA/l10n-spain, version 19.0.1.0.2. Il n'est pas dans OCA/delivery-carrier, où presque tout le monde le cherche, et il ne sert que pour l'API de DHL Parcel : pas pour DHL Express.
Et pour GLS ?
Sur Odoo 19, non. delivery_gls_asm est publié de la branche 12.0 à la 18.0 dans OCA/l10n-spain ; en 19.0, il n'existe pas.
Si la valeur déclarée manque, Odoo renvoie-t-il une erreur ?
Non : elle est optionnelle dans l'API. L'envoi est enregistré, l'étiquette est générée et le bon de livraison est validé ; le problème apparaît au dédouanement à destination, déjà hors d'Odoo.
Pour aller plus loin
Ce que nous faisons à ce sujet
Vous exportez et le module ne suffit pas ?
Nous examinons votre contrat, l'API qui vous a été fournie et le catalogue, et nous vous disons si on règle cela en étendant le module OCA ou s'il faut un développement sur mesure.

