Ne modifiez ni ne supprimez jamais une écriture financière. Si un paiement, une facture ou un mouvement de stock est faux, corrigez-le en ajoutant une écriture qui l'annule, puis ajoutez la bonne.
Votre historique reste ainsi complet. Les litiges deviennent prouvables, les erreurs faciles à retrouver, et la fraude silencieuse beaucoup plus difficile.
Ce guide explique l'idée simplement et montre le modèle de base de données avec du vrai SQL. Il explique aussi pourquoi c'est encore plus important pour les entreprises en Algérie.
Pourquoi ne faut-il jamais modifier une écriture financière ?
Parce qu'un bouton Modifier sur l'argent détruit la seule chose qui rend un système financier utile. C'est-à-dire la capacité à répondre : que s'est-il passé, quand, et qui l'a fait.
Pensez à un bulletin de notes. Si un enseignant pouvait effacer une note et en écrire une autre sans trace, plus personne ne ferait confiance à un bulletin.
Alors les écoles barrent et paraphent, ou émettent un correctif. L'ancienne note reste visible.
Les clients demandent pourtant sans arrêt un bouton Modifier, sur les factures, les mouvements de stock ou les paiements. La demande paraît raisonnable : un chiffre est faux, on le corrige.
Mais dès qu'une ligne d'argent peut être changée en silence, votre base de données cesse d'être un registre et devient une opinion. Elle ne montre que la dernière chose tapée.
Qu'est-ce qu'un registre en ajout seul ?
Un registre en ajout seul est une table où les mouvements d'argent sont seulement ajoutés, jamais modifiés ni supprimés.
La comptabilité a réglé ce problème bien avant l'informatique. En comptabilité en partie double, chaque mouvement est écrit deux fois, au débit d'un compte et au crédit d'un autre, et les deux doivent s'équilibrer.
Quand il y a une erreur, on ne réécrit pas l'histoire. On passe une nouvelle écriture qui annule l'ancienne, puis la bonne.
En base de données, c'est la même chose :
- Les lignes sont ajoutées. Jamais modifiées, jamais supprimées.
- Un solde n'est pas une colonne stockée. Il se calcule en additionnant les mouvements.
- Une erreur se corrige par une contrepassation (une nouvelle écriture qui annule la mauvaise).
Exemple : un client a été débité de 4 000 DA au lieu de 3 000 DA. Vous ne changez pas la ligne en 3 000. Vous ajoutez une contrepassation de 4 000, puis la bonne écriture de 3 000.
Qui lit plus tard voit le débit, l'erreur, l'annulation et la correction, chacun avec une date et un auteur.
Qu'apporte un registre en ajout seul qu'un bouton Modifier ne peut pas ?
| Ligne modifiable (bouton Modifier) | Registre en ajout seul | |
|---|---|---|
| Corriger une erreur | L'ancienne valeur est écrasée et perdue | Une contrepassation est ajoutée, les deux restent visibles |
| « Qu'est-ce qui était écrit la semaine dernière ? » | Impossible à dire | Une requête par date |
| Qui a changé | Inconnu | Chaque ligne enregistre son auteur |
| Le même paiement envoyé deux fois | Débité deux fois | Rejeté grâce à une référence unique |
| Deux personnes écrivent en même temps | Une modification perdue en silence | Deux lignes, rien de perdu |
| Le solde | Un chiffre qui dérive | Calculé, toujours cohérent |
| Un litige avec un client | Votre parole contre la sienne | Une liste d'événements datés |
| Un employé qui cache de l'argent | Il modifie le chiffre et passe à autre chose | Il lui faut une contrepassation visible |
La dernière ligne est la plus importante en pratique. Une table d'argent modifiable permet à une personne malhonnête de changer un chiffre sans laisser de trace.
Pourquoi est-ce encore plus important en Algérie ?
La loi l'attend déjà des livres du commerçant. L'article 11 du code de commerce algérien prévoit que le livre journal et le livre d'inventaire sont tenus chronologiquement, « sans blanc, ni altération d'aucune sorte » (code de commerce, Livre I). Un logiciel qui laisse réécrire les montants passés va à l'encontre de ce principe.
L'argent circule loin de votre serveur. Avec le paiement à la livraison, argent et marchandise changent de mains à la porte, via un livreur qui ne travaille pas pour vous. Entre « commande passée » et « argent en caisse », il y a beaucoup d'événements : pas de réponse, deuxième tentative, refus, retour, versement hebdomadaire du livreur moins ses frais.
Enregistrez tout ça dans une seule ligne avec un statut que vous écrasez, et quand le versement du livreur ne correspond pas à votre total, vous n'avez rien à vérifier.
Les paiements partiels sont fréquents. Un client paie 5 000 DA d'une commande de 12 000 DA à la porte, puis 4 000 DA une semaine plus tard au magasin, et les 3 000 DA restants n'arrivent jamais. Sur une ligne modifiable, quelqu'un tape 9 000 et l'histoire disparaît. Dans un registre, vous avez trois reçus et un solde restant qui se calcule tout seul.
Le cahier papier était déjà un registre. Dans un cahier, on ne peut pas effacer proprement. Une ligne barrée avec la correction à côté, c'est un registre en ajout seul écrit à l'encre. Remplacez ce cahier par un logiciel avec un bouton Modifier, et vous donnez au commerçant quelque chose de pire que ce qu'il avait.
Comment construire un registre en ajout seul dans une base de données ?
1. Traitez l'argent comme des événements, pas comme un état. Stockez les montants en nombres entiers de centimes, car les nombres décimaux en programmation créent des erreurs d'arrondi sur l'argent.
create table ledger_entries (
id uuid primary key default gen_random_uuid(),
account_id uuid not null references accounts(id),
amount_cents bigint not null check (amount_cents > 0),
direction text not null check (direction in ('credit', 'debit')),
currency char(3) not null default 'DZD',
reference_type text not null,
reference_id uuid not null,
external_ref text unique,
reverses_id uuid references ledger_entries(id),
actor_id uuid references profiles(id),
memo text,
created_at timestamptz not null default now()
);
create index on ledger_entries (account_id, created_at desc);
create index on ledger_entries (reference_type, reference_id);
2. Bloquez modifications et suppressions dans la base elle-même. Ne comptez pas sur le bon comportement de l'application. Un trigger (une règle qui s'exécute automatiquement dans la base) peut refuser toute modification et suppression (documentation PostgreSQL).
create or replace function ledger_is_immutable() returns trigger as $$
begin
raise exception 'ledger_entries is append only: write a compensating entry instead';
end;
$$ language plpgsql;
create trigger ledger_no_update before update or delete on ledger_entries
for each row execute function ledger_is_immutable();
Une règle imposée par la base est une règle. Une règle imposée seulement par l'application est une suggestion.
3. Calculez le solde au lieu de le stocker.
select coalesce(sum(case when direction = 'credit' then amount_cents
else -amount_cents end), 0) as balance_cents
from ledger_entries
where account_id = $1;
Si cela ralentit sur une grosse table, enregistrez un instantané avec la dernière écriture couverte, et additionnez à partir de là. Mettez le chiffre en cache, mais ne laissez jamais le cache devenir la vérité.
Ce modèle est proche de ce que les ingénieurs appellent l'event sourcing : stocker chaque changement comme un événement, pas seulement le dernier état (Martin Fowler).
4. Donnez au client le bouton qu'il demande, en version sûre. Ne lui faites pas de cours de comptabilité. Appelez le bouton « Corriger », laissez-le taper le bon chiffre, et faites-lui écrire une contrepassation et une nouvelle écriture en coulisses. Il a sa correction, vous gardez l'historique.
5. Affichez l'historique à l'écran. Une facture corrigée doit montrer clairement l'original, la correction, la date et la personne. Cette trace est ce qui règle un litige en faveur de votre client.
Quelles erreurs font les développeurs avec l'argent dans un logiciel ?
- Stocker le solde dans une colonne et la mettre à jour. Deux mises à jour simultanées peuvent en perdre une en silence.
- Utiliser des nombres décimaux pour l'argent. Utilisez des entiers en centimes.
- Protéger le registre seulement dans l'application. Bloquez modifications et suppressions dans la base.
- Pas de référence unique sur les événements externes. Un versement de livreur importé deux fois compte deux fois.
- Cacher les corrections aux utilisateurs. La trace visible est la fonction qui met fin aux litiges.
Que faire cette semaine ?
- Aujourd'hui : cherchez dans votre système tout écran qui permet de changer un paiement, une facture ou un mouvement de stock passé.
- Cette semaine : listez chaque table où un solde est stocké au lieu d'être calculé.
- Ce mois-ci : ajoutez une table de registre pour les nouveaux mouvements d'argent, avec le trigger ci-dessus.
- Ensuite : transformez chaque « Modifier » sur l'argent en « Corriger », qui écrit une contrepassation et une nouvelle écriture.
- Enfin : affichez l'historique des corrections sur les factures et les comptes clients.
Pour un exemple concret de l'importance d'une trace écrite dans une petite entreprise, lisez pourquoi les garages ont besoin d'un registre infalsifiable. Et si votre activité tourne encore sur WhatsApp et Excel, commencez par quand WhatsApp et Excel ne suffisent plus.