Au-delà de QWeb : générer vos documents Odoo avec Carbone
Odoo génère nativement ses documents (devis, factures, bons de livraison...) avec QWeb, son propre moteur de templating basé sur du HTML/XML, converti en PDF. C'est efficace pour un usage standard, mais la personnalisation reste du ressort d'un développeur :
| QWeb (natif) | Carbone | |
|---|---|---|
| Format de sortie | PDF uniquement (Excel/Word nécessitent un module tiers) | DOCX, XLSX, PDF, ODT, PPTX depuis un seul template |
| Édition du template | XML/HTML, Mode développeur ou Odoo Studio (payant) | Fichier Word/Excel, modifiable par une personne non technique |
| QR code / code-barres | Possible via un contrôleur interne, à appeler en XML avec une URL construite à la main | Un seul tag (:barcode), une centaine de formats, sans XML |
| Sous-totaux / agrégats | Champ calculé Python côté modèle | Directement dans le tag (:aggSum, :aggCount...) |
| Déployer une modification | Mise à jour du module, redéploiement | Remplacer le fichier Word/Excel dans la config du rapport |
Le module Carbone pour Odoo déplace donc la personnalisation des documents des mains d'un développeur vers celles des équipes métier. Dans cet article, on part d'un cas concret — un bon de livraison généré depuis un transfert par lot (Batch Transfer) regroupant plusieurs bons de livraison — et on construit le template de A à Z, jusqu'à l'ajout d'un QR code et d'un code-barres.
Le scénario
On utilise un transfert par lot Odoo : plusieurs bons de livraison individuels (un par entrepôt ou par expédition) regroupés sous un même envoi. C'est une fonctionnalité native d'Odoo (Inventaire > Transferts par lots), pertinente dès qu'un client reçoit sa commande en plusieurs colis.
Sur ce document, on veut :
- Lister tous les produits, tous transferts confondus, avec le BL d'origine de chacun
- Détecter automatiquement une livraison partielle (reliquat) sans aucune formule à maintenir
- Ajouter un QR code de suivi et un code-barres scannable en entrepôt
1. Installer le module
Depuis le menu Apps d'Odoo, recherchez "Carbone" et cliquez sur Installer. Une fois actif, un nouveau menu de configuration apparaît, permettant d'associer n'importe quel rapport Odoo (bon de livraison, transfert par lot, facture...) à un template Carbone au format DOCX ou XLSX — à la place du rapport QWeb par défaut.

2. Préparer un transfert par lot de test
Avant de construire le template, on prépare un cas réel dans Odoo :
Inventaire > Configuration > Paramètres→ vérifier que "Transferts par lots" est activé.Inventaire > Transferts > Livraisons→ créer deux bons de livraison pour un même client, chacun avec ses propres lignes de produits.- Sur l'un des deux, indiquer une quantité faite inférieure à la quantité demandée sur une ligne (par exemple 7 au lieu de 10) — c'est ce qui va nous permettre de tester la détection automatique du reliquat.
Inventaire > Transferts par lots→ créer un lot et y rattacher les deux bons de livraison.

3. Associer le template Carbone au rapport
Le template complet utilisé dans cet article est téléchargeable ici :
Vous pouvez l'utiliser tel quel pour suivre le tutoriel, ou comme point de départ pour votre propre document — c'est un fichier Word ordinaire, chaque élément (logo, colonnes, mentions) se modifie directement dans Word.
Côté configuration, une fois le module installé :
- Renseignez votre clé API Carbone dans les paramètres du module (créez un compte sur carbone.io pour l'obtenir — ou pointez vers votre instance On-Premise).
- Ouvrez la configuration des rapports Carbone et créez une entrée pour le modèle Transfert par lot (
stock.picking.batch). - Téléversez le fichier
.docxcomme template associé à ce rapport, et choisissez le format de sortie souhaité (PDF pour l'impression, ou DOCX si le document doit rester retouchable). - Cliquez sur "Ajouter au menu Impression" : c'est ce qui rend le rapport visible dans le menu Imprimer du transfert par lot, à côté des rapports natifs.
À partir de là, chaque impression de transfert par lot passera par Carbone plutôt que par le rendu QWeb natif. Pour ajuster le document plus tard, il suffira de remplacer le fichier téléversé — sans redémarrage, sans mise à jour de module.

4. Comprendre et construire le template Word
Le principe de Carbone tient en une phrase : le template est un document Word ordinaire, dans lequel on insère des tags entre accolades ({d.name}, {d.move_ids[i].product_id}...) là où les données doivent apparaître. À la génération, Carbone fusionne le JSON envoyé par Odoo avec le template : chaque tag est remplacé par sa valeur, les lignes marquées [i] sont répétées pour chaque élément d'une liste, et les blocs conditionnels s'affichent ou disparaissent selon les données. La mise en forme (polices, tableaux, couleurs, en-têtes) reste celle du document Word — Carbone ne touche qu'au contenu.

Voyons chaque partie du document.
En-tête société + QR code
En haut du document, un bloc classique (nom de société, adresse) et un QR code de suivi. Le QR code est une image "placeholder" insérée dans Word, dont le texte alternatif contient le tag Carbone :
{d.name:prepend('https://tracking.exemple-transport.fr/bl/'):barcode(qrcode,eclevel:M)}
Carbone remplace l'image par le QR code généré, aux dimensions du placeholder défini dans le template.
Un code-barres pour le scan en entrepôt
Même principe, avec un code-barres Code128 sous le titre, en alt-text d'une seconde image :
{d.name:barcode(code128,includetext:true,textsize:10)}En-tête du document
Numéro de lot, date, type d'opération et liste des transferts inclus — des champs simples à insérer, chacun correspondant à une information affichée telle quelle sur le transfert dans Odoo :
N° de lot : {d.name}
Date : {d.scheduled_date:formatD('DD/MM/YYYY')}
Type d'opération : {d.picking_type_id}
Transferts inclus : {d.picking_ids:arrayJoin(', ')}arrayJoin transforme directement la liste des bons de livraison inclus dans le lot en une ligne lisible séparée par des virgules — pratique pour ne pas avoir à écrire de boucle pour un simple résumé.
La liste des produits, tous transferts confondus
Chaque ligne de produit d'un mouvement de stock (stock.move) est parcourue en boucle, avec le bon de livraison d'origine, la quantité demandée et la quantité disponible :
{d.move_ids[i].picking_id} {d.move_ids[i].product_id} {d.move_ids[i].product_uom_qty} {d.move_ids[i].quantity} [statut]
{d.move_ids[i+1]}Détecter un reliquat, en un seul tag
{d.move_ids[i].product_uom_qty:sub(.quantity):ifGT(0):show('⚠ reliquat'):elseShow('OK')}Un seul formateur chaîné : on soustrait la quantité disponible de la quantité demandée, puis on affiche la mention seulement si le résultat est positif. Pas besoin de champ intermédiaire ni de logique côté Odoo — c'est exactement le cas qu'on a préparé à l'étape 2.
Totaux
Nombre de transferts : {d.picking_ids:len}
Quantité totale disponible : {d.move_ids[].quantity:aggSum:formatN(2)}:len compte le nombre de bons de livraison inclus dans le lot, et :aggSum agrège une valeur sur l'ensemble des lignes, sans avoir à écrire de boucle explicite pour un total.
5. Générer le document
Retour sur le transfert par lot créé à l'étape 2 : un clic sur Imprimer génère désormais le bon de livraison au format PDF (ou Word si le document doit rester retouchable), avec :
- la ligne en reliquat automatiquement signalée,
- le QR code et le code-barres générés à la volée,
- une mise en page entièrement modifiable par les équipes métier, sans ticket ni ligne de code.

Pour aller plus loin
Le bon de livraison n'est qu'un exemple : la même approche s'applique à tous les documents générés par Odoo — devis, factures, contrats, fiches de paie, étiquettes, rapports d'inventaire... — et à tous les formats de sortie (PDF, Word, Excel, PowerPoint, ODT). Un seul template suffit par type de document, quel que soit le format demandé à la génération.
- Documentation complète des tags et formatters Carbone : https://carbone.io/documentation/design/overview/getting-started.html
- Module Carbone sur l'Odoo Apps Store : https://apps.odoo.com/apps/modules/19.0/report_carbone
D'autres formateurs Carbone sont pertinents pour aller plus loin sur ce type de document :
:color: appliquer une couleur dynamique à une cellule ou une ligne selon une condition — par exemple une ligne en reliquat mise en évidence en rouge, plutôt qu'une simple mention texte.:html: si votre bon de livraison intègre un champ de notes ou d'instructions saisi en texte enrichi dans Odoo, ce formateur l'injecte tel quel (gras, listes...) dans le document généré.
Enfin, Carbone existe aussi en version On-Premise : le moteur de rendu tourne directement dans votre infrastructure plutôt que via l'API Cloud, un point souvent déterminant pour les entreprises soumises à des contraintes de résidence ou de confidentialité des données (secteur public, santé, finance...). Plus d'info : https://carbone.io/documentation/developer/on-premise-installation/introduction.html