8.1 KiB
Runbook — quel instrument pour quelle dette
Public : un agent, quel que soit son modèle, ou l'opérateur.
Lire ceci AVANT d'enregistrer quoi que ce soit. Le choix de l'instrument décide de tout ce qui suit : le compte comptable, les rapports où l'écriture apparaîtra, et jusqu'à la voie technique disponible. Une opération parfaitement exécutée avec le mauvais instrument reste une erreur, et elle est plus coûteuse à défaire qu'à éviter.
La question qui tranche
À qui la société doit-elle cet argent ?
| Le créancier est… | Instrument | Écran Dolibarr |
|---|---|---|
| un fournisseur réel (prestataire, éditeur, greffe, La Poste…) | facture fournisseur | Facturation → Factures fournisseur |
| un organisme social ou fiscal (URSSAF, CFE, TVA…) | charge sociale ou fiscale | Comptabilité → Charges sociales/fiscales |
| l'associé lui-même, ou personne (régularisation interne) | paiement divers | Banques → Paiements divers |
Le piège, et il a été payé deux fois
Ni l'URSSAF ni le gérant ne sont des fournisseurs. Leur ouvrir une fiche fournisseur les fait apparaître au grand livre auxiliaire, dans les balances âgées et dans les états de dettes fournisseurs — des états censés ne montrer que le poste fournisseurs. L'erreur est invisible à la saisie et se découvre à la clôture.
Le contrôle qui la révèle est gratuit : regarder l'existant. Les dettes déjà portées au compte courant d'associé sont toutes des factures de fournisseurs réels payées personnellement par le gérant — le tiers y est le fournisseur, jamais le gérant. Un modèle qui contredit celui déjà en place est presque toujours le mauvais.
Une charge sociale est TOTALEMENT figée — écrire juste du premier coup
Caution
Sur ce déploiement (Dolibarr 22.0.4 + PostgreSQL), aucune écriture sur une charge sociale n'aboutit : ni la date, ni le montant, ni même la note publique. Toutes échouent sur
ERROR 42601: multiple assignments to same column "fk_user_modif"—ChargeSociales::update()affecte deux fois la même colonne, ce que MySQL tolère et PostgreSQL rejette. Suivi : erp#87.
La règle générale — « si c'est déjà en production et sans incidence sur
l'exercice, annoter l'objet suffit » — reste juste, mais son canal habituel est
fermé ici. Le champ note passe par le même UPDATE.
Ce qui fonctionne, parce que c'est un autre chemin : attacher un document.
Le téléversement n'est pas un UPDATE sur l'objet.
curl -s -X POST https://erp.arcodange.lab/api/index.php/documents/upload \
-H "DOLAPIKEY: $(cat test/.ai_agent_prod_prod_write.key)" \
-H 'Content-Type: application/json' -d @- <<JSON
{"filename":"NOTE-<sujet>-<date>.md","modulepart":"tax","subdir":"<ID DE LA CHARGE>",
"filecontent":"<BASE64>","fileencoding":"base64","overwriteifexists":1}
JSON
Vérifier sur /compta/sociales/document.php?id=<ID> que le compteur a bougé.
Première application : la charge n°1 (URSSAF 1re échéance) porte le 22/05, date
du prélèvement, quand l'échéance officielle est le 05/05 — l'écart, resté dans
le même mois et le même exercice, est porté par une note attachée plutôt que
forcé dans la donnée.
test/annotateObject.ts écrit la note publique d'un objet et refuse
explicitement quand le bug la bloque, au lieu de croire une page qui ré-affiche
le formulaire. Ce faux positif a bien failli passer : la page de retour contient
le texte soumis, donc un contrôle naïf « le texte est là » réussit sur un
enregistrement qui n'a jamais eu lieu. Relire l'objet, jamais la page de
retour. Le script reste utile sur les objets non affectés par erp#87.
Le compte courant d'associé : deux usages à ne pas confondre
Le compte bancaire CCA1 (id 3) porte le numéro comptable 45511 et son
propre journal comptable. Il sert dans deux cas différents :
1. Le gérant a avancé une dépense — un fournisseur réel a facturé, le gérant
a payé de sa poche. → facture fournisseur au nom du fournisseur, puis
règlement sur le compte 3. C'est adc-005.
2. La société doit quelque chose au gérant lui-même — indemnité d'occupation, remboursement forfaitaire. → paiement divers sur le compte 3, sans aucun tiers.
cd test
DOLIBARR_ADDRESS=https://erp-sandbox.arcodange.lab \
deno run -A recordVariousPayment.ts \
--label "Indemnité d'occupation — mars 2026" \
--amount 220.00 --date 2026-03-31
Production — double opt-in explicite, comme toute écriture de production :
DOLIBARR_ADDRESS=https://erp.arcodange.lab \
ARCO_ALLOW_PRODUCTION=erp.arcodange.lab \
ARCO_PROD_CONFIRM=I-UNDERSTAND-THIS-WRITES-PROD \
deno run -A recordVariousPayment.ts --label "…" --amount … --date …
Défauts : --account 3 (compte courant), --code 613 (Locations),
--sens 0 (débit). --dry-run affiche sans écrire.
L'écriture produite :
débit 613000 Locations (la charge)
crédit 45511 G. RADUREAU, compte courant (la dette envers l'associé)
Le plan comptable est chargé — nuance à connaître
358 comptes sont disponibles dans le sélecteur des paiements divers, dont un
455110 déjà dédié au compte courant du gérant. Ne pas confondre trois choses :
- le plan comptable est chargé et utilisable depuis ce formulaire ;
- l'API REST comptable n'est pas exposée (
/accountancy/*→ 404) ; - le dictionnaire des types de charges sociales ne porte aucun code
comptable (colonne vide pour tous les types,
TAXSSIcompris).
Conclusion pratique : sur un paiement divers, le compte se choisit et est enregistré. Sur une charge sociale, le type n'est qu'un libellé et l'imputation vit dans le grand livre de l'expert-comptable.
Ce que le pipeline gated ne peut pas porter
fleet/harness/promote/ parle REST. Or ni les charges sociales ni les
paiements divers n'ont d'API : /taxes, /socialcontributions,
/chargesociales, /variouspayments répondent tous « API not found ».
Le choix de l'instrument décide donc de la voie disponible. Facture fournisseur → pipeline gated complet, avec juge et artefact de gate. Charge sociale ou paiement divers → script UI, qui garde la discipline (répétition sandbox, relecture par la liste, opt-in production) sans juge indépendant ni gate. Ne pas choisir l'instrument pour la commodité de la voie : c'est la nature de la dette qui décide, et la voie s'ajuste.
Les pièges, tous rencontrés
- Les dates sont un piège à double fond. Le champ visible est décoratif :
le backend ne lit que les champs cachés
{nom}day/{nom}month/{nom}year. Remplir le champ texte seul soumet une date vide. Vaut pourdatep,datev,ech,period. - Vérifier par la LISTE, jamais par l'URL. Dolibarr renvoie des pages sans identifiant : conclure d'après l'URL fait déclarer un échec sur une création réussie — c'est ainsi que quatre doublons sont apparus en sandbox.
- Comparer le libellé ENTIER, jamais un préfixe. Une version comparait les
24 premiers caractères ; « Indemnité d'occupation — » en fait exactement 24,
si bien que mars reconnaissait février et se déclarait déjà enregistré — six
mois silencieusement sautés. Un préfixe ne distingue que ce qui diffère avant
lui. (
recordSocialCharge.tsporte encore ce défaut, latent : ses libellés diffèrent avant le 24ᵉ caractère, aujourd'hui seulement.) - Les milliers s'affichent avec une espace insécable :
1215.00devient « 1 215,00 ». Comparer sans les espaces, sinon l'idempotence saute au-delà de 999 €. - En zsh,
set -- $varne découpe pas les mots (contrairement à bash) : une boucle de saisie a produit des dates2026--. Écrire les appels explicitement, ou utiliser un tableau.
Après l'enregistrement
- Rapprocher le mouvement bancaire réel quand il a lieu — un paiement divers sur le compte courant ne déplace aucune trésorerie, il constate une dette.
- Attacher le justificatif à l'objet concerné : voir
RUNBOOK_ged.md.