diff --git a/.claude/skills/dolibarr-sandbox-write/RUNBOOK_quel_instrument.md b/.claude/skills/dolibarr-sandbox-write/RUNBOOK_quel_instrument.md new file mode 100644 index 0000000..257f485 --- /dev/null +++ b/.claude/skills/dolibarr-sandbox-write/RUNBOOK_quel_instrument.md @@ -0,0 +1,128 @@ +# 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. + +## 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. + +```bash +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 : + +```bash +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, `TAXSSI` compris). + +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 + +1. **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 pour + `datep`, `datev`, `ech`, `period`. +2. **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. +3. **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.ts` porte encore ce défaut, latent : ses libellés + diffèrent avant le 24ᵉ caractère, aujourd'hui seulement.)* +4. **Les milliers s'affichent avec une espace insécable** : `1215.00` devient + « 1 215,00 ». Comparer sans les espaces, sinon l'idempotence saute au-delà de + 999 €. +5. **En zsh, `set -- $var` ne découpe pas les mots** (contrairement à bash) : une + boucle de saisie a produit des dates `2026--`. É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`. diff --git a/AGENTS.md b/AGENTS.md index 7f48676..fffc124 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,6 +27,7 @@ The [AI back-office PRD](https://gitea.arcodange.lab/arcodange-org/factory/src/b - **Prod is read-only for agents** (`ai_agent` key from `.claude/skills/dolibarr/.env`, mode 600). Beware the `voir_tous` ACL trap: a missing permission returns empty lists, not errors. - **Writes rehearse on the sandbox first** (`ai_agent_sandbox`, host-guarded — structurally cannot reach prod), then reach prod only through the human-gated promote flow (`arcodange promote plan|apply`, prod key ENV-only + explicit confirm) — [ADR-0003](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/ADR/0003-sandbox-state-lifecycle.md). - **Production is an append-only ledger**: create → validate → pay → avoir; never mutate or delete a validated document, never fabricate a ref Dolibarr owns. Full grammar + anti-hallucination write contract (provenance anchors, fresh-feed corroboration, refuse-never-repair): PRD [compliance](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/compliance.md) + [agent-architecture](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/agent-architecture.md). +- **Choose the accounting instrument before writing, and read the existing state to check the choice.** *Who does the company owe?* A real supplier → supplier invoice; URSSAF or the tax office → social charge; **the associé himself → various payment on `CCA1`, with no thirdparty at all**. Neither URSSAF nor the gérant is a supplier: giving either a supplier record pollutes the auxiliary ledger, the aged balances and the payables reports, and is far costlier to undo than to avoid. The check that catches it is free — **an entry whose model contradicts the entries already in the ledger is almost always wrong**. This also decides the technical path: `/chargesociales` and `/variouspayments` have **no REST API**, so the gated promote cannot carry them (UI scripts keep the sandbox rehearsal and prod opt-in, but have no judge and no gate artefact). [RUNBOOK_quel_instrument.md](.claude/skills/dolibarr-sandbox-write/RUNBOOK_quel_instrument.md), `adc-010`. - Sandbox state is disposable: `bin/arcodange sandbox checkpoint {status|refresh|provision|relink-env}` (refresh re-seeds iso-prod and wipes the write agent → re-provision, human login). Anything irreversible-by-design is trialed on a checkpoint first. - Bank feeds (Qonto/Wise) and the Zoho mailbox are **read-only by construction**; no agent ever moves money. - **Doc freshness.** Docs describe intent; the PRD STATUS + git describe reality. Before acting on any versionable claim (a path exists, a flag's value, a status emoji), verify in trust order: **live system > code/git log > [PRD STATUS](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/STATUS.md) > PRD leaves > memories**. A PR that makes a documented claim false updates that doc **in the same PR**; whoever closes a milestone follows the QA-gated [closure protocol](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/vibe/PRD/ai-back-office/STATUS.md) — the QA gate is held by an **independent context-free subagent prompted to refute** (the closer never self-certifies) → flip STATUS → truth-pass docs → deprecation grep → fresh-reader smoke test — before the milestone closes. diff --git a/fleet/profile/calendar.yaml b/fleet/profile/calendar.yaml index 068473b..1c71d07 100644 --- a/fleet/profile/calendar.yaml +++ b/fleet/profile/calendar.yaml @@ -188,6 +188,15 @@ entries: # le gérant cotise. Le point erp#57 est clos sur la partie cadence ; reste à qualifier # la nature exacte des cotisations avec l'expert-comptable si besoin. + - id: "remuneration-gerant-decision-2027" + title: "Décision associé unique — rémunération du gérant (reportée à 2027)" + category: "legal" + status: "confirmed" + due: "2027-01-31" + authority: "associé unique" + source: "décision de l'opérateur du 2026-08-13 : « On actera en 2027, pas de rémunération en 2026 »" + notes: "L'exercice 2026 se clôture SANS rémunération de mandat — conforme à la décision n°1 du 09/01/2026 (« le gérant n'est pas rémunéré au titre de son mandat social »), désormais assumée pour l'exercice entier. Conséquences à porter : aucun trimestre de retraite validé en 2026 ; les cotisations URSSAF 2026 (3 041 EUR, provisoires sur forfait) seront régularisées sur une assiette quasi nulle, donc probablement À LA BAISSE. L'indemnité d'occupation (220 EUR/mois, adc-010) n'est PAS une rémunération et n'entre pas dans l'assiette TNS. À arbitrer en 2027 avec l'expert-comptable : verser ou non une rémunération, et son montant." + # --- Contract-driven (KissMetrics) ---------------------------------------- - id: "km-fac005-due" diff --git a/fleet/profile/decisions/adc-010-dette-envers-l-associe.md b/fleet/profile/decisions/adc-010-dette-envers-l-associe.md new file mode 100644 index 0000000..8bb362b --- /dev/null +++ b/fleet/profile/decisions/adc-010-dette-envers-l-associe.md @@ -0,0 +1,124 @@ +--- +id: adc-010 +title: "Une dette envers l'associé s'enregistre en paiement divers, jamais en facture fournisseur" +status: Accepted +decided: 2026-08-13 +effective_from: 2026-01-01 +effective_until: null +supersedes: null +superseded_by: null +--- + +# adc-010 — Instrument d'enregistrement d'une dette envers l'associé + +## Context + +La convention annexée aux statuts (annexe 3) et la décision n°1 de l'associé +unique du 09/01/2026 fixent une **indemnité d'occupation de 220 EUR/mois** pour +un bureau de 10 m² dans le domicile du gérant. Au 13/08/2026 elle n'avait jamais +été ni versée ni comptabilisée : sept mois échus, 1 483,23 EUR. + +Question posée : par quel instrument l'enregistrer ? La première réponse — une +fiche fournisseur au nom du gérant et sept factures fournisseur réglées par le +compte courant, sur le modèle d'`adc-005` — a été **rejetée par l'opérateur** +avant d'atteindre la production. + +## Decision + +Une dette envers l'**associé lui-même** s'enregistre en **paiement divers** +(*Banques → Paiements divers*) sur le compte bancaire `CCA1` (id 3, numéro +comptable 45511), avec le code comptable de la charge et le sens débit. + +**Aucune fiche tiers n'est créée pour le gérant.** + +Pour l'indemnité d'occupation, le code est **613000 — Locations** : + +``` +débit 613000 Locations (la charge) +crédit 45511 G. RADUREAU, compte courant (la dette envers l'associé) +``` + +**Limite qui inverse la décision :** si le créancier est un **fournisseur réel** +que le gérant a payé de sa poche, la décision ne s'applique pas — c'est +`adc-005` : facture fournisseur au nom du **fournisseur**, réglée sur le compte +courant. Le compte courant sert dans les deux cas ; ce qui change est le +créancier. + +## Base légale & doctrine + +Le compte **455 — Associés, comptes courants** est le compte des sommes dues à +l'associé (PCG). Le poste **fournisseurs (401)** enregistre les dettes +d'exploitation envers des tiers ayant fourni biens ou services dans le cadre +d'une relation commerciale. Le gérant qui met à disposition une partie de son +domicile n'entre pas dans cette catégorie : il n'est pas fournisseur de sa +société, et la convention qui les lie n'est pas un contrat de fourniture. + +Porter cette dette au compte fournisseurs la ferait figurer au grand livre +auxiliaire, dans les balances âgées fournisseurs et dans les états de dettes +fournisseurs — des états dont la sincérité suppose qu'ils ne montrent que le +poste fournisseurs. + +C'est le même raisonnement qu'`adc-008` et que +`RUNBOOK_charges_sociales.md` opposent déjà à l'URSSAF, qui n'est pas davantage +un fournisseur. + +## Alternatives rejected + +- **Fiche fournisseur au nom du gérant + factures fournisseur** — première + proposition. Rejetée : pollue le grand livre auxiliaire, et contredit la règle + déjà posée pour l'URSSAF. Un `403` sur le droit 122 l'a arrêtée avant la + production, pour une raison qui n'était pas la bonne. +- **Une écriture unique de 1 483,23 EUR** — rejetée : la convention stipule une + indemnité *mensuelle*. Sept écritures datées de chaque fin de mois suivent le + fait générateur et restent lisibles à la clôture. +- **Attendre un décaissement réel pour enregistrer** — rejetée : la charge est + engagée par la convention, indépendamment du versement. Ne pas l'enregistrer + laissait une dette invisible et une charge déductible non prise. + +## Consequences + +- **Le choix de l'instrument décide de la voie technique.** + `/variouspayments` répond « API not found », comme `/chargesociales` : le + pipeline gated `fleet/harness/promote/`, qui parle REST, **ne peut pas porter + cette opération**. Elle passe par `test/recordVariousPayment.ts`, qui garde la + répétition sandbox, la relecture par la liste et l'opt-in production explicite, + mais **sans** juge indépendant ni artefact de gate. La couverture du promote + gated est plus étroite qu'elle en a l'air. +- **Le plan comptable est chargé** — 358 comptes sélectionnables depuis ce + formulaire, dont un `455110` dédié au compte courant du gérant. À ne pas + confondre avec l'API REST comptable (absente) ni avec le dictionnaire des types + de charges sociales (sans code comptable). `adc-009` confond les trois et doit + être corrigé. +- Le montant du forfait est justifié dans le libellé et dans la note du PR : + loyer 1 100 EUR, quote-part de surface 16,67 % → 183,33 EUR, charges réelles + 12,53 EUR au prorata, soit 195,87 EUR de prorata strict contre 220 EUR retenus + (+12,3 %). +- Côté personnel du gérant, l'indemnité est un revenu **BNC** — sous-location + d'un local nu par un locataire, BOI-RFPI-CHAMP-10-30 § 80. Elle n'entre **pas** + dans l'assiette des cotisations TNS (CSS art. L131-6 renvoyant à L136-3, qui + vise les revenus d'activité professionnelle). Question ouverte : l'inscription + au compte courant vaut-elle encaissement au sens du BNC, régime de trésorerie ? + +## QA & validation + +- **Le contrôle qui aurait dû venir en premier : lire l'existant.** Les 8 dettes + déjà portées au compte courant sont toutes des factures de fournisseurs réels ; + le tiers n'y est jamais le gérant. Un modèle qui contredit celui déjà en place + est presque toujours le mauvais, et la vérification coûte une requête. +- **Le juge pré-gate n'a pas vu le défaut structurel.** Il a rendu BLOCK sur la + chronologie (art. 289, qui régit les factures émises et non la référence de + classement des factures reçues) et laissé passer le choix d'instrument. Un juge + qui lit le change-set sans lire l'état observé ne peut pas détecter une + contradiction avec le modèle existant. +- Répétition sandbox puis production, chaque écriture relue **dans la liste**. + Contrôle final : tiers et factures fournisseur inchangés (12 et 15), compte + courant porté de −429,75 à −1 912,98 EUR. + +## References + +- Convention et décision n°1 : statuts, annexes 2 et 3 — versées en GED sous + `Juridique/Decisions` et `Juridique/Domiciliation`. +- Mode opératoire : `.claude/skills/dolibarr-sandbox-write/RUNBOOK_quel_instrument.md`. +- Voie du compte courant pour une dépense avancée : `adc-005`. +- Dossier de preuve du change-set abandonné : + `fleet/harness/runs/2026-08-13-indemnite-occupation/ABANDONNE.md`.