Aller au contenu principal
Making DigitalMaking Digital
Note technique

Facture Dolibarr à 0 sur le PDF : réparer les montants en devise

En bref

Quand le module Multidevise est activé, Dolibarr imprime les montants en devise des factures dont le taux n'est pas 1. S'ils sont vides (devise sans taux, import, écriture directe en base), le PDF affiche 0. On les recalcule en ressaisissant le taux de la facture avec le recalcul des prix en devise ; le SQL n'est sûr que pour les factures dans la devise de la société. Un connecteur doit passer par POST /invoices et laisser Dolibarr calculer.

Une facture arrive dans Dolibarr par un import ou un connecteur : la fiche affiche le bon montant HT, le PDF un total HT à 0,00. Le module Multidevise est activé et les montants "en devise" de la facture sont restés vides : Dolibarr les imprime dès que la facture n'est pas dans la devise de la société. La correction passe par Dolibarr lui-même ; le SQL n'est sûr qu'au taux 1.

D'où vient le montant à 0 ?

Avec le module Multidevise, chaque ligne et chaque facture portent deux séries de montants :

  • dans la devise de la société : subprice, total_ht, total_tva, total_ttc ;
  • dans la devise du document : multicurrency_subprice, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc, avec le taux multicurrency_tx sur la facture.

Le modèle PDF de facture (sponge) prend la série en devise quand le module est actif et que le taux n'est pas 1. Sur une facture en dollars (taux 1,2) dont nous avions vidé ces montants, la fiche affichait toujours "Montant HT 200,00 €", mais le PDF donnait "P.U. HT 0,00", "Total HT 0,00" et "Total TTC (€) 240,00". Sur une facture en euros, le PDF reste juste : le défaut passe inaperçu, mais l'API renvoie multicurrency_total_ht à 0.

Qui laisse ces montants vides ?

Sur Dolibarr 24, l'API REST les calcule dans les cas courants. Nous avons créé des factures de six façons (lignes dans POST /invoices ou par POST /invoices/{id}/lines, facture en USD, taux 0 envoyé, multicurrency_subprice à 0 envoyé, prix donné seulement en devise) : montants en devise justes à chaque fois. Restent trois sources :

  • une devise sans aucun taux : l'écran de configuration demande un taux, mais POST /multicurrencies sans rate crée la devise sans taux. La facture reçoit alors un taux 0 : notre facture en GBP créée par l'API avait tous ses montants en devise à 0, PDF compris ;
  • le module Import, qui insère les colonnes du fichier telles quelles. Les colonnes en devise y sont facultatives, et celle du prix unitaire en devise est libellée "Taux de change de la devise" ;
  • un script qui écrit directement dans llx_facturedet, sans passer par l'API.

Comment repérer les factures concernées ?

SQL
-- Invoices with an amount but empty currency amounts
SELECT f.rowid, f.ref, f.fk_statut, f.multicurrency_code, f.multicurrency_tx,
       f.total_ht, f.multicurrency_total_ht
FROM llx_facture AS f
WHERE f.total_ht <> 0
  AND (f.multicurrency_total_ht = 0
       OR EXISTS (SELECT 1 FROM llx_facturedet AS d
                  WHERE d.fk_facture = f.rowid
                    AND d.total_ht <> 0 AND d.multicurrency_total_ht = 0));

fk_statut vaut 0 pour un brouillon, 1 pour une facture validée. Sur la base de démonstration, seules nos factures abîmées pour le test sont sorties.

Comment corriger une facture brouillon ou validée sans paiement ?

Pour une devise sans taux, ajoutez d'abord son taux dans la configuration du module. Puis, sur la fiche de la facture, modifiez le champ Taux de change de la devise : gardez le taux, choisissez "Change P.U net (devise) of lines" (libellé à moitié en anglais), puis Modifier. Dolibarr recalcule le prix en devise de chaque ligne à partir du prix HT et du taux, puis les totaux. Nos factures sont repassées à 120 / 240 / 288 $ et, avec le taux 0,87, à 87 / 174 / 208,80 £.

Une facture validée se repasse d'abord en brouillon avec Modifier. Ce bouton n'apparaît que si elle n'a aucun paiement, n'est pas transférée en comptabilité et n'a pas été remplacée. Corrigez le taux, puis Valider : Dolibarr ne tire un nouveau numéro que pour une référence provisoire (PROV...). Notre facture FA2610-0004 a gardé son numéro et retrouvé exactement les montants d'une facture jumelle créée normalement.

Par l'API, le recalcul du taux n'existe pas, et PUT /invoices/{id}/lines/{lineid} remplace tous les champs de la ligne : ce qui n'est pas renvoyé (description, prix d'achat...) est perdu.

Et pour une facture payée ou déjà en comptabilité ?

Au taux 1, les deux séries sont identiques (c'est ce que Dolibarr a calculé pour toutes nos factures en euros) : la copie par SQL est sûre. Sauvegardez la base avant.

SQL
START TRANSACTION;

-- 1. Lines: copy the amounts, only for invoices in the company currency (rate 1)
UPDATE llx_facturedet AS d
JOIN llx_facture AS f ON f.rowid = d.fk_facture
SET d.multicurrency_subprice  = d.subprice,
    d.multicurrency_total_ht  = d.total_ht,
    d.multicurrency_total_tva = d.total_tva,
    d.multicurrency_total_ttc = d.total_ttc
WHERE f.multicurrency_tx = 1
  AND d.total_ht <> 0
  AND d.multicurrency_total_ht = 0;

-- 2. Header: sum of the lines, as update_price() does
UPDATE llx_facture AS f
JOIN (SELECT fk_facture,
             SUM(multicurrency_total_ht)  AS ht,
             SUM(multicurrency_total_tva) AS tva,
             SUM(multicurrency_total_ttc) AS ttc
      FROM llx_facturedet
      GROUP BY fk_facture) AS s ON s.fk_facture = f.rowid
SET f.multicurrency_total_ht  = s.ht,
    f.multicurrency_total_tva = s.tva,
    f.multicurrency_total_ttc = s.ttc
WHERE f.multicurrency_tx = 1
  AND f.total_ht <> 0
  AND f.multicurrency_total_ht = 0;

COMMIT;

La seconde requête refait ce que fait update_price() : le total de la facture est la somme de ses lignes. L'ancienne requête de cette note visait un identifiant écrit en dur, oubliait l'en-tête llx_facture (notre PDF affichait encore "Total HT 0,00") et ignorait le taux : 100 au lieu de 120 $ sur la facture en dollars.

En devise étrangère, pas de requête fiable : Dolibarr recalcule chaque ligne depuis le prix unitaire en devise et arrondit à chaque étape. Multiplier les totaux par le taux donnait 159,99 au lieu de 159,98 sur une de nos lignes. Mieux vaut passer par Dolibarr (avoir puis nouvelle facture).

Comment un connecteur doit-il créer ses factures ?

Par l'API, en laissant Dolibarr calculer. Le prix va dans subprice, dans la devise de la société, et la devise du client dans multicurrency_code. Sans multicurrency_tx, Dolibarr prend le dernier taux connu de la devise (1,2 pour le dollar dans notre test), ou 0 s'il n'en connaît aucun. Avec "multicurrency_tx": 0.87, notre facture en livres était juste malgré l'absence de taux.

JSON
{
  "socid": 1,
  "multicurrency_code": "USD",
  "lines": [
    {"desc": "Prestation", "subprice": 100, "qty": 2, "tva_tx": 20, "product_type": 1}
  ]
}
Terminal
curl -X POST -H "DOLAPIKEY: votre_cle" -H "Content-Type: application/json" -d @facture.json "https://erp.example/api/index.php/invoices"

Après la création, relisez la facture (GET /invoices/{id}) et vérifiez que multicurrency_total_ht n'est pas à 0 quand total_ht ne l'est pas. Ce contrôle a sa place dans tout connecteur qui crée des factures. D'autres requêtes testées sont réunies dans Requêtes SQL utiles pour Dolibarr, et le prix d'achat à 0 dans cette note.

À retenir
  • PDF à 0 : montants en devise vides sur une facture dont le taux n'est pas 1 (devise sans taux, import, écriture directe).
  • Brouillon ou validée sans paiement : ressaisir le taux avec le recalcul des prix en devise.
  • SQL seulement au taux 1, lignes puis en-tête, sur les factures détectées.
  • Connecteur : POST /invoices, Dolibarr calcule, puis contrôle du total en devise.

Testé avec Dolibarr 24.0.2 (module Multidevise activé, données de démonstration) et MariaDB 11.4.13.

Questions fréquentes

Les factures en euros sont-elles concernées ?

Leur PDF reste juste, car Dolibarr imprime les montants dans la devise de la société quand le taux vaut 1. Mais l'API renvoie des montants en devise à 0 aux logiciels qui les lisent : la requête de correction au taux 1 les remet d'aplomb.

Un connecteur doit-il envoyer multicurrency_subprice ?

Non. Dans nos essais, Dolibarr a calculé le prix en devise à partir de subprice et du taux, même quand multicurrency_subprice était envoyé à 0. Il suffit d'envoyer la devise et, si besoin, le taux.

Comment ajouter un taux à une devise par l'API ?

Avec PUT /multicurrencies/{id}/rates et un corps {"rate": 0.93}. Les factures créées ensuite dans cette devise reprennent ce taux.

Peut-on corriger une facture déjà payée en devise étrangère ?

Pas de façon fiable en SQL, car Dolibarr arrondit ligne par ligne. Le plus sûr est de passer par Dolibarr : avoir, puis nouvelle facture créée correctement.

Making Digital

Nous connectons les logiciels des PME, automatisons leurs tâches répétitives et créons des assistants IA, depuis 2010. Nos articles partent de nos projets réels.

Notre parcours
Une question sur ce sujet ?

Parlons-en 30 minutes.

Vous saurez si votre problème se règle, comment, et en combien de temps. Sans engagement.

Un échange de 30 minutes, en visio ou par téléphone

Gratuit, sans engagement. On parle de votre problème, pas de technique.