Aller au contenu
← Tous les articles

24 sept. 2026
2 min de lecture

  • Fintech
  • Multi-currency
  • PostgreSQL
  • TypeScript
  • Architecture

À Goma, un client peut payer moitié en CDF, moitié en USD. Les flottants, les arrondis et les taux qui bougent cassent la comptabilité en silence. Voici le modèle que j’utilise.

Dans la plupart des tutoriels, l'argent est un number avec un symbole. Dans l'Est du Congo, ce modèle casse dès le premier jour : les prix sont annoncés en dollars, la monnaie est rendue en francs, et le taux bouge pendant la semaine.

En construisant des caisses et des trésoreries pour des produits comme Hela et Nunua, j'ai fini par adopter quelques règles que j'applique désormais partout.

1. Ne jamais stocker l'argent en flottant

0.1 + 0.2 ne vaut pas 0.3 en JavaScript, et cette erreur s'accumule sur des milliers de ventes. On stocke des entiers dans la plus petite unité :

type Money = {
  amount: bigint | number; // unités mineures : cents pour l'USD, francs pour le CDF
  currency: 'USD' | 'CDF';
};

En PostgreSQL, c'est un bigint (ou numeric si vraiment nécessaire), jamais un real.

2. Une conversion est un événement avec son propre taux

L'erreur la plus fréquente : enregistrer un paiement en USD et recalculer sa valeur en CDF plus tard avec le taux du jour. Six mois après, les rapports ne correspondent plus aux reçus que les clients ont en main.

À la place, chaque conversion enregistre le taux utilisé :

type Payment = {
  id: string;
  paid: Money;          // ce que le client a réellement donné
  settles: Money;       // ce que cela règle sur la facture
  rate: string;         // ex. "2850" CDF pour 1 USD, stocké en chaîne décimale
  rateSource: 'manual' | 'daily';
  at: Date;
};

Les rapports additionnent settles — aucune conversion à la lecture, aucune dérive.

3. Décider qui absorbe l'arrondi

10 USD à 2 850 donnent exactement 28 500 CDF. 7,35 USD donnent 20 947,5 — et le franc n'a pas de demi. Quelqu'un gagne ou perd ce demi-franc.

Choisissez une règle, écrivez-la, appliquez-la dans une seule fonction :

  • arrondir en faveur du client à la caisse ;
  • garder la différence dans une ligne arrondi explicite, pour que les comptes restent équilibrés.

4. Un paiement mixte, ce sont plusieurs paiements

« La moitié en dollars, le reste en francs » paraît compliqué, mais ce sont deux lignes Payment sur la même facture. La facture est réglée quand la somme des settles atteint le total. La monnaie rendue est un paiement négatif dans la devise rendue.

5. Toujours afficher les deux

Les caissiers pensent dans les deux devises. Chaque total à l'écran affiche la devise de la facture et son équivalent au taux actuel, avec le taux visible. Cela supprime toute une catégorie de litiges au comptoir.

Check-list

  • Entiers en unités mineures, typés avec leur devise
  • Taux enregistré à chaque conversion, jamais recalculé
  • Une seule fonction d'arrondi, avec une ligne d'arrondi explicite
  • Paiement mixte = plusieurs lignes de paiement
  • Les deux devises et le taux visibles à l'écran

Rien de tout cela n'est exotique. Mais sauter une de ces règles passe très bien en démo — et échoue la première fois qu'un comptable rapproche un mois de ventes réelles.