Personnalisation des factures dans PrestaShop : modèles PDF et exigences légales
Les chemins de fichiers et les menus du back-office ci-dessous s'appliquent à PrestaShop 1.6, 1.7, 8 et 9 (les différences avec la 1.6 sont signalées au fil du texte). Les références juridiques propres à chaque pays, Code de commerce français, UStG/GoBD allemand, seuil polonais du paiement fractionné, etc., étaient exactes au moment de la rédaction, mais la législation évolue ; considérez-les comme des repères et faites confirmer les obligations actuelles de votre marché par un expert-comptable local. Ceci ne constitue pas un conseil juridique ou fiscal, et l'installation d'un module ne rend pas, à elle seule, vos factures conformes.
Vous pouvez concevoir la majeure partie de votre boutique comme vous l'entendez. La facture, non. C'est un document juridiquement opposable, et dès qu'un client la transmet à son comptable, ou qu'un contrôleur fiscal l'extrait lors d'un audit, chaque champ manquant devient votre problème, pas le sien. Une facture allemande sans date de livraison, une facture française sans indemnité forfaitaire de recouvrement, une facture polonaise de plus de 15 000 PLN pour les biens ou services figurant sur la liste prévue par la réglementation, sans mention du paiement fractionné : chacun de ces défauts peut entraîner le rejet d'une déduction de TVA ou une pénalité. Le piège, c'est que PrestaShop génère les factures automatiquement à partir d'un modèle PDF fixe, conçu pour être correct de manière générique, pas pour votre juridiction précise. Ce guide traite de la partie que vous contrôlez réellement : ce que la loi exige sur la facture imprimée dans les principaux marchés de l'UE, et la manière exacte de modifier le modèle PDF de PrestaShop pour ajouter ces champs sans perdre votre travail à la prochaine mise à jour.
Précisons rapidement le périmètre, car ce sujet touche à des domaines voisins. Cet article porte sur le document PDF, sa mise en page, ses champs, sa conformité. Il ne traite pas de la numérotation des factures (un sujet à part entière, voir la personnalisation des numéros de facture et de commande), ni des formats structurés de facturation électronique comme le SDI italien ou Factur-X en France (couverts dans la facturation électronique en Europe), ni de la configuration des taux de TVA eux-mêmes (configuration des taxes dans PrestaShop). Ici, nous restons sur le document.
Ce que PrestaShop fait réellement lorsqu'il crée une facture
Comprendre le mécanisme vous évite d'abord de modifier le mauvais fichier. Lorsqu'une commande atteint un statut dont le drapeau « Facture » est activé, PrestaShop crée une ligne dans la base de données order_invoice et attribue le numéro séquentiel. Les statuts qui génèrent une facture ne sont pas figés, tout dépend de ce drapeau « Facture » propre à chaque statut, configuré dans Paramètres de la boutique → Paramètres des commandes → Statuts, et les valeurs par défaut varient selon la version et la configuration de PrestaShop. Ne partez pas du principe qu'un statut donné facture par défaut : ouvrez votre propre liste de statuts et vérifiez ceux pour lesquels le drapeau « Facture » est activé. Le PDF lui-même n'est pas stocké. Il est généré à la demande chaque fois que quelqu'un clique sur le téléchargement, par une chaîne de trois éléments :
- La classe PHP
classes/pdf/HTMLTemplateInvoice.php, rassemble les données de commande, d'adresse, de taxe et de produits, puis les expose au modèle. C'est là que vous intervenez pour ajouter un champ que PrestaShop ne transmet pas déjà. - Le modèle Smarty
pdf/invoice.tpl, la mise en page et le balisage réels du document. C'est ici que vous changez ce qui apparaît et à quel endroit. - Le modèle de style
pdf/invoice.style-tab.tpl, le CSS. TCPDF (la bibliothèque qui transforme le HTML en PDF) ne prend en charge qu'un sous-ensemble limité de CSS : attendez-vous donc à des tableaux et à des styles en ligne, pas à du flexbox.
Et alors ? Cette conception a deux conséquences pratiques. Premièrement, comme le PDF est régénéré à partir des données en direct, une facture émise en mars dernier changera silencieusement si vous modifiez ensuite le modèle ou les données de la commande, exactement la raison pour laquelle l'archivage d'une copie figée est important (nous y revenons plus bas). Deuxièmement, la séparation entre la classe PHP et le .tpl vous indique quel fichier modifier : si la donnée existe déjà dans la commande, vous ne modifiez que le modèle ; si vous avez besoin d'une donnée que PrestaShop ne charge jamais, vous modifiez aussi la classe.
Modifier le modèle sans se faire écraser à la mise à jour

L'erreur la plus fréquente consiste à modifier directement les fichiers du cœur, la prochaine mise à jour de PrestaShop, ou la prochaine restauration d'une installation propre, efface vos champs légalement requis sans prévenir. Il existe deux voies sûres, qui s'appliquent à des fichiers différents.
Les fichiers de modèle (.tpl) se surchargent proprement en les copiant dans votre thème actif. PrestaShop cherche dans le répertoire pdf/ du thème avant de revenir au dossier pdf/ du cœur :
- Copiez
pdf/invoice.tplversthemes/YOUR_THEME/pdf/invoice.tplet modifiez la copie. - Le même principe fonctionne pour
invoice.style-tab.tpl,order-slip.tpl(le modèle d'avoir / note de crédit) etdelivery-slip.tpl. - Rien dans le cœur n'est touché, donc les mises à jour laissent votre version en place, mais vous devez tout de même revérifier la copie après un changement majeur de version, au cas où le modèle du cœur aurait gagné des champs que vous souhaiteriez récupérer.
La classe PHP, elle, utilise le système d'override de PrestaShop. Créez override/classes/pdf/HTMLTemplateInvoice.php en étendant la classe du cœur, puis supprimez la carte des classes compilée pour que PrestaShop la reconstruise :
- En 1.7/8/9, le fichier de cache est
var/cache/prod/class_index.php(etvar/cache/dev/class_index.phpsi vous êtes en mode dev). Sur les anciennes boutiques 1.6, il s'agit decache/class_index.php. - Surchargez
getContent()pour assigner des variables Smarty supplémentaires, puis lisez-les dans leinvoice.tplde votre thème.
Un exemple minimal rend la voie du modèle plus concrète. Si la donnée existe déjà dans la commande. Le numéro de TVA du client sur l'adresse est le cas le plus courant, la modification se limite au modèle. Copiez le fichier du cœur dans votre thème et ajoutez le champ à l'endroit où vous voulez l'imprimer :
# Copy the core template into your active theme (PS 1.7/8/9)
cp pdf/invoice.tpl themes/YOUR_THEME/pdf/invoice.tpl
Ensuite, dans ce invoice.tpl copié, affichez le numéro de TVA de l'acheteur près du bloc d'adresse, avec une condition pour ne l'afficher que s'il existe :
{if $order->id_address_invoice}
{assign var=invoiceAddress value=Address::initialize($order->id_address_invoice)}
{if $invoiceAddress->vat_number}
<p>{l s='VAT number:' pdf='true'} {$invoiceAddress->vat_number}</p>
{/if}
{/if}
Pour un champ que PrestaShop ne charge jamais (une date de livraison extraite de order_history, un IBAN/BIC bancaire, une référence de bon de commande), récupérez la donnée dans l'override de HTMLTemplateInvoice::getContent() et assignez-la à Smarty, puis affichez la variable dans ce même modèle, gardez la collecte des données en PHP et le balisage dans le .tpl, jamais de SQL dans le modèle. Régénérez toujours une vraie facture et confirmez que le champ s'affiche avant de vous y fier.
Conservez une copie des deux fichiers en dehors de la boutique. Les mises à jour de thème et les actions agressives de type « réinitialiser le thème » peuvent supprimer l'override pdf/, et un module tiers qui embarque son propre override peut entrer en conflit avec le vôtre, traitez donc vos modèles personnalisés comme du code source versionné, pas comme des modifications en production que vous ne reverrez jamais.
Les champs légaux attendus par chaque marché sur le document
Voici ce qui doit apparaître sur la facture imprimée dans les marchés où vendent le plus souvent les marchands PrestaShop. Il s'agit ici de la vue mise en page et champs, les mécanismes de taux de TVA qui se trouvent derrière ces chiffres sont traités dans la TVA dans l'UE : OSS, IOSS, et la question de l'affichage HT ou TTC relève de règles distinctes dans les règles d'affichage des prix en Europe. Faites toujours confirmer par un expert-comptable local ; la législation change.
| Marché | Champs sur facture que la facture par défaut de PrestaShop oublie souvent | Base légale |
|---|---|---|
| France (Facture) | SIREN/SIRET, ville d'immatriculation au RCS, forme juridique & capital social, taux des pénalités de retard et indemnité forfaitaire de recouvrement de 40 EUR pour le B2B | Code de commerce, Art. L441-9 |
| Allemagne (Rechnung) | Date de livraison / de prestation (distincte de la date de facture, le champ le plus souvent oublié), Steuernummer ou USt-IdNr, et la mention Kleinunternehmer (§19 UStG) en cas d'exonération de TVA | UStG §14 / §14a |
| Italie (Fattura) | Codice Fiscale / Partita IVA des deux parties ; le B2B est désormais exclusivement électronique via SDI, donc le PDF sert surtout au B2C et à l'archivage | Fatturazione elettronica (SDI) |
| Espagne (Factura) | NIF/CIF, identifiant de série de facture et ligne de surtaxe Recargo de equivalencia pour les revendeurs soumis à ce régime | RD 1619/2012 |
| Pologne (Faktura) | NIP des deux parties en B2B, et la mention "Mechanizm podzielonej płatności" (paiement fractionné) sur les factures de plus de 15 000 PLN pour les biens/services listés | Ustawa o VAT |
Le schéma est le même partout : PrestaShop imprime correctement les noms et adresses du vendeur et de l'acheteur, les lignes produit et le détail de TVA. Ce qu'il omet régulièrement, ce sont les mentions légales propres à chaque pays, la date de livraison allemande, la clause française de pénalités, la mention polonaise du paiement fractionné. Ce sont ces éléments que vous ajoutez dans le modèle.
D'où vient réellement chaque champ manquant
Avant de commencer à coder, deux de ces mentions n'exigent aucune intervention dans le modèle, PrestaShop dispose déjà d'un emplacement intégré pour elles :
- Le texte légal statique (conditions de paiement, clause française de pénalités, mention fixe d'exonération de TVA) se place dans les champs Texte libre légal et Texte de pied de page sous Commandes → Factures. Ils s'affichent sur chaque facture sans code. Si votre seul manque est un bloc constant de mentions légales, vous avez peut-être terminé ici.
- Les champs dynamiques par facture (date de livraison allemande, référence de bon de commande B2B, IBAN/BIC pour les commandes par virement bancaire) ne sont pas constants, donc ils relèvent de la méthode par modèle ci-dessous.
Pour les champs dynamiques, voici où se trouvent les données afin que votre override puisse les récupérer :
- Date de livraison, le champ
delivery_datede la commande, ou la date à laquelle la commande est passée dans un statut expédié/livré depuisorder_history. Transmettez-la au modèle dans votre overrideHTMLTemplateInvoice.php. - Numéro de TVA du client, stocké sur l'adresse (
address.vat_number), pas sur le client. PrestaShop expose déjà l'adresse, c'est donc souvent une modification limitée au modèle. - Coordonnées bancaires (IBAN/BIC), elles se trouvent dans la configuration du module de paiement Virement bancaire, pas dans la commande ; l'approche la plus propre consiste à lire la configuration du module dans votre override et à l'afficher uniquement lorsque le moyen de paiement de la commande était le virement bancaire.
- Référence de commande B2B, si vous collectez un numéro de bon de commande client, faites-le remonter depuis la commande et affichez-le près de l'en-tête, là où les comptables s'attendent à le trouver.
Avoirs et bons de livraison : même mécanisme, documents distincts
Les remboursements et les expéditions produisent leurs propres PDF, construits et personnalisés de la même manière, mais ce sont des documents juridiquement distincts, donc ne supposez pas qu'une modification de facture se reporte automatiquement.
- Les avoirs (notes de crédit / avoirs / Gutschriften) sont des documents légaux à part entière. Ils ont besoin de leur propre numérotation séquentielle, séparée des factures, d'une référence au numéro de facture d'origine et des montants remboursés avec le détail de TVA. PrestaShop appelle ce document "order slip" en interne ; le modèle à personnaliser est donc
themes/YOUR_THEME/pdf/order-slip.tpl(classeHTMLTemplateOrderSlip), même s'il s'imprime avec un intitulé "Credit slip". - Les bons de livraison ne portent aucun prix. Ce sont des documents d'entrepôt et de preuve de livraison. Personnalisez-les via
themes/YOUR_THEME/pdf/delivery-slip.tpl. Si vous ajoutez la date de livraison allemande aux factures, le bon de livraison est souvent l'endroit d'où provient la date sous-jacente ; il vaut donc la peine d'aligner les deux.
Le piège de l'archivage que personne ne remarque avant un audit
C'est celui qui fait mal discrètement. Comme PrestaShop régénère chaque PDF depuis la base de données au moment du téléchargement, une facture n'est jamais figée. Modifiez votre modèle pour ajouter la date de livraison, et toutes les factures historiques récupèrent silencieusement ce champ, y compris celles émises avant que vous n'y soyez tenu. Changez un nom de produit ou un paramètre de taxe, et les factures du trimestre dernier se regénèrent différemment. Au quotidien, cela paraît sans conséquence. Pour la conformité, c'est une vraie exposition : la France impose généralement de conserver les factures pendant 10 ans, tandis que l'Allemagne impose généralement de conserver les copies de factures pendant huit ans ; confirmez les exigences de conservation et d'intégrité applicables, notamment les règles GoBD allemandes, auprès de votre conseiller fiscal.
La solution consiste à capturer une copie figée de chaque facture au moment de son émission, plutôt que de s'appuyer sur une régénération. Concrètement :
- Archivez au moment où la facture est créée et numérotée pour la première fois, pas à chaque rendu PDF. Déclenchez votre archivage depuis la transition de statut de commande qui génère la facture (ou depuis un hook/service dédié à la création de facture), afin de capturer le document une seule fois, lorsque son numéro est attribué. S'accrocher au flux de rendu PDF (par exemple
actionPDFInvoiceRender) est le mauvais point d'ancrage : il se déclenche au téléchargement et à la régénération, peut donc manquer les factures qui ne sont jamais retéléchargées et peut écraser votre archive avec une sortie ultérieure régénérée. Écrivez ce PDF exact du premier rendu sur disque ou dans un stockage objet. - Stockez-le dans un emplacement immuable, un stockage cloud avec une politique write-once-read-many (WORM) vous donne à la fois la durabilité et l'inaltérabilité attendues par le GoBD et la loi française.
- Ne laissez jamais la copie archivée être celle qui se régénère ; tout l'intérêt est qu'elle ne puisse plus changer après émission.
Les problèmes qui génèrent vraiment des tickets support
Quand les factures se comportent mal dans PrestaShop, c'est presque toujours l'un de ces cas, et la correction se trouve rarement dans le modèle :
- Mauvaise adresse de société sur la facture. Elle est construite à partir du nom et de l'adresse de la boutique (
PS_SHOP_NAME,PS_SHOP_ADDR1et les autres), que vous définissez dans le bloc d'adresse de la boutique sous Paramètres de la boutique → Contact, pas à partir de vos coordonnées générales de boutique/e-mail. Mettez-la à jour à cet endroit. - Numéro de TVA du vendeur manquant. Il n'y a pas de surprise ici : la facture par défaut de PrestaShop n'imprime aucun numéro de TVA/taxe vendeur. Le bloc vendeur est construit uniquement à partir du nom et de l'adresse de la boutique (les valeurs
PS_SHOP_*), sans champ TVA, et International → Taxes configure uniquement les taux et règles de taxe, pas un identifiant vendeur. Pour faire apparaître votre numéro de TVA, ajoutez-le comme texte constant dans les champs Texte libre légal / Texte de pied de page sous Commandes → Factures, ou affichez-le depuis votre override de modèle. Le numéro de l'acheteur est séparé : il ne s'imprime que si le client l'a saisi dans son adresse. - Caractères spéciaux corrompus dans le PDF (ł/ą/ę polonais, diacritiques tchèques, signe euro affiché sous forme de carrés). TCPDF a besoin d'une police contenant ces glyphes, remplacez la police de facture par une famille complète en Unicode (par exemple une famille DejaVu/freefont) dans les paramètres PDF plutôt que d'utiliser la police par défaut.
- Échec de génération du PDF sur les grosses commandes. Il s'agit généralement du
memory_limitPHP, les factures comportant de nombreuses lignes et un modèle lourd peuvent le dépasser. Augmentez-le à 256M+ côté PHP. - Trous dans la numérotation. Souvent, une commande annulée qui avait déjà généré une facture. Certains pays tolèrent les trous ; la France, non. La solution relève d'une stratégie de numérotation, pas d'un ajustement de modèle, c'est le sujet de la personnalisation des numéros de facture et de commande.
Multiboutique : un modèle, plusieurs identités légales
Si vous exploitez plusieurs vitrines dans une installation multiboutique, chacune a besoin de sa propre identité de facturation, nom de société différent, pied de page légal différent, souvent langue différente. PrestaShop gère l'essentiel de ce contexte : basculez vers la boutique concernée dans le sélecteur de boutique du back-office avant de modifier les paramètres de facture, et le préfixe, le texte libre légal et le pied de page s'appliqueront uniquement à cette boutique. Le danger consiste à modifier en contexte Toutes les boutiques, où chaque changement se répercute sur toutes. Les fichiers de modèle eux-mêmes sont partagés depuis le thème ; si deux boutiques exigent réellement des mises en page différentes, pilotez la différence avec une condition sur l'id de boutique dans le .tpl plutôt que de maintenir deux modèles divergents.
Quand un module vous évite le travail d'override
Tout ce qui précède peut être fait à la main, et pour une seule boutique dans un seul pays, c'est parfois le bon choix. La voie de l'override devient coûteuse lorsque vous maintenez du PHP personnalisé et des modèles de thème au fil des mises à jour de PrestaShop, dans plusieurs langues et sur plusieurs juridictions à la fois. C'est précisément là qu'un module maintenu prend tout son sens, car la charge de compatibilité sort de votre assiette.
Là où le problème apparaît le plus souvent en premier, c'est la numérotation plutôt que la mise en page : remises à zéro annuelles, séries séparées pour les factures et les avoirs, formats comme FA-2029-0001 que plusieurs juridictions attendent de fait. Notre module mprinvoicenumber gère cela depuis le back-office, remises à zéro annuelles automatiques, numérotation multi-séries et formats personnalisés avec année/mois et séquences complétées par des zéros, afin que vous n'ayez pas à modifier le compteur à la main chaque janvier ni à risquer les trous que la France ne pardonne pas. Quel est donc l'intérêt ? La numérotation reste conforme et la configuration vit dans l'administration, pas dans un fichier d'override que la prochaine mise à jour pourrait écraser. Le raisonnement complet sur les limites de la numérotation par défaut se trouve dans pourquoi les numéros par défaut ne suffisent pas.
Le résumé honnête : le moteur de facturation de PrestaShop est solide, mais son modèle par défaut est volontairement générique, et « générique » ne veut pas dire « légal dans votre pays ». Personnalisez le .tpl dans votre thème, surchargez la classe PHP uniquement pour les champs que PrestaShop ne charge pas déjà, placez vos mentions légales constantes dans les emplacements de texte libre intégrés et, la partie que la plupart des marchands ignorent jusqu'à ce qu'il soit trop tard, archivez une copie figée de chaque facture le jour de son émission. Faites cela correctement une fois, et la facturation redevient la partie invisible et ennuyeuse de votre boutique qu'elle devrait être.
Questions fréquentes
Où modifier le modèle de facture PrestaShop ?
Copiez pdf/invoice.tpl depuis le cœur vers themes/YOUR_THEME/pdf/invoice.tpl et modifiez la copie, PrestaShop vérifie le dossier pdf/ du thème avant le cœur, donc les mises à jour laissent votre version intacte. Le fichier de style correspondant est invoice.style-tab.tpl. Ce n'est que lorsque vous avez besoin de données que PrestaShop ne transmet pas déjà au modèle que vous ajoutez aussi un override/classes/pdf/HTMLTemplateInvoice.php. Ne modifiez jamais directement le fichier du cœur.
Pourquoi le numéro de TVA de mon entreprise n'apparaît-il pas sur la facture ?
Parce que la facture par défaut de PrestaShop n'imprime aucun numéro de TVA vendeur. Le bloc vendeur est construit uniquement à partir du nom et de l'adresse de la boutique (les valeurs PS_SHOP_*), et International → Taxes définit les taux de taxe, pas un identifiant vendeur. Ajoutez votre numéro de TVA comme texte constant dans les champs Texte libre légal ou Texte de pied de page sous Commandes → Factures, ou affichez-le depuis un override de modèle. Le numéro de l'acheteur est séparé et n'apparaît que si le client l'a saisi dans son adresse.
Mes modifications de modèle survivront-elles à une mise à jour de PrestaShop ?
Les overrides pdf/ au niveau du thème survivent aux mises à jour du cœur, et les overrides de classes sous override/classes/ aussi, mais une mise à jour de thème ou une action de « réinitialisation du thème » peut effacer la copie du thème, et un module tiers embarquant son propre modèle ou override peut entrer en conflit avec le vôtre. Gardez les deux fichiers sous contrôle de version en dehors de la boutique, et revérifiez-les après un saut majeur de version au cas où le modèle du cœur aurait gagné des champs que vous voudriez fusionner.
Les avoirs et les bons de livraison se personnalisent-ils de la même manière ?
Même mécanisme, fichiers différents. L'avoir (note de crédit / avoir) correspond en interne à l'"order slip" ; vous personnalisez donc themes/YOUR_THEME/pdf/order-slip.tpl (classe HTMLTemplateOrderSlip) ; le bon de livraison est themes/YOUR_THEME/pdf/delivery-slip.tpl. Ce sont des documents juridiquement distincts, une modification de invoice.tpl ne se reporte pas, donc modifiez chacun de ceux dont vous avez besoin.
Pourquoi les caractères polonais ou tchèques se transforment-ils en carrés dans le PDF ?
TCPDF, la bibliothèque qui rend le PDF, n'affiche que les glyphes présents dans la police choisie. La police par défaut peut ne pas inclure ł/ą/ę ni d'autres diacritiques. Remplacez la police de facture par une famille complète en Unicode (une variante DejaVu/freefont) dans les paramètres PDF, et les caractères s'afficheront correctement. La même correction résout un signe euro imprimé sous forme de carré.
Guides associés
- Personnalisation des numéros de facture et de commande : pourquoi les numéros par défaut ne suffisent pas
- Facturation électronique en Europe : quels pays l'exigent et comment s'y conformer
- Configuration des taxes dans PrestaShop : les règles de TVA de l'UE expliquées
- TVA dans l'UE : OSS, IOSS et ce que votre boutique PrestaShop doit gérer
- Règles d'affichage des prix en Europe : quand afficher les prix HT, TTC et unitaires