← LemonFacturX

JOURNAL DES VERSIONS

Tout ce qui a changé
dans LemonFacturX.

Facturation électronique Factur-X automatique

Version en cours 4.2.0 Dolibarr 19 et supérieur

4.2.0 (19 octobre 2026)

La société du contact « Facturation » peut être celle qui est facturée. Quand le contact de facturation d’une facture appartient à une autre société que le client (maison mère, centre de services partagés), un nouveau réglage dit ce qu’elle est. Par défaut, elle reçoit seulement la facture, comme en 4.1.2 (bloc « Adressée à », profil étendu). Réglée sur « Elle est facturée », elle devient l’acheteur du XML : nom, SIREN, TVA, adresse, et adresse de facturation électronique (BT-49) routée sur son SIREN. Le client de la facture passe en informations de livraison, en EN 16931, et la facture reste rattachée à sa commande. L’avertissement de cohérence entre le PDF et le XML nomme les deux réglages possibles, et ne dit plus rien à corriger quand l’acheteur est la société du contact. LemonSuperPDP 2.2.0 envoie alors la facture à cette même société.

Le courriel des contacts ne fait plus rejeter la facture. Depuis la 4.0.4, le courriel du contact vendeur (BT-43) et du contact acheteur (BT-58) partait avec un attribut schemeID="SMTP" que le Schematron Factur-X signale comme inutilisé à cet endroit. La plupart des plateformes le laissaient passer, une plateforme de réception a rejeté la facture (fr:213, REJ_SEMAN). L’attribut n’est plus écrit. L’adresse de facturation électronique de l’acheteur et du vendeur garde le sien, qui y est obligatoire.

Le champ BT-132 n’apparaît plus sous chaque ligne quand il est vide. Le « N° de ligne du bon de commande acheteur (BT-132) », ajouté en 4.1.0 pour les acheteurs qui l’exigent (Amazon), s’affichait sous toutes les lignes des commandes et des factures, rempli ou non. Il ne se montre plus que rempli, et reste saisissable en modifiant la ligne. Sa recopie de la commande vers la facture et son émission dans le XML ne changent pas.

4.1.2 (14 octobre 2026)

L’API REST exige à nouveau une clé. La classe ne déclarait pas @access protected : les quatre routes répondaient sans authentification. Elles ne laissaient rien sortir, car chacune vérifie l’utilisateur avant de lire quoi que ce soit et s’arrêtait en erreur 500 faute d’utilisateur. Un appel sans clé reçoit désormais 401.

Une route qui n’en était pas une disparaît. La fonction interne qui charge la facture était publiée par l’API sous /lemonfacturxapi/loadinvoice/{id} et renvoyait l’objet facture brut. Elle n’est plus exposée (404).

4.1.1 (14 octobre 2026)

Une facture adressée à la maison mère garde la filiale comme acheteur. Dans un groupe, c’est souvent une filiale qui commande et se fait livrer, alors que la facture doit partir à la maison mère ou au centre de services partagés. Dans Dolibarr, on le dit avec un contact « Facturation » rattaché à cette autre société, et le PDF l’imprime comme destinataire. Le XML, lui, ne nommait que l’acheteur : le PDF et le fichier ne désignaient pas la même société.

La société du contact est désormais écrite dans le bloc « Adressée à » (EXT-FR-FE-BG-04) du profil étendu EXTENDED-CTC-FR, que la norme réserve à « l’entité à laquelle est adressée la facture quand elle est différente de l’acheteur » : raison sociale, SIREN, SIRET, adresse, adresse électronique, TVA, et la personne à joindre. L’acheteur ne change pas : c’est lui qui a commandé, qui doit la facture et qui déduit la TVA, et le remplacer fausserait tout cela. Rien de plus à saisir : le contact de facturation suffit.

Le bloc n’existant qu’en profil étendu, la facture bascule comme une facture multi-commandes, quand le réglage le permet. Son premier choix devient « Quand la facture l’exige », qui couvre les deux cas. Réglage éteint, le XML ne change pas, mais un avertissement signale que le PDF et le XML ne nomment pas la même société. Chorus Pro reste en dehors. Les factures dont le contact de facturation appartient au client lui-même sortent à l’identique.

Le module dit quel PDF déposer sur le portail Chorus Pro. Une facture au secteur public produit deux PDF : {ref}.pdf pour la plateforme agréée et {ref}-CHORUS.pdf pour le portail, qui refuse le premier. La génération et « Vérifier la Factur-X » l’affichent désormais : « Chorus Pro : déposez {ref}-CHORUS.pdf sur le portail. »

La référence client ne part plus comme code service. Sans code service saisi, le PDF Chorus la mettait à sa place. Chorus Pro contrôle ce champ contre son annuaire, où elle est inconnue : le champ reste maintenant vide, et la référence client part toujours comme numéro de commande. Un avertissement signale le code service manquant, que certaines administrations exigent.

4.1.0 (5 octobre 2026)

Une mise à jour par copie de fichiers s’installe toute seule. Jusqu’ici, après avoir remplacé les fichiers du module, il fallait le désactiver puis le réactiver pour que les nouveaux champs, onglets et réglages apparaissent. Sans ce geste, rien ne le signalait, et c’était la première cause des demandes de support. Le module mémorise désormais la version installée : dès qu’un administrateur ouvre une facture ou la configuration du module après une mise à jour, l’installation est rejouée automatiquement, sans toucher aux factures ni aux données, et un message le confirme. Un utilisateur sans droits d’administration est prévenu une fois qu’un administrateur doit passer. La configuration affiche la version installée et celle des fichiers, avec un bouton « Rejouer l’installation » pour le faire à la demande.

Le numéro de ligne du bon de commande de votre client (BT-132). Certains acheteurs rapprochent chaque ligne de la facture d’une ligne de leur bon de commande, et refusent la facture quand ce numéro manque : Amazon la rejette avec le message « No PO line number on invoice ». Ce numéro appartient à votre client, Dolibarr ne le connaît pas et le module ne l’invente pas. Les lignes de commande et de facture portent désormais un champ « N° de ligne du bon de commande acheteur (BT-132) ». Saisi sur la commande, il est repris par Dolibarr sur la facture créée à partir d’elle, facturation groupée comprise ; il se saisit aussi directement sur la facture tant qu’elle est en brouillon. Laissé vide, le XML ne change pas. Le numéro du bon de commande lui-même se renseigne toujours dans la « Réf. client » de la facture ou de la commande. Le champ est créé par le module lui-même après la mise à jour, il n’y a rien à faire.

La référence et le code-barres de vos articles. Une ligne liée à un produit porte désormais sa référence (BT-155) et, quand le produit a un code-barres EAN13, EAN8 ou UPC, ce code (BT-157) : le logiciel de votre client reconnaît l’article sans avoir à relire son nom. Un code-barres d’un autre type (Code 128, QR code…) n’est pas repris, ce n’est pas un code article reconnu hors de chez vous ; un code dont la clé de contrôle est fausse non plus. Les lignes saisies sans produit ne changent pas. En mode secret professionnel, une ligne qui part sous le libellé générique ne porte ni référence ni code-barres. Ni l’un ni l’autre n’entre dans l’extrait transmis à l’administration.

Le détail de vos lignes ne part plus à l’administration. Votre plateforme agréée envoie la facture complète à votre client et un extrait à l’administration fiscale, le « Flux 1 ». Cet extrait reprend le nom de chaque article (BT-153), jamais sa description (BT-154). LemonFacturX mettait jusqu’ici la description de la ligne dans le nom, et la recopiait en note de ligne (BT-127) quand elle dépassait 255 caractères : deux champs de l’extrait. Désormais, une ligne liée à un produit ou un service part sous le libellé de ce produit, traduit dans la langue de la facture comme sur le PDF, et sa description en BT-154. Une ligne saisie sans produit garde sa description comme nom ; coupée, elle part en entier en BT-154. Le PDF ne change pas. Les lignes entrent dans l’extrait avec le profil complet, obligatoire au 1er septembre 2027.

Mode secret professionnel. Pour les professions tenues au secret (article 242 nonies J de l’annexe II au CGI), un réglage remplace le nom des articles par un libellé générique, « Honoraires » par défaut, et envoie tout le texte de la ligne dans la description, que seul le client reçoit. Au choix : sur les lignes saisies sans produit, ou sur toutes. Aucune saisie n’est bloquée. Sur une facture de prestations, l’adresse de livraison, qui entrerait dans l’extrait, n’est plus écrite.

Ce que reçoit l’administration. Une nouvelle entrée du menu Factur-X de la facture affiche l’extrait transmis au fisc, lu dans le PDF lui-même et filtré par la liste officielle des champs (norme XP Z12-012, annexe A v1.4), avec la date à partir de laquelle chaque champ part.

L’installation s’explique dès l’ouverture du ZIP. Un fichier INSTALL.txt, en français et en anglais, donne les deux façons d’installer le module (depuis le menu de Dolibarr, sans décompresser, ou par copie dans custom), son activation, où trouver le mode d’emploi, et comment le mettre à jour.

Le XML parle la langue de la facture. Un client anglophone recevait un PDF en anglais et, dans le XML, des textes en français : mentions de retard de paiement, d’indemnité et d’escompte, motif de l’exonération de TVA. Ils suivent désormais la langue du PDF, comme le moyen et les conditions de paiement. Une mention réécrite dans la configuration part toujours telle que vous l’avez saisie. Les codes (VATEX, BAR, moyen de paiement) ne changent pas, et une facture française sort à l’identique.

Le libellé du prélèvement ne contient plus d’entités HTML. En 4.0.7, une facture en français payée par prélèvement (codes 59 et 49) portait « Prélèvement SEPA » dans le XML au lieu de « Prélèvement SEPA ».

Les conditions de paiement suivent la langue du PDF. Elles étaient traduites dans la langue de l’utilisateur qui générait la facture, et pouvaient donc différer de celles imprimées sur le PDF d’un client étranger.

4.0.7 (21 septembre 2026)

Le moyen de paiement s’écrit aussi en toutes lettres (BT-82). La facture portait le code du moyen de paiement — 30, 59 — et rien d’autre. C’est ce qu’attend une machine ; ce n’est pas ce que lit la personne du service comptable de l’acheteur quand elle ouvre la facture sur le portail de sa plateforme. Le libellé en clair accompagne désormais le code : « Virement bancaire », « Prélèvement SEPA ». Il est dérivé du code, jamais saisi à part — deux champs libres finissent toujours par se contredire — et il suit la langue du document, puisque c’est l’acheteur qui le lit. Un code sans libellé connu n’écrit rien plutôt qu’une clé de traduction brute.

Le profil EXTENDED-CTC-FR peut être imposé sur toutes les factures. Le réglage ne proposait que « jamais » et « sur les factures multi-commandes ». Il manquait le cas que remontent les clients dont la plateforme agréée exige ce profil pour tout ce qu’ils émettent : l’exigence vient alors de la plateforme, pas du contenu de telle ou telle facture, et aucun réglage par client n’y répondrait. Un troisième choix, « Toujours », a été ajouté.

Ce que fait ce mode, et ce qu’il ne fait pas : seul l’identifiant de profil change. Le contenu du fichier reste celui de la norme de base, ce qui est permis — le profil étendu l’englobe, et son schéma accepte tout ce qu’accepte celui de la norme socle. On n’annonce donc pas un document qu’on n’écrit pas. Ce qui reste à vérifier, comme pour le mode multi-commandes, ce sont les règles propres au profil étendu que la plateforme peut opposer en plus : un envoi de test reste la seule façon de le savoir, et le message de la configuration le rappelle.

Le réglage reste éteint par défaut, et les deux premiers choix se comportent exactement comme avant.

Sous le capot : les fichiers de référence du test de non-régression octet pour octet ont été régénérés pour intégrer BT-82 — un seul ajout de ligne par fichier, visible dans le diff, et rien d’autre n’a bougé.

4.0.6 (12 septembre 2026)

Saisie de l’adresse électronique du client (BT-49) sur la fiche tiers. Le BT-49, l’adresse électronique de l’acheteur sur le réseau des Plateformes Agréées, valait jusqu’ici le SIREN de l’acheteur, et rien d’autre. Ça couvre le cas courant et lui seul. Un grand compte adresse ses factures à un service facturier — 123456789_ACHATS, 12345678900014_COMPTA — et un client étranger n’a pas de SIREN du tout : ni l’une ni l’autre de ces adresses ne se devine. La facture partait alors vers une adresse que personne ne relève, sans que rien ne le signale : une facture électronique mal adressée n’est pas rejetée, elle est livrée chez personne.

La fiche de chaque client porte donc désormais un champ « Adresse électronique (facturation électronique) », qui accepte les deux écritures usuelles — 0225:123456789_ACHATS comme la plateforme l’affiche, ou l’identifiant nu. Le schéma est découpé et non recopié dans la valeur, faute de quoi l’endpoint sortirait en schemeID="0225">0225:123456789_ACHATS< : valide pour le XSD, routable par personne. Laissé vide, le comportement ne bouge pas d’un octet.

Ce qui est saisi est contrôlé avant l’envoi, puisque c’est le seul moment où l’erreur est encore rattrapable : les caractères que la règle BR-FR-23 n’admet pas sont retirés et signalés, la longueur maximale de 125 caractères (BR-FR-25) est vérifiée, et une adresse qui ne laisse rien d’exploitable est ignorée au profit du SIREN plutôt que d’émettre un endpoint vide. À l’inverse, un client qui a maintenant une adresse à lui ne déclenche plus l’avertissement de routage réclamant son SIREN.

Le champ est partagé avec LemonSuperPDP, qui l’avait introduit de son côté : même donnée, même fiche, même saisie. Le module activé le premier le crée, l’autre le trouve et s’en sert — un client qui possède les deux voit une ligne et non deux, et n’a rien à ressaisir en achetant le second.

Corrigé au passage : le mode d’emploi annonçait un BT-49 lu depuis l’« Id. prof. 5 » du tiers. Ce champ, en France, porte le numéro EORI, et plus aucune ligne de code ne le lisait depuis longtemps — la documentation avait survécu au détournement qu’elle décrivait.

4.0.5 (9 septembre 2026)

Références de commande au niveau ligne pour les factures multi-commandes. La norme EN 16931 ne prévoit qu’un seul numéro de bon de commande, à l’en-tête. Jusqu’ici, une facture issue de cinq commandes en citait donc une, la première venue, et les quatre autres disparaissaient — l’acheteur cherchait à rapprocher un total avec une commande qui n’en couvrait qu’un cinquième. Ces factures-là sortent désormais dans le profil étendu EXTENDED-CTC-FR du socle XP Z12-012, où chaque ligne porte sa propre commande : la nôtre et son rang de ligne, et le bon de commande de l’acheteur quand il nous l’a donné. Les références de commande quittent alors l’en-tête, puisqu’aucune ne vaut pour la facture entière.

Le changement de profil est décidé facture par facture, jamais globalement, et seulement quand les lignes viennent réellement de plus d’une commande. Une facture ordinaire produit exactement le même XML qu’avant, à l’octet près — une recette dédiée compare neuf documents caractère par caractère à leur version antérieure et refuse la moindre dérive. Le B2G Chorus Pro reste en dehors.

Le profil étendu s’active explicitement, dans la configuration du module, et il est éteint tant qu’on ne l’allume pas. La raison est mesurée, pas supposée : passé au Schematron officiel EN 16931 de la Commission — celui que les plateformes opposent — un document étendu lève trois assertions, parce que ces règles-là implémentent la norme socle et interdisent exactement ce que le profil étendu ouvre. Une plateforme qui les applique telles quelles refuserait la facture. Le lien ligne–commande, lui, est enregistré dans tous les cas : allumer le réglage plus tard ne demande aucune reprise.

Ce qui manquait pour en arriver là n’était pas le XML mais la donnée : Dolibarr ne conserve nulle part le lien entre une ligne de facture et la ligne de commande dont elle vient. Le module le note maintenant lui-même au moment où la facture est créée. Deux conséquences à connaître : les factures déjà émises n’ont pas cette information et resteront en EN 16931, et le module doit être désactivé puis réactivé pour que le mécanisme se mette en place — comme après chaque mise à jour, et sans perte de données.

Dernier point, à vérifier une fois : le profil étendu appartient au socle français, mais toutes les plateformes de dématérialisation ne l’ont pas ouvert. Un message vert le rappelle à la génération de la première facture concernée. Un dépôt de test suffit à lever le doute.

Les titres et sous-totaux ne partent plus comme des articles. Sur une facture construite avec un module de sous-totaux — celui du cœur depuis Dolibarr 22, l’ancien Sous-total d’ATM, Milestone ou LemonJalon — les lignes de titre et de sous-total sortaient dans le XML au même titre que les prestations. Le filtre en place écartait les lignes « sans quantité ni montant », or un titre Sous-total porte sa profondeur dans la quantité : un lot de niveau 1 devenait un article facturé en quantité 1, une ligne de fermeture ATM un article en quantité 99. Une facture à deux prestations et deux lots partait avec sept lignes.

Ces lignes sont maintenant reconnues à leur type de produit — la valeur 9, hors de la plage Dolibarr, que tous ces modules emploient — et écartées avant la construction du XML, quel que soit le numéro du module qui les a écrites.

Deux conséquences que le décompte de lignes cachait. La nature du document (BT-23) se déduit du type des lignes : une facture de pur conseil accompagnée de sous-totaux était annoncée « mixte » au lieu de « services », ce dont dépend la règle d’exigibilité appliquée en aval. Et une ligne de structure qui aurait gardé un montant en base le faisait compter deux fois dans le total des lignes, donc un écart avec le total de la facture et un rejet à la validation. Ce cas-là est désormais écarté et nommé dans les avertissements de génération.

Rien ne change pour une facture sans sous-totaux, et aucune donnée n’est modifiée : le filtre est en lecture, à la génération.

4.0.4 (1er septembre 2026)

Le contact de facturation part avec la facture. La norme prévoit une personne à joindre de chaque côté — nom, téléphone, courriel — et le champ restait vide. Le contact « Facturation » de la facture (à défaut « Client ») alimente désormais le bloc acheteur, et le contact interne « Suivi commercial » (à défaut « Signataire ») celui du vendeur. Sans contact rattaché, la facture sort exactement comme avant.

Le contact ne déplace ni le SIREN, ni l’adresse, ni l’adresse de routage. C’est une personne à qui écrire, pas un tiers de substitution — un contact rattaché à une autre société reste publié sous l’acheteur de la facture.

Chaque avertissement dit maintenant quoi faire. Vingt-et-un messages se contentaient de constater — « adresse du tiers acheteur manquante », « aucun compte bancaire configuré », « écart entre la TVA des lignes et le total » — sans indiquer où corriger. Ils nomment désormais l’écran et le champ : la fiche tiers, la configuration de la société, le masque de numérotation, la configuration du module.

Deux cas méritaient plus qu’une adresse. Le SIREN manquant sur un acheteur explique qu’un particulier se déclare comme tel sur sa fiche, ce qui fait sortir la facture en B2C et supprime l’avertissement — sans cette information, le XML annonce un traitement entre entreprises pour une vente à un consommateur. Et le numéro de TVA absent rappelle que la franchise en base se déclare en décochant « Assujetti à la TVA », au lieu de laisser croire à un oubli.

4.0.3 (27 août 2026)

Un message d’erreur qui n’en était pas un. Quand l’injection passait par un sous-process, le module pouvait afficher « injection PDF échouée : OK ». OK est le marqueur de succès que le script d’injection écrit en fin de travail : il ressortait tel quel comme motif d’échec, ce qui ne renseignait sur rien.

Deux corrections. D’abord, le fichier fait foi : quand le code de sortie du sous-process annonce un échec, le module regarde désormais le PDF avant de le croire. Si celui-ci a bien été remplacé et porte la pièce jointe Factur-X, l’injection est considérée réussie et le code inattendu part au journal. Ensuite, le motif d’échec ne recrache plus la sortie brute : OK et les lignes vides sont écartés, une interruption est annoncée comme telle, et un process qui se termine sans rien dire l’annonce avec son code de sortie plutôt que par du silence.

Prise en charge de la facture déjà payée (cas d’usage AFNOR n° 5 et n° 7). Un collaborateur règle sa nuitée à la réception de l’hôtel, puis demande une facture au nom de son employeur ; une carte logée paie avant que la facture existe. Dans ces situations, la facture doit sortir « déjà payée » — ce que le module ne savait pas produire : le XML annonçait le montant plein à payer, quand le PDF affichait « reste à payer 0,00 ».

Le montant déjà payé (BT-113) reprend désormais, en plus des acomptes imputés, les règlements encaissés au plus tard à la date de facture. La restriction de date est la définition même du champ — « paid in advance » — et elle a une conséquence pratique : régénérer le PDF d’une facture réglée six mois plus tard redonne exactement le même XML que celui qui a été déposé. Un règlement postérieur à l’émission n’entre pas dans le calcul.

Quand la facture est intégralement encaissée avant son émission, le cadre de facturation passe en B2 / S2 / M2 et la règle BR-FR-CO-09 s’applique : montant déjà payé égal au total TTC, net à payer nul, et la date d’échéance porte la date à laquelle la facture a été payée — un délai de paiement n’aurait aucun sens sur une facture soldée. Une avance partielle, elle, reste en cadre nominal avec un montant déjà payé partiel.

Un avoir n’est jamais concerné. Sur une facture définitive après acompte également soldée, le cadre « après acompte » l’emporte : c’est lui que porte la référence à la facture d’acompte.

Un message qui annonçait un problème là où il n’y en avait pas. Une facture parfaitement conforme pouvait s’afficher sur un bandeau orange, avec la mention « avertissement non bloquant à corriger pour une conformité totale » — alors que le seul point signalé était une désignation de ligne raccourcie, dont le texte intégral est conservé et qui ne rend le document ni moins valide ni moins déposable.

Les avertissements sont maintenant de deux natures. Ceux qui appellent une action — un IBAN absent, un SIRET incohérent, un identifiant trop long — gardent le bandeau orange et la formule « à corriger ». Ceux où le module a déjà fait le nécessaire — désignation raccourcie, écart d’arrondi imputé, TVA recalculée pour satisfaire une règle — s’affichent en vert sous « pour information », et le décompte passe à la ligne au lieu de se coller à la référence de la facture.

L’injection échouait sur les hébergements à open_basedir, et accusait le temps. Pour lancer son process d’injection, le module ouvrait /dev/null en entrée standard. C’est un accès fichier ordinaire, donc soumis à la directive open_basedir — et /dev/null ne figure jamais dans la liste autorisée d’un hébergement mutualisé. Le lancement était refusé, et l’utilisateur lisait « a dépassé la limite de temps » sur une facture de quelques dizaines d’euros.

L’entrée standard passe maintenant par un tuyau refermé aussitôt : l’enfant y lit la même fin de fichier, sans que rien ne soit ouvert sur le disque. Reproduit et vérifié sous open_basedir restreint, avant et après.

« L’injection a dépassé la limite de temps » quand rien n’avait démarré. Trois situations très différentes affichaient le même message : le vrai dépassement de délai, l’absence de tout moyen de lancer un process borné sur le serveur, et un lancement refusé par l’hébergement. Les deux dernières n’ont rien à voir avec le temps, et envoyaient chercher au mauvais endroit — on attend une facture trop lourde alors que la cause est une restriction de configuration.

Chacune a désormais son message, avec la marche à suivre correspondante : basculer sur l’injection sans process pour la première, vérifier open_basedir pour la seconde.

open_basedir : le diagnostic nomme la restriction. Un hébergement peut restreindre les chemins que PHP a le droit d’atteindre. S’il autorise le binaire PHP en ligne de commande mais pas la commande timeout — celle qui lance ensuite PHP en lui imposant une limite de temps — l’injection échoue sans rien dire d’exploitable. Le cas s’est produit chez un utilisateur le 27 août : exec() était disponible, le binaire PHP correctement détecté, et rien ne fonctionnait.

Le bloc Diagnostic vérifie désormais les deux chemins, nomme celui qui manque et rappelle la valeur en vigueur. Le mode d’emploi documente le point.

L’API REST couvre la supervision. Deux routes s’ajoutent, en lecture seule comme les précédentes — aucune n’écrit de fichier, ne régénère un PDF ni ne transmet quoi que ce soit.

GET /lemonfacturx/invoices/status répond en une requête à « combien de mes factures validées n’ont pas de Factur-X, et lesquelles ? » : des compteurs et la liste des factures à problème, filtrables avec la syntaxe de recherche universelle de Dolibarr. Par défaut elle vérifie la présence de la pièce jointe ; avec validate=1 elle passe chaque XML aux règles métier. Le nombre de factures examinées est plafonné dans les deux cas — cette route lit des fichiers sur le disque, elle ne doit pas pouvoir mettre un serveur à genoux.

GET /lemonfacturx/health, réservée aux administrateurs, renvoie ce que montre l’écran Diagnostic : version du module, mode d’injection retenu, binaire PHP CLI connu, présence d’un moteur PDF concurrent, options actives. De quoi surveiller un parc d’instances sans se connecter à chacune.

4.0.2 (26 août 2026)

À lire avant de mettre à jour : le XML produit change. Trois données nouvelles partent désormais dans la facture — l’adresse de livraison, les conditions de paiement, et la référence à la facture d’acompte. Concrètement, une facture définitive après acompte régénérée aujourd’hui ne produit plus tout à fait le même XML qu’hier : elle gagne la référence à l’acompte et son cadre de facturation passe en x4. Rien à configurer, rien à migrer, aucune facture à ressaisir — le nouveau XML est plus conforme que l’ancien, pas différent en mal. Mais mieux vaut le savoir avant de régénérer un PDF de l’exercice précédent.

Adresse de livraison (BG-15) émise dans la facture. Depuis le décret 2022-1299, l’adresse de livraison des biens est une mention obligatoire dès qu’elle diffère de l’adresse du client. Le module ne l’émettait pas : le bloc livraison ne portait que la date, et un code pays pour les seules livraisons intracommunautaires.

Elle est maintenant reprise du contact de type « livraison » de la facture, et sort en BG-13/BG-15 : nom du destinataire (BT-70), voie (BT-75), code postal (BT-78), ville (BT-77), pays (BT-80). Rien n’est émis si l’adresse est la même que celle du client — la mention n’est alors pas due, et la répéter laisserait croire à une livraison ailleurs. Rien n’est émis non plus si le contact n’a pas d’adresse propre : il hérite de celle de son tiers, il n’y a rien à déclarer.

Reconnaissance des acomptes déduits en ligne. Dolibarr sait déduire un acompte de deux façons, selon la constante FACTURE_DEPOSITS_ARE_JUST_PAYMENTS : par une ligne négative dans le corps de la facture, ou par un montant « déjà réglé » en pied. Les cas d’usage AFNOR n° 20 et 21 admettent les deux, sans en recommander une — mais ils exigent dans les deux cas que la facture d’acompte soit référencée (BT-25/BT-26) et que le cadre de facturation soit en x4 « facture définitive après acompte ».

Le module ne savait traiter que la seconde. Or la première est celle que produit le réglage recommandé, celui que Dolibarr commente lui-même « Never use this » à l’envers — autrement dit le cas nominal. Sur ces factures, le XML ne disait tout simplement pas qu’il y avait eu un acompte.

C’est réparé : la facture d’acompte est référencée et le cadre x4 est posé quelle que soit la méthode de déduction. Sur la déduction en ligne, le montant déjà payé (BT-113) reste volontairement absent — la ligne a déjà retiré la somme du total, l’émettre en plus la compterait deux fois.

Le cadre de facturation ne se laisse plus tromper par une ligne de déduction. La lettre du cadre — B pour des biens, S pour des services, M pour les deux — se déduit de la nature des lignes. Dolibarr type sa ligne d’acompte en « produit » : une facture de pures prestations avec un acompte sortait donc en M4 au lieu de S4. Les lignes en déduction ne vendent rien et ne qualifient plus la nature de la facture.

Les conditions de paiement sont écrites en clair (BT-20). « Règlement à 30 jours fin de mois » figurait sur le PDF, jamais dans le XML. Le champ est maintenant renseigné à partir de la condition de règlement de la facture, avec la même résolution que le document imprimé — les deux faces du Factur-X disent la même chose. Rien à configurer : la donnée est déjà là.

Un avertissement quand les acomptes sont traités comme des règlements. Le diagnostic de la configuration signale désormais la constante FACTURE_DEPOSITS_ARE_JUST_PAYMENTS lorsqu’elle est active. Elle fait passer la déduction de l’acompte du corps de la facture au pied « déjà réglé », ce qui décale les totaux et les journaux comptables — Dolibarr la déconseille explicitement dans son propre code. L’avertissement constate et renvoie vers le réglage ; il ne corrige rien de lui-même, la constante n’appartient pas au module.

Contrôles de cette version. Le XML produit passe le Schematron officiel EN 16931 de la Commission européenne (13 scénarios, 1 235 règles évaluées, aucun échec) et les PDF produits sont validés PDF/A-3B par veraPDF, l’outil de référence de la PDF Association (146 règles, 3 879 contrôles, aucun échec). La recette métier tourne sur PostgreSQL comme sur MySQL.

4.0.1 (18 août 2026)

L’autoliquidation domestique sort en catégorie AE. Une facture de sous-traitance du bâtiment (art. 283-2 nonies du CGI) partait jusqu’ici en catégorie E « Exonéré de TVA » : la ligne était à 0 %, et rien dans les données Dolibarr ne disait pourquoi. C’est faux au sens EN 16931 — une autoliquidation n’est pas une exonération — et les contrôles de conformité le relèvent.

Il suffit maintenant de créer au dictionnaire des taux de TVA un taux à 0 % pour la France portant le code AE. Toute ligne qui l’utilise sort en catégorie AE avec le code VATEX-FR-AE. Le champ lu est vat_src_code, natif Dolibarr sur les lignes de facture : pas d’extrafield à créer, pas de schéma modifié, rien à ressaisir sur les factures existantes.

Correction d’un rejet en production : la désignation de ligne était trop longue. Une facture acceptée par la plateforme agréée — statut « Déposée », qui atteste pourtant qu’elle est « contrôlée et conforme » — pouvait être rejetée vingt minutes plus tard par le portail public de facturation, avec ce motif : « Le champ BT-153 ne respecte pas la longueur maximale imposée par PPF ».

BT-153, c’est le nom de l’article, autrement dit la désignation de la ligne. Le portail la plafonne à 255 caractères. Le schéma Factur-X, lui, n’impose aucune limite : le XML était donc valide, la plateforme le validait, et le rejet n’arrivait qu’au bout de la chaîne — une fois la facture partie.

Les désignations sont maintenant tronquées à 255 caractères, sur une fin de mot plutôt qu’au milieu, et le texte intégral est conservé en note de ligne (BT-127, plafonnée à 1024 caractères). Le PDF lisible n’est pas modifié. Un avertissement indique combien de lignes ont été raccourcies.

Les notes de document (BT-22) sont plafonnées au même titre : elles sont surchargeables par constante, donc rien n’empêchait d’y dépasser la limite.

Les autres exonérations françaises peuvent porter leur base légale. Formation professionnelle, DOM, presse… : la constante MAIN_VAT_EXEMPTION_CODE_FOR_<taux>[_<code source>] contient le code VATEX à émettre, et le module le reprend tel quel en BT-121. La ligne reste en E, ce qui est correct, mais elle cesse d’être un « Exonéré de TVA » sans justification. C’est la convention Dolibarr : une instance déjà configurée pour le module e-invoicing officiel n’a rien à refaire.

Un écran pour les exonérations de TVA. Les codes d’exonération se saisissaient jusqu’ici dans l’éditeur de constantes générique de Dolibarr, à la main, de mémoire — pour une valeur qui doit correspondre au caractère près à l’une des 90 entrées d’un référentiel, sous peine de rejet. La configuration du module propose maintenant la liste complète avec les libellés officiels, affiche les associations existantes et signale celles dont le code n’est plus au référentiel.

L’autoliquidation, elle, ne demande toujours rien : un taux à 0 % portant le code AE au dictionnaire suffit, et l’écran le rappelle.

Le prix unitaire brut est désormais émis (BT-148). L’annexe 1 des spécifications externes le déclare obligatoire dans le flux de données réglementaires, alors que le schéma Factur-X comme le contrôle européen le laissent facultatif.

Le brut, c’est le prix catalogue avant remise de ligne ; le net, celui après. Quand il y a une remise, l’écart est publié séparément (BT-147) et le triplet reste cohérent par construction — le net vaut toujours le brut moins la remise, quelle que soit la fiabilité du prix unitaire saisi. Sans remise, brut et net sont égaux et aucun bloc de remise n’est produit.

Les numéros de TVA sont normalisés à l’émission. Le champ « TVA intracom. » de la fiche tiers est du texte libre : on y saisit volontiers « FR 38 909 458 306 » pour la lisibilité, parfois un commentaire. Le portail plafonne cet identifiant à 18 caractères, espaces compris. Ils sont désormais retirés à l’émission — retirer les espaces d’un numéro de TVA ne le dénature pas.

Ce qui dépasse encore 18 caractères après normalisation n’est pas tronqué : un identifiant fiscal amputé est un identifiant faux. Il ressort en violation, avec le champ nommé, pour être corrigé sur la fiche tiers.

Le reste des longueurs déclarées par l’annexe 1 a été vérifié en émettant des données volontairement hors limites : rien d’autre ne dépasse. Les noms et adresses de tiers, en particulier, ne relèvent pas de l’annexe 1 — l’extrait de données réglementaires du flux 1 ne les contient pas.

Ces longueurs viennent de l’annexe 1 « Format sémantique FE e-invoicing — Flux 1 » v1.2 des spécifications externes v3.2. Le portail les contrôle explicitement (« Contrôles des longueurs maximales »), et un dépassement se solde par un rejet REJ_SEMAN.

Les codes d’exonération de TVA sont désormais vérifiés. Le code VATEX déclaré (dictionnaire des taux ou constante) est contrôlé contre la liste officielle de l’annexe 7 des spécifications externes — 90 codes. Un code hors liste n’est plus émis : la catégorie de TVA est déduite du contexte, et un avertissement nomme le code refusé.

Ce contrôle manquait, et rien d’autre ne le faisait : dans le schéma Factur-X, le code d’exonération est une chaîne libre. Une faute de frappe produisait donc une facture parfaitement valide au regard du schéma, transmise à la plateforme, et rejetée par elle — après émission.

À noter : la v3.2 des spécifications (30 avril 2026) a précisément ajouté VATEX-FR-AE, le code de l’autoliquidation domestique livré en 4.0.1, avec pour définition « exonération fondée sur le 2 de l’article 283 du CGI » et la mention « uniquement pour la facturation domestique en France ».

Garde-fous. La déclaration ne s’applique jamais à une ligne qui porte réellement de la TVA — un taux > 0 reste en S (BR-E-05, BR-AE-05). Et une autoliquidation déclarée sur un tiers sans numéro de TVA ressort en violation BR-AE-02 au contrôle interne : le module ne masque pas une facture incomplète.

Correction d’étiquetage : les remises de pied de facture sont BG-20, pas BG-21. Le XML était juste — l’indicateur distingue correctement une remise d’une charge — mais la documentation et les commentaires nommaient BG-21, qui désigne les charges. La v3.2 a renommé BG-21 en « charges ou frais » ; le module suit.

Alignement sur Factur-X 1.09.2 et sur les spécifications externes v3.2. Le module embarquait les schémas Factur-X 1.08 ; la version en vigueur est la 1.09.2 (10 juin 2026, mise à jour le 4 août). Pour le profil EN 16931 que le module produit, les schémas sont identiques — les nouveautés du millésime sont allées dans le profil EXTENDED et dans les listes de codes. Aucune facture existante n’est donc affectée ; les schémas sont simplement à jour.

Le nom du fichier de schéma ne figure plus en dur dans le code. Il portait la version (Factur-X_1.08_EN16931.xsd), si bien qu’une mise à jour de la bibliothèque embarquée désactivait la validation en silence : le fichier attendu n’existait plus, et le contrôle se réduisait au « XML bien formé ».

Validation contre le contrôle européen de référence. La recette compare désormais les factures produites aux artefacts de validation officiels de la Commission européenne, et non plus seulement à nos propres règles. Dix scénarios, 951 évaluations de règles, aucun écart.

4.0.0 (14 août 2026)

Le module vous prévient désormais qu’une mise à jour existe. Le descripteur déclare url_last_version, le fichier de version publié sur hellolemon.fr. Dolibarr le lit et signale « nouvelle version disponible » dans la liste des modules, à condition que la vérification y soit activée. La page de configuration du module, elle, affiche le bandeau sans rien avoir à activer.

Jusqu’ici, aucune instance ne pouvait apprendre qu’une version plus récente était sortie : ni Dolibarr ni le Dolistore n’interrogent quoi que ce soit d’eux-mêmes. C’est ce qui motive le passage en 4.0.0.

Le contrôle de version ne passe plus par GitHub. Les dépôts sont privés, l’appel à l’API des releases ne pouvait plus aboutir. Le bandeau lit maintenant le même fichier que Dolibarr, sur hellolemon.fr. Le nombre d’appels réseau sortants est inchangé : un seul, mis en cache 24 h, échecs compris.

Ce fichier ChangeLog et l’onglet qui l’affiche. L’onglet « Fichier ChangeLog » de la fiche du module était vide faute de fichier ; les notes de version, jusque-là dans le README, sont désormais ici.

3.9.8 (août 2026)

Correction de robustesse — la page de configuration pouvait rendre un hébergement mutualisé indisponible. Elle recherchait le binaire PHP en ligne de commande à chaque affichage, en lançant jusqu’à dix processus. Sur un hébergement à quota de processus, quelques rechargements suffisaient à saturer le compte, et les processus bloqués n’étaient jamais libérés.

  • La recherche du binaire n’a plus lieu qu’à l’activation du module, ou sur le bouton « Détecter le binaire PHP CLI » de la configuration. Aucun affichage de page ne lance de processus.
  • Toute commande lancée par le module est désormais interrompue au-delà d’une échéance (3 s pour une recherche, 60 s pour une injection).
  • Si aucun binaire n’est disponible, le module bascule seul sur l’injection interne. Aucune constante n’est à créer avant d’installer le module.

Aide en ligne, infobulles et diagnostic mis à jour en conséquence.

3.9.7 (août 2026)

Correction de conformité — le n° de bon de commande du client changeait de balise. Le module émettait en BT-13 la référence interne de la commande Dolibarr (CO2607-...), alors que la norme y attend le bon de commande émis par l’acheteur (« issued by the Buyer »). Le service achats du destinataire ne pouvait donc pas rapprocher la facture de sa commande.

  • BT-13 prend désormais le n° de commande de l’acheteur : n° d’engagement (Chorus Pro), sinon la « Réf. client » de la facture, sinon celle de la commande liée.
  • BT-14 reçoit notre propre n° de commande — la valeur émise jusqu’ici en BT-13 : rien n’est perdu, elle retrouve sa place.
  • BT-10 est réservé au B2G (code service). En B2B standard, la « Réf. client » n’y va plus.

⚠️ Le XML émis change. Si vous transmettez vos factures à une plateforme, vérifiez avec vos clients grands comptes que le bon de commande arrive bien là où ils l’attendent.

Valeurs Chorus Pro sur la fiche client. Le code service et le cadre de facturation se saisissent une fois pour toutes sur la fiche d’une administration, au lieu d’être ressaisis à chaque facture. Ce qui est renseigné sur une facture l’emporte toujours. Le n° d’engagement et la référence de marché restent au niveau de la facture : ils changent d’un marché à l’autre.

Onglet « Mode d’emploi » dans l’administration du module : mise en route, tableau « ce que votre client demande → où le saisir dans Dolibarr », volet Chorus Pro et points qui surprennent.

Documentation : tableau de correspondance Dolibarr → Factur-X complété (BT-14 ajouté), et correction de la source documentée de BT-30/BT-47 — le SIREN vient d’idprof1, pas d’idprof2.

Après mise à jour, désactivez puis réactivez le module : c’est ce qui enregistre le nouvel onglet et crée les champs Chorus sur les fiches clients. Aucune donnée n’est perdue à la réactivation.

3.9.6 (31 juillet 2026)

Robustesse PostgreSQL. Les six requêtes de confort exécutées pendant la génération du Factur-X (RIB de l’acheteur, unité, factures d’acompte liées, commande d’origine, contact) sont protégées par un savepoint. Le cœur de Dolibarr appelle parfois la génération à l’intérieur de sa transaction de validation ; sur PostgreSQL, une seule erreur y annule la transaction entière et le commit se comporte en annulation silencieuse annoncée comme un succès. Sans effet sur MySQL.

3.9.5 (30 juillet 2026)

Un hébergement mutualisé pouvait ralentir tout le compte. La détection du binaire PHP en ligne de commande sonde jusqu’à dix candidats, et son résultat n’était mis en cache qu’en cas de succès : un environnement où elle échoue la relançait à chaque chargement de page. L’échec est maintenant mis en cache 24 h (repli immédiat, aucun processus lancé), le marqueur est effacé dès qu’une détection réussit, et un chemin renseigné à la main reste prioritaire. Signalé par un client sur un mutualisé à quota de processus.

3.9.4 (24 juillet 2026)

PHP 7.4 est de nouveau supporté (le prérequis était monté à 8.1). Demande d’un client sur un NAS Synology bloqué en 7.4. Vérifié avant abaissement : lint PHP 7.4 réel des fichiers du module, absence de fonction propre à PHP 8 au runtime, et suite de tests complète passée sous PHP 7.4 (177 tests, 0 échec). Les bibliothèques embarquées déclarent toutes php >= 7.4. Dolibarr 19 minimum reste requis.

3.9.3 (9 juillet 2026)

Correction d’un contrôle CSRF trop strict sur l’onglet Chorus. Le jeton était comparé à celui de la soumission suivante au lieu du jeton courant : l’enregistrement des champs Chorus aurait été refusé à tort chez un client ayant activé le renouvellement du jeton à chaque appel.

3.9.2 (juillet 2026)

Le compte bancaire du XML suit celui de la facture (signalé par un client). Le module publiait toujours l’IBAN/BIC du compte figé dans sa configuration, même quand un autre compte était sélectionné au niveau du tiers ou de la facture (le PDF, lui, montrait le bon) — d’où un IBAN incohérent entre PDF et XML. Désormais l’ordre de résolution est : compte sélectionné sur la facture (fk_account) → compte configuré dans le module (repli). Rétrocompatible : sans compte sur la facture, le comportement précédent est conservé.

3.9.1 (juillet 2026)

ActionsLemonFacturX::verifyInvoicePdf() passe publique : elle est appelée par l’onglet « Facturation électronique » de LemonSuperPDP (bouton « Vérifier la Factur-X ») pour afficher le résultat sans quitter l’onglet. Aucun autre changement.

3.9.0 (juillet 2026)

Mise en conformité XP Z12-012 (édition juin 2026) — socle minimum de la réforme.

  • Bloc de règles France au validateur : BR-FR-01/02 (BT-1 ≤ 35 caractères, charset strict sans espace), BR-FR-04 (liste fermée des types de document BT-3), BR-FR-09 (cohérence SIRET/SIREN vendeur et acheteur), BR-FR-23 (charset des adresses électroniques en schemeID 0225).
  • Références obligatoires (BR-FR-CO-04/05) : un avoir sans référence à la facture d’origine est désormais bloqué (plus un simple warning) ; une rectificative (384) exige exactement une référence datée — et n’agrège plus les acomptes imputés dans BG-3 (bug corrigé).
  • BT-23 cadre de facturation émis pour le profil PDP/B2B (B1/S1/M1 déduit des lignes, x4 pour une facture définitive après acomptes) — le chemin Chorus Pro B2G (codes AIFE) est inchangé.
  • Note BAR (BR-FR-20) : qualification du traitement attendue par les plateformes (B2B / B2BINT / B2C) émise dans le XML, déduite du profil du tiers.
  • Sanitisation du suffixe d’endpoint vendeur + borne de longueur (BR-FR-23/25) ; BT-8 vérifié contre la codelist (mapping 5/72 déjà correct, documentation enrichie).
  • +50 tests unitaires (177 au total) couvrant toutes les nouvelles règles.
  • Limitation assumée documentée : profil EXTENDED-CTC-FR (multi-vendeurs, sous-lignes) non émis — cible 2027 ; la construction des flux 1/10.1 relève de la Plateforme Agréée.

3.8.0 (juin 2026)

Nouveau : support des modèles de facture ODT. Le module se branche désormais aussi sur le hook afterODTCreation (contexte odtgeneration) et injecte le Factur-X dans le PDF issu d’un modèle ODT converti par LibreOffice (Factur-X principal + 2e PDF Chorus le cas échéant). Prérequis : MAIN_ODT_AS_PDF = libreoffice + MAIN_ODT_AS_PDFA = 1 (sinon le PDF produit est ≥ 1.5 / xref compressé, illisible par FPDI). Code 100 % best-effort : toute condition manquante dégrade proprement avec un avertissement explicite, sans fatale ni PDF corrompu. Validé en interne (LibreOffice 7.4) et en condition réelle (génération ODT confirmée sur un Dolibarr utilisateur) ; voir la section « Support des modèles ODT ». Réactiver le module pour que le nouveau contexte de hook soit pris en compte.

3.7.3 (juin 2026)

Correctif de conformité EN16931. L’identifiant SIRET du vendeur (BT-29) et de l’acheteur (BT-46) était émis dans ram:ID schemeID="0009" au niveau du TradeParty. Or EN16931 ne lit le schemeID que sur ram:GlobalID : sur ram:ID l’attribut est « not used in the given context » et faisait échouer la validation Schematron (constaté avec le validateur FNFE-MPE — « Fully Valid : NO »). L’identifiant qualifié passe désormais dans ram:GlobalID schemeID="0009". Le SIREN en SpecifiedLegalOrganization (BT-30, schemeID="0002") et le profil Chorus Pro ne changent pas. Régénérer les factures concernées pour bénéficier du correctif.

3.7.2 (juin 2026)

Correctif API REST. L’API n’expose plus la classe core Facture dans son spec (@return object au lieu de @return Facture) : le @return Facture faisait planter en HTTP 500 la génération de /explorer/swagger.json dès que le module était actif (Restler tentait de modéliser toute la classe core). Les appels API authentifiés directs n’étaient pas touchés — seul l’explorer / le spec OpenAPI.

3.7.1 (juin 2026)

Correctif de régression (à appliquer). La 3.7.0 avait fait de l’injection in-process le mode par défaut, ce qui déclenche une erreur fatale Declaration of FpdfTplTrait::setPageFormat must be compatible with TCPDF::setPageFormat sur un Dolibarr standard : pdf_getInstance() charge le moteur tcpdi (class FPDF extends TCPDF) à chaque génération, et la lib d’injection FPDI en hérite alors → conflit de signature, génération de facture cassée. L’injection repasse par un sous-process PHP isolé dès qu’exec() est disponible (process vierge, aucun conflit possible — comportement d’avant la 3.7.0). L’in-process n’est tenté que si exec() est désactivé, avec un garde-fou qui conserve le PDF classique au lieu de planter, et un diagnostic qui indique la marche à suivre (activer exec(), ou poser MAIN_DISABLE_TCPDI=1).

3.7.0 (juin 2026)

Mode d’injection réglable (LEMONFACTURX_INJECTION_MODE) avec injection in-process sans exec(). Ne pas utiliser tel quel — corrigé en 3.7.1 (conflit FPDF/TCPDF via le moteur tcpdi de Dolibarr).

3.6.3 (juin 2026)

Sélecteur de police PDF dans la configuration (compatibilité Factur-X indiquée pour chaque police) ; mentions légales BR-FR-05 centrées sur le PDF.

3.6.2 (juin 2026)

Recopie des mentions légales BR-FR-05 dans le pied de facture (INVOICE_FREE_TEXT) avec option « écraser » ; bouton pour reporter les champs Chorus dans la note publique de la facture.

3.6.1 (juin 2026)

Correctif : les champs Chorus n’apparaissent plus comme un bloc parasite dans le corps du PDF sous Dolibarr 23 (printable=0 forcé sur les extrafields Chorus).

3.6.0 (juin 2026)

Compatibilité Dolibarr 23 (onglet et hooks Chorus), meilleures performances sur les factures en brouillon, suffixe d’endpoint vendeur (BT-34) pour l’adressage des Plateformes Agréées.

3.5.1 (juin 2026)

Correctif de la détection du binaire PHP CLI sous Windows.

3.5.0 (juin 2026)

Réglages simplifiés et auto-détection du binaire PHP CLI (plus de configuration manuelle dans le cas courant).

3.4.0 (juin 2026)

Support Chorus Pro (B2G) : génération d’un second PDF dédié au profil Chorus, sans jamais modifier le Factur-X standard.

3.2.1 (juin 2026)

SIREN lu depuis le champ SIREN de Dolibarr (idprof1) plutôt que dérivé du SIRET.

3.2.0 (juin 2026)

SIRET et SIREN dans deux champs distincts (SIRET → ram:ID 0009 BT-29/46, SIREN → SpecifiedLegalOrganization 0002 BT-30/47) — corrige le rejet au dépôt sur les Plateformes Agréées (BR-FR-10).

3.1.0 (juin 2026)

Mentions légales BR-FR-05 rendues visibles sur le PDF en un clic depuis la configuration.

3.0.3 (juin 2026)

Avertissement SIREN/routage : critère « non-assujetti à la TVA » complété pour ne plus signaler à tort certains tiers.

3.0.2 (juin 2026)

Correction en un clic de MAIN_PDF_FORCE_FONT depuis le diagnostic.

3.0.1 (juin 2026)

Plus d’avertissement SIREN pour les clients particuliers (B2C).

3.0.0 (juin 2026)

Refonte de conformité majeure — lire les changements de comportement avant mise à jour.

Corrections de conformité (bloquantes auparavant) :

  • Avoirs (381) : montants désormais émis en positif (BR-27) avec DuePayableAmount exact (BR-CO-16 — l’écrêtage à zéro produisait des avoirs rejetés par les validateurs Schematron) + référence BG-3 à la facture d’origine.
  • AFRelationship Alternative au lieu de Data (exigé par la spec Factur-X pour le profil EN16931 ; Data était signalé en erreur par Mustang/FNFE).
  • Remises fixes : converties en remises document BG-21 (les lignes à prix négatif violaient BR-27).
  • Intracom (K) : pays de livraison ShipTo (BR-IC-12) et date de livraison (BR-IC-11) émis ; distinction K (biens) / AE (services art. 196) par product_type.
  • BR-61 : bloc moyen de paiement omis si virement sans IBAN configuré (au lieu d’un XML rejeté).
  • Ventilation TVA par (catégorie, taux) + réconciliation des arrondis avec les totaux facture (BR-CO-14/17) ; totaux BG-22 recalculés de bas en haut (BR-CO-10..16).
  • Multidevise et taxes locales : détectées et refusées proprement (le XML divergeait silencieusement du PDF visible).
  • SIREN/SIRET réservés aux tiers français : l’identifiant local d’un tiers étranger (HRB allemand…) n’est plus publié sous un scheme SIREN/SIRET — repli email pour l’endpoint.

Changements de comportement :

  • Deux identifiants dans deux champs distincts (depuis 3.2.0) : le SIRET (établissement, 14 chiffres) va dans ram:ID schemeID 0009 (BT-29/BT-46), et le SIREN (entité légale, 9 chiffres) dans SpecifiedLegalOrganization/ram:ID schemeID 0002 (BT-30/BT-47). Jusqu’en 3.1.x le module mettait à tort le SIRET dans SpecifiedLegalOrganization, ce qui faisait échouer la règle BR-FR-10 (« SIREN du vendeur obligatoire, exactement 9 chiffres ») et le dépôt sur les Plateformes Agréées (« l’entreprise liée à la session ne correspond pas au vendeur »). Chorus Pro conserve son SIRET via BT-29/BT-46. Aucun réglage nécessaire : chaque identifiant à sa place.
  • Mentions légales BR-FR-05 (PMD/PMT/AAB) : le texte par défaut s’applique désormais réellement quand le champ est laissé vide (auparavant les constantes créées vides à l’activation produisaient des mentions vides dans le XML).
  • Libellés moyens de paiement corrigés : 58 = virement SEPA (et non prélèvement) ; nouveau code 59 = prélèvement SEPA (avec ICS/RUM/IBAN débiteur BT-89/90/91). Vérifier votre réglage si vous aviez choisi « 58 - Prélèvement SEPA ».
  • BT-72 : date de livraison réelle (delivery_date) ou bloc omis — la date d’émission n’est plus forgée en date de livraison (sauf repli intracom).
  • Quantités et prix unitaires émis avec jusqu’à 4 décimales.

Nouvelles données émises : BT-8 (TVA débits/encaissements, config), BT-10 (ref_client), BT-13 (commande liée), BT-23 (cadre de facturation, config), BG-3 (factures antérieures : avoirs, rectificatives 384, acomptes imputés), BG-14 (période depuis les dates de service), BT-121 (codes VATEX), BT-89/90/91 (prélèvement).

Outillage :

  • Validateur interne de règles métier EN16931 (sous-ensemble Schematron en PHP) avant injection — bloquant en mode strict.
  • Boutons « Vérifier Factur-X » / « Régénérer Factur-X » sur la fiche facture.
  • API REST (/lemonfacturx/invoice/{id}/xml et /status) et export par lot (scripts/export_facturx_batch.php).
  • Post-validation veraPDF optionnelle ; diagnostic enrichi (MAIN_PDF_FORCE_FONT, exec(), binaire PHP CLI, note multidevise).
  • Suite de tests unitaires standalone (sans Dolibarr) + CI GitHub (lint + tests sur chaque push/PR, et avant chaque release).
  • Traduction en_US complète ; messages du hook et des contrôles internationalisés.

Robustesse et sécurité :

  • Écriture atomique du PDF dans le subprocess (un disque plein ne peut plus tronquer le PDF) ; retours d’écriture vérifiés ; catch \Throwable.
  • Garde CLI sur demo/* et tests/* (les fixtures créaient un admin de démo accessibles en HTTP si le dépôt était cloné sous la racine web) + .htaccess de refus sur demo/, tests/, scripts/.
  • Actions GitHub épinglées par SHA ; cache des échecs du check de version (page admin ne rame plus si GitHub est injoignable) ; garde curl_init ; filtre entity sur les comptes bancaires (multicompany) et les contacts.
  • Prérequis matérialisés dans le descripteur (phpmin 7.4, need_dolibarr_version 19).
  • Fonctions globales préfixées (xmlEncode/formatAmount → lemonfacturx_xml_encode/lemonfacturx_format_amount).

Migration : aucune migration DB, mais désactiver puis réactiver le module après mise à jour pour enregistrer le nouveau hook invoicecard (boutons de la fiche facture). Vérifier ensuite : (1) le réglage moyen de paiement si « 58 » était choisi pour du prélèvement → passer à 59 ; (2) régénérer les avoirs récents non transmis pour bénéficier du correctif. L’identifiant légal BT-30/BT-47 est désormais toujours SIRET/0009 (plus de réglage).

2.1.2 (juin 2026)

Correctif Chorus Pro — identifiant légal SIRET (et non SIREN) dans SpecifiedLegalOrganization :

  • <ram:SpecifiedLegalOrganization>/ID (BT-30 vendeur / BT-47 acheteur) : émet désormais le SIRET complet (14 chiffres) au lieu du SIREN (9 chiffres), schemeID="0002" conservé. Chorus Pro identifie les structures par leur SIRET et rejetait un SIREN à 9 chiffres. Le fichier restait valide EN16931, d’où le passage des validateurs Factur-X mais le rejet à la transmission Chorus Pro.
  • Indépendant de l’adressage de routage : l’endpoint BT-34/BT-49 (schemeID="0225", introduit en 2.1.0) continue de porter le SIREN.
  • Diagnostic : alerte si le SIRET émetteur (BT-30) ou acheteur (BT-47) ne fait pas 14 chiffres.

2.1.1 (mai 2026)

  • Franchise en base TVA : le diagnostic ne signale plus la TVA intracommunautaire manquante comme une erreur pour une société non assujettie (293 B CGI).

2.1.0 (mai 2026)

  • Endpoint BT-34 / BT-49 : SIREN avec schemeID="0225" (annuaire PPF) au lieu de l’email — requis par le routage du réseau des Plateformes Agréées. Schéma configurable (LEMONFACTURX_ENDPOINT_SCHEME), repli email pour les tiers sans SIREN.

2.0.2 (mai 2026)

  • Compatibilité Windows (#4, PR #5 de @Charlymd) : XML temporaire dans DOL_DATA_ROOT/facturx/temp/, regex LEMONFACTURX_PHP_CLI_PATH étendue.
  • Franchise en base TVA (#6) : catégorie E (au lieu de O), SIREN publié en SpecifiedTaxRegistration schemeID="FC" (BR-CO-26/BR-E-09).

2.0.1 (mai 2026)

  • Boutons Corriger du diagnostic ciblés par type d’erreur ; check des modules Dolibarr requis.

1.1.1 (avril 2026)

Maintenance des dépendances vendored : atgp/factur-x v3.3.0, smalot/pdfparser v2.12.5, setasign/fpdf 1.8.6 (patch /F 4 réappliqué), setasign/fpdi v2.6.6, symfony/polyfill-mbstring v1.36.0.

1.1.0 (avril 2026)

Module distribué publiquement sur GitHub : acomptes (386, TotalPrepaidAmount), CategoryCode contextuel, mapping unités UN/ECE, validation XSD interne, mode strict, demo/ + tests/.

1.0.0

Version initiale : génération XML EN16931, injection PDF/A-3, conformité B2Brouter sur le cas standard.