Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Le contenu est rédigé en français à destination des **fiduciaires, PME, ind

- **Les exercices se clôturent dans l'ordre : un bilan clos ne change plus en silence ([#543](https://github.com/guycorbaz/kesh/issues/543)).** Le bilan est cumulatif depuis l'origine : toute écriture d'un exercice figure dans le bilan des suivants. Or on pouvait clôturer un exercice en laissant ouvert un exercice antérieur — ou créer un exercice antérieur à un exercice clôturé —, puis écrire dans cet exercice ouvert : le bilan clos changeait sans que rien ne le signale. **La clôture est désormais refusée tant qu'un exercice antérieur est ouvert** : à l'écran, le bouton **Clôturer** est désactivé et son infobulle nomme l'exercice à clôturer d'abord. **La création d'un exercice est refusée** si un exercice postérieur est déjà clôturé. Avec la réouverture, qui allait déjà du plus récent vers l'ancien, aucun exercice ouvert ne peut plus précéder un exercice clôturé **à partir d'une installation saine**. Le refus de modifier ou de supprimer une écriture sous un exercice postérieur clos dit maintenant comment s'en sortir — rouvrir les exercices clôturés **en commençant par le plus récent**, et non celui qu'il nomme, que la réouverture refuserait. ⚠️ Une installation mise à jour ou une sauvegarde restaurée peut porter cet état, hérité d'une version antérieure : il se résorbe en clôturant le plus ancien exercice ouvert.

- **La configuration d'une installation de production s'inscrit au journal d'audit ([#434](https://github.com/guycorbaz/kesh/issues/434)).** Chaque étape de l'assistant — langue, mode d'utilisation, passage en production, type d'organisation, langue comptable, coordonnées, compte bancaire (ou son omission) et finalisation — laisse une entrée *Étape d'installation franchie*, précédée de ce qu'elle a réellement changé : la société créée ou modifiée, le compte bancaire (sans jamais l'IBAN en clair), les réglages de facturation et les taux de TVA effectivement insérés. Le plan comptable livré s'inscrit en **une seule** entrée, *Plan comptable chargé*, qui liste les comptes créés. Quatre actions nouvelles sont libellées dans les quatre langues. Une étape ne laisse plus la société modifiée à moitié : la modification, la progression de l'étape et leur trace sont désormais **une seule transaction**, et l'étape est revérifiée sous verrou — deux demandes simultanées ne chargent plus le plan comptable deux fois. *Le perdant d'une telle course reçoit désormais « étape déjà franchie » au lieu d'un conflit de version.* *La version de la société (`version`, lue par le verrou optimiste de `PUT /company`) n'avance plus lorsqu'une étape ne change rien ; sur une société provisoire dont les coordonnées changent, elle avance désormais de deux.* Le peuplement de démonstration et la remise à zéro restent à tracer (même issue).

- **Un compte non imputable est refusé partout où un client le désigne pour recevoir des écritures ([#427](https://github.com/guycorbaz/kesh/issues/427), [#429](https://github.com/guycorbaz/kesh/issues/429)).** Les écrans filtraient ces comptes, mais le serveur ne les contrôlait pas : un appel direct — par clé d'API ou par une intégration — pouvait rapprocher une transaction bancaire sur **9000 Bilan d'ouverture**, et fausser le résultat de l'exercice et le report à nouveau. Sont désormais refusés en `400 ACCOUNT_NOT_POSTABLE`, qui nomme le compte : le **rapprochement** manuel et ventilé, l'acceptation d'une proposition ventilée ou par règle (dans `failed[]`, sans bloquer le reste du lot) ; les **règles d'affectation** — création, changement de compte, et **réactivation** d'une règle dont le compte n'est plus imputable ; le **compte comptable d'un compte bancaire**, à la création, ou quand on le change. Une règle dont le compte est devenu non imputable — par exemple scindé en sous-comptes — **n'est plus proposée** ; la règle suivante qui correspond l'est à sa place. Les **réglages de facturation** refusent un compte non imputable **au moment où on le désigne** (créance, produit, TVA due, TVA récupérable, décompte TVA, créanciers), avec un message qui nomme le champ. ⚠️ **Limites** : un compte déjà désigné ou déjà lié, devenu non imputable après coup, reste accepté — on peut enregistrer les réglages, modifier le compte bancaire ou renommer la règle sans le changer. La validation d'une facture et la saisie (ou la complétion) d'une facture fournisseur refusent désormais un compte de réglage devenu non imputable (entrée ci-dessous) ; **restent** hors de cette garde l'avoir, le compte de produit par défaut et le compte comptable d'un compte bancaire déjà lié. L'écran des règles affichait « [object Object] » au lieu du message d'un refus : il affiche le message. Sur l'écran des comptes bancaires, un compte lié devenu non imputable s'affichait vide dans les formulaires de modification et de lien : il reste affiché.

- **Un compte de réglage devenu non imputable n'est plus utilisé par les écritures automatiques ([#429](https://github.com/guycorbaz/kesh/issues/429)).** La créance et la TVA due, désignées dans *Paramètres → Facturation*, recevaient l'écriture de chaque facture validée même devenues non imputables — après la création de sous-comptes, la case *imputable* décochée ou le rôle « résultat de l'exercice » attribué —, comme les créanciers et la TVA récupérable pour chaque facture fournisseur. La **validation d'une facture** et la **saisie (ou la complétion) d'une facture fournisseur** les contrôlent désormais au moment d'écrire, et refusent avec un message qui nomme le compte, renvoie à *Paramètres → Facturation* et dit qu'un **administrateur** doit y désigner un compte imputable — la page des réglages lui est réservée. La TVA due (ou récupérable) n'est contrôlée que si la pièce en porte. L'**avoir** n'est pas soumis à ce contrôle, délibérément — une facture émise reste annulable : il crédite la créance que la facture a débitée (entrée ci-dessous, [#473](https://github.com/guycorbaz/kesh/issues/473)), et relit encore la TVA due dans les réglages du moment, ce que corrigera [#525](https://github.com/guycorbaz/kesh/issues/525). ⚠️ **Après la mise à jour, vérifiez dans *Paramètres → Facturation* que les comptes désignés sont imputables** : un compte devenu non imputable (sous-comptes créés, case *imputable* décochée…) doit y être remplacé, faute de quoi la validation des factures (ou la saisie des factures fournisseurs) est refusée. *(API : `400 ACCOUNT_NOT_POSTABLE`, `details.rejected[{accountId, accountNumber}]`, sur `POST /invoices/{id}/validate`, `POST /supplier-invoices` et `POST /imported-supplier-invoices/{id}/complete` — après tous les autres refus, exercice compris.)*
Expand Down
37 changes: 37 additions & 0 deletions _bmad-output/implementation-artifacts/15-7a2-review-prompt-p1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Prompt — revue de code P1, Story 15-7a2

*Versionné le 2026-10-09. Trois lentilles (Sonnet), contexte frais chacune, en lecture seule (bmad-code-review :
Blind Hunter, Edge Case Hunter, Acceptance Auditor). Rotation D6 : passes complètes Sonnet ↔ Opus ; Haiku en passe ciblée.*

Worktree `/home/gcorbaz/devel/kesh-15-7a2`, branche `story/15-7a2-trace-installation-production`. **Le diff à revoir** : `git -C /home/gcorbaz/devel/kesh-15-7a2 diff ec745d0c..a298d19f` (un seul diff aplati ; le code,
les tests, les manuels, la doc — les fiches `_bmad-output/` sont le contexte, pas l'objet). **Fiche** :
`_bmad-output/implementation-artifacts/15-7a2-trace-installation-production.md` (AC, tâches, Dev Agent Record, Change Log). Issues (par
`gh api repos/guycorbaz/kesh/issues/N`) : #434. Registre : `epic-15-choix-autonomes.md`. Règles : `CLAUDE.md`. Choix C-15-7-*, C-15-7a1-*, C-15-7a2-1 à 3. Code touché : crates/kesh-api/src/routes/onboarding.rs (neuf routes en une transaction, lock_state_at_step, record_step_completed_in_tx, conclude_step, macro company_select!), ACTIONS et quatre .ftl, registre des routes 104/6/2, tests onboarding_audit_e2e.rs, Pattern 5, manuels FR et PDF, CHANGELOG. Axes : chaque route est-elle vraiment atomique (aucune lecture ni écriture sur le pool pendant la transaction ; rejeu éventuel et booléen « inséré » relu à chaque tentative) ; changements de comportement (400 au lieu de 409 pour le perdant d'une course, version +2 sur stub) — sont-ils annoncés au CHANGELOG et au frontend qui lit ces codes (`grep -rn ONBOARDING_ frontend/src`) ? ; ordre des verrous (état d'onboarding, société, comptes) contre les autres écrivains ; la partition du registre recomptée ; libellés d'audit dans les 4 locales ; manuel et PDF aplati.

## Lentilles

- **B — Blind Hunter** : le diff seul, sans la fiche. Défauts de correction, régressions, erreurs de concurrence
(verrous, REPEATABLE READ, ordre d'acquisition), erreurs rendues au client, tests qui passeraient à vide (un test qui
ne mord pas sur la mutation qu'il prétend couvrir), code mort, duplication (DRY), doc-comments devenus faux.
- **E — Edge Case Hunter** : chaque branche et chaque borne du code modifié — entrées vides, nulles, multiples, en
doublon, d'une autre société, archivées ; chemins par clé d'API ; lots partiellement en échec ; locales ; et les
**chemins NON modifiés qui devraient l'être** (inventorier les sites non résolus de la même famille par `grep`).
- **A — Acceptance Auditor** : chaque AC de la fiche contre le code ET les tests (un AC sans test qui le prouve est
un finding) ; le Dev Agent Record ne déclare-t-il que ce qui a tourné (chiffres recomptés : `grep -c '#\[sqlx::test\]\|#\[test\]\|#\[tokio::test\]'` aux deux bornes) ;
le **manuel** (`docs/manual/fr/*.tex` **et PDF aplatis** : `pdftotext -nopgbrk f.pdf - | tr '\n' ' ' | tr -s ' '` vers
`target/gate-logs/`, ligatures ff/fi/fl normalisées), `docs/api-external.md`, CHANGELOG, i18n 4 locales.

## Ce que tu rends

Rapport complet dans `target/gate-logs/15-7a2-review-p1-<B|E|A>.md` : findings numérotés, sévérité
(CRITICAL/HIGH/MEDIUM/LOW), `fichier:ligne`, **preuve** (sortie de `grep -nF` pour toute affirmation de présence ou
d'absence ; code cité relu), correction proposée ; ⛔ **axes exercés ET non exercés**. Dernier message : le chemin, le
bilan par sévérité, une ligne par MEDIUM+.

## Interdits

⛔ N'écris aucun fichier hors `target/gate-logs/`. Aucune commande qui écrit dans le dépôt ou dans une base, ni
aucune commande qui compile ou exécute des tests : `scripts/*` (dont `scripts/prepare-release.sh`), `make`,
`latexmk`, `git commit`/`add`/`checkout`/`stash`/`apply`, `sqlx`, `cargo`, `npm`, `npx`,
`gh issue create`/`comment`/`edit`, SQL d'écriture. Autorisés : lecture, `grep`, `sed -n`, `git log`/`show`/`diff`,
`gh api` en lecture, `pdftotext` vers `target/gate-logs/`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Prompt — revue de code P2 ciblée, Story 15-7a2

*Versionné le 2026-10-09. Passe ciblée (CLAUDE.md § « La passe ciblée ») : une seule lentille (Haiku), contexte
frais, en lecture seule, braquée sur le seul commit de la remédiation P1 — qui ne touche que des tests et de la
documentation.*

Worktree `/home/gcorbaz/devel/kesh-15-7a2`, branche `story/15-7a2-trace-installation-production`. **Objet** :
`git show 23b3e46e` (diff unique ; ouvre `crates/kesh-api/tests/onboarding_audit_e2e.rs` à `HEAD` autour des
hunks). Rapports remédiés : `target/gate-logs/15-7a2-review-p1-{B,E,A}.md`. Choix C-15-7a2-4.

## Lentille unique — chasseur de régressions de la remédiation

1. **Test 14** `demo_installation_is_refused_by_every_production_step` : chaque route est-elle appelée à son
étape EXACTE (sinon le 400 viendrait de la garde d'étape et non de `require_not_demo`, et la mutation ne
serait pas distinguée) ? Le contrôle « même requête, `is_demo` levé → 200 » est-il fait pour chacune ? La
liste de six routes est-elle exacte contre `crates/kesh-api/src/routes/onboarding.rs`
(`grep -n "require_not_demo\|lock_state_at_step" `) ?
2. **Tests 9 (c) et 9 (d)** : le déclencheur fait-il échouer la BONNE écriture (`account.chart_loaded` pour (c),
l'entrée d'étape pour (d)) ? Les assertions (« 0 compte », « état inchangé ») pourraient-elles être vraies
par construction, comme le test 9 d'origine ?
3. **Test 13 étendu** (pool d'une connexion, neuf routes) : chaque route atteint-elle vraiment son code
transactionnel, ou s'arrête-t-elle avant (refus d'étape) — auquel cas le test ne prouve rien pour elle ?
4. **Test 1** : les `details` comparés « en entier aux lignes en base » le sont-ils vraiment (toutes les clés),
ou le test relit-il ce qu'il a écrit ?
5. **Aucune ligne de production touchée** : `git diff -U0 a298d19f 23b3e46e -- 'crates/*/src'` doit être vide.

## Ce que tu rends

Findings numérotés (CRITICAL/HIGH/MEDIUM/LOW), `fichier:ligne`, **preuve** (sortie de `grep -nF` ; code relu cité),
correction proposée. ⛔ **Liste des axes exercés ET non exercés** — un « 0 » sans elle ne compte pas. Rapport
complet dans `target/gate-logs/15-7a2-review-p2-ciblee.md` ; dernier message : le chemin, le bilan, une ligne par MEDIUM+.

## Interdits

⛔ N'écris aucun fichier hors `target/gate-logs/`. Aucune commande qui écrit dans le dépôt ou dans une base, ni qui
compile ou exécute des tests : `scripts/*` (dont `scripts/prepare-release.sh`), `make`, `latexmk`,
`git commit`/`add`/`checkout`/`stash`, `sqlx`, `cargo`, `npm`, `npx`, `gh issue create`/`comment`/`edit`, SQL
d'écriture. Autorisés : lecture, `grep`, `sed -n`, `git log`/`show`/`diff`.
Loading
Loading