Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9c4df11
docs(25-4): découpée en a/b/c ; 25-4-a spécifiée — l'avoir compté TTC…
guycorbaz Sep 26, 2026
0f4b9ec
docs(25-4-a): prompt de validation P1 (refs #455, refs #456)
guycorbaz Sep 26, 2026
73172c8
docs(25-4): Q1 tranchée — QR sans montant sur une relance partielleme…
guycorbaz Sep 26, 2026
1ed7313
docs(25-4): le reste à payer figure aussi sur le PDF joint à la relan…
guycorbaz Sep 26, 2026
f288117
docs(25-4): le document joint est un rappel pour un montant partiel, …
guycorbaz Sep 26, 2026
b62db3c
docs(25-4-a): validation P1 — #455 exposé par l'API, bouton d'avoir a…
guycorbaz Sep 26, 2026
ca66c11
docs(25-4-a): prompt de validation P2 ; plages de monter harmonisées …
guycorbaz Sep 26, 2026
7503be9
docs(25-4): la QR du rappel porte le reste dû, une règle pour les deu…
guycorbaz Sep 26, 2026
5c337d6
docs(25-4): frais de rappel configurables, rien d'affiché à zéro (ref…
guycorbaz Sep 26, 2026
451e2cc
docs(25-4-a): validation P2 — facture auxiliaire du gabarit, amountDu…
guycorbaz Sep 26, 2026
1344b3a
docs(25-4-a): prompt de validation P3 ciblée (refs #455, refs #456)
guycorbaz Sep 26, 2026
9df357e
docs(25-4-a): validation P3 ciblée — propagation des corrections P1 (…
guycorbaz Sep 26, 2026
b18f7cd
docs(25-4): avoir sur facture réglée refusé en 25-4-a (levée : #471) …
guycorbaz Sep 26, 2026
5ed4a70
docs(25-4-a): prompt de validation P4 ciblée (refs #455, refs #456)
guycorbaz Sep 26, 2026
ab9b944
docs(25-4-a): validation P4 — close en 4 passes, prête pour le dev (r…
guycorbaz Sep 26, 2026
9bf2bb2
feat(25-4-a): le reste dû compte l'avoir TTC, et l'avoir est refusé s…
guycorbaz Sep 26, 2026
21ee264
docs(25-4-a): prompt de la revue de code P1 (refs #455, refs #456)
guycorbaz Sep 26, 2026
41e14e4
docs(25-4-a): revue P1 à zéro au-dessus de LOW — story done (refs #45…
guycorbaz Sep 26, 2026
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ Le contenu est rédigé en français à destination des **fiduciaires, PME, ind

- **Sur la fiche d'une facture fournisseur, le bouton *Annuler la facture* s'affichait aussi pour un utilisateur en consultation**, qui ne pouvait que se heurter à un refus ; et un refus effaçait toute la fiche au profit d'un message d'erreur. Le bouton est désormais réservé aux comptables et administrateurs, et un refus s'affiche sous le bouton, la fiche restant visible.

- **Une facture créditée gardait sa TVA en « reste dû » ([#455](https://github.com/guycorbaz/kesh/issues/455)).** Le reste dû retranchait l'avoir **hors taxes** d'un total **TTC** : une facture de 100.— HT à 8,1 %, entièrement créditée, restait due de 8.10, alors que le grand livre, lui, avait soldé la créance. L'écran ne l'affichait que dans un cas rare, mais ⚠️ **l'API le rendait toujours** : `GET /api/v1/invoices/{id}`, ouverte aux clés API en lecture, renvoyait la TVA dans `amountDue` pour toute facture créditée. **Si une intégration lisait ce champ, ses chiffres étaient faux.** Le reste dû compte désormais l'avoir TTC, arrondi ligne par ligne comme son écriture.

- **Un avoir pouvait viser une facture déjà réglée en partie ([#456](https://github.com/guycorbaz/kesh/issues/456)), et le compte du client devenait créditeur sans que rien ne le signale.** L'avoir était refusé sur une facture **payée**, mais pas sur une facture réglée **en partie** — qui, depuis le règlement partiel, n'est « payée » qu'une fois soldée. Comme l'avoir annule tout le montant de la facture, le client se retrouvait avec un crédit du montant déjà encaissé, que Kesh ne sait ni montrer, ni rembourser. L'avoir est désormais refusé dès qu'un règlement existe, avec un message qui dit quoi faire : annuler d'abord le règlement. *(Autoriser l'avoir sur une facture encaissée, avec le remboursement ou l'imputation qu'il appelle, est suivi par [#471](https://github.com/guycorbaz/kesh/issues/471).)*

### Changed

- **Le bouton *Créer un avoir* s'affiche aussi sur une facture payée**, et c'est voulu. Il était masqué sur une facture payée mais pas sur une facture réglée en partie : l'écran ne couvrait que la moitié de la règle. Il reste désormais visible, et Kesh explique le refus dans le dialogue — comme le bouton *Dévalider*.

- **Supprimer une facture validée n'est plus possible — il faut la « dévalider » d'abord.** Jusqu'ici, le bouton *Supprimer* d'une facture validée effaçait la facture **et son écriture comptable** d'un seul geste. La destruction d'une écriture était donc un **effet de bord du mot « supprimer »** : rien, dans le vocabulaire de l'écran, ne disait qu'on touchait aux livres.

Le geste existe toujours, mais il porte désormais son nom. Le bouton **« Dévalider »** repasse la facture en **brouillon**, supprime son écriture, et **conserve son numéro** — en la revalidant, elle reprend *le même*, sans consommer le compteur. Deux sorties s'ouvrent alors : corriger puis revalider, ou supprimer le brouillon.
Expand Down
527 changes: 527 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-a-residuel-juste.md

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-a-review-prompt-p1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Prompt — revue de code P1, Story 25-4-a (le résiduel juste)

*Versionné le 2026-09-27. **Une lentille** (Sonnet), contexte frais.*

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-propager-le-residuel`. Diff à relire :
`git diff ab9b9448 9bf2bb2b` (commit de dev, après la validation close). Fiche :
`_bmad-output/implementation-artifacts/25-4-a-residuel-juste.md` (AC, Dev Notes, Dev Agent Record).
Issues : `gh issue view 455`, `gh issue view 456`. Règles : `CLAUDE.md`. **Arbitrages de Guy** (fiche
§ Arbitrage, fiche mère `25-4-propager-le-residuel.md`) : ne pas les contester.

## Axes — tous obligatoires

1. **SQL** : les quatre constantes produites par `line_ttc_sql!` (`invoices.rs`,
`invoice_settlements.rs`) — développe-les à la main et vérifie le texte exact (espaces, alias,
`\` de continuation dans un `concat!`), l'égalité **octet pour octet** des deux constantes TTC
facture avec leur forme d'avant (`git show ab9b9448:crates/kesh-db/src/repositories/invoices.rs`),
et l'agrégation de la forme jointe de l'avoir (GROUP BY, jointure, filtre `issued`).
2. **La garde** (`credit_notes.rs`) : ordre verrou → lecture verrouillante, scoping `company_id`,
chemins d'erreur, rien écrit en cas de refus. Les tests prouvent-ils ce qu'ils annoncent, ou
peuvent-ils passer à vide (surtout l'entrelacement : que se passe-t-il si
`attendre_une_requete_en_cours` voit une AUTRE requête que celle de l'avoir) ?
3. **Tous les lecteurs** des grandeurs changées : `grep -rn "INVOICE_CREDITED\|amount_due\|INVOICE_TTC" crates/`
— un appelant change-t-il de valeur sans test ? Et tout appelant de `create_credit_note`, ou qui
matchait `IllegalStateTransition` pour le cas « payée » (API, frontend, tests) ?
4. **La fixture `monter`** : le gabarit tient-il pour les quinze cas ? Un motif lit-il la facture
auxiliaire ?
5. **Le manuel dit-il vrai ?** `docs/manual/fr/user-manual.tex` — les passages modifiés (§ Avoirs, les
deux limites, les deux « cas hérité ») contre le code ; **le PDF aplati**
(`pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '`, vers
`/tmp/claude-1000/-home-gcorbaz-devel-kesh/ca5ce2e2-67a3-4eeb-817f-c2de35620a1c/scratchpad/`),
`??` compris. Le renvoi `\S\ref{sec:reglement-client}` pointe-t-il où il faut ? Le CHANGELOG
décrit-il juste (l'API, le bouton) ?
6. **i18n** : la clé ×4 — sens, registre du glossaire (`docs/i18n-glossaire.md` § Registre), terme
« avoir » du glossaire.
7. **Frontend** : le bouton, les commentaires, les `data-testid` ; les Vitest tuent-ils vraiment m6 ?
8. **Dev Agent Record** : chaque décompte (tests, mutations, gates) **recompté** depuis la source.

## Ce que tu rends

- **Findings** : sévérité (CRITICAL / HIGH / MEDIUM / LOW), fichier:ligne, **preuve** (commande et
résultat, code lu), correction proposée.
- ⛔ **La liste des axes réellement exercés ET de ceux qui ne l'ont pas été.**

## Interdits

⛔ N'écris aucun fichier du dépôt ; aucune commande qui écrit dans le dépôt ou dans une base —
`scripts/prepare-release.sh`, `scripts/regen-test-schema.sh`, `scripts/install-hooks.sh`,
`scripts/test-fast.sh`, `scripts/mem-guard.sh`, `make`, `latexmk`, tout `git commit`/`push`/`add`/
`stash`/`reset`/`rebase`/`checkout`/`switch`/`worktree`, `sqlx migrate`, `cargo test`/`nextest`,
`npm run`, `npx playwright`. Autorisés : lecture, `grep`, `git log`/`show`/`diff`, `gh issue view`,
`pdftotext` vers le scratchpad, `cargo check`, `cargo expand` s'il est installé.
50 changes: 50 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-a-validate-prompt-p1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Prompt — validation P1, Story 25-4-a (le résiduel juste)

*Versionné le 2026-09-26. **Une lentille** (Sonnet), contexte frais.*

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-propager-le-residuel`. Fiche à valider :
`_bmad-output/implementation-artifacts/25-4-a-residuel-juste.md`. Fiche mère (inventaire,
découpage) : `25-4-propager-le-residuel.md`. Issues : `gh issue view 455`, `gh issue view 456`.
Contexte de la grandeur : `24-2-encaissement-client.md` § D3, D4, AC 5-7. Règles du dépôt :
`CLAUDE.md`. Checklist BMAD : `.claude/skills/bmad-create-story/checklist.md`.

## Axes — tous obligatoires

1. **Chaque référence `fichier:ligne`** existe et dit ce que la fiche affirme — relis le code.
2. **La formule** : la sous-requête TTC de l'avoir prescrite (AC 1-2) concorde-t-elle réellement,
centime par centime, avec l'écriture de l'avoir (`generate_credit_note_journal_lines`,
`line_vat_amount` — lis `kesh-core`, sens d'arrondi de `ROUND` MariaDB vs Rust) ? Et avec
`INVOICE_TTC_SUBQUERY_SQL` ? Un écart d'un centime possible est un finding.
3. **La garde** (AC 9-11) : inventorie **tous** les chemins qui créent un règlement ou un avoir
(pars du symptôme : `grep -rn "INSERT INTO invoice_settlements\|create_credit_note\|INSERT INTO credit_notes" crates/`),
et leur sérialisation (verrou pessimiste ou optimiste). La fiche en nomme trois : en manque-t-il ?
Le raisonnement REPEATABLE READ de § Courses est-il juste ?
4. **L'état hérité** : l'import d'une sauvegarde ramène-t-il vraiment l'état (règlement + avoir) ?
Les textes prescrits (AC 17) le disent-ils juste ? D'autres lecteurs de `amount_due` ou des
constantes changent-ils de valeur avec l'AC 1 (inventaire : `grep -rn "INVOICE_CREDITED\|amount_due" crates/ frontend/src`) ?
5. **Les tests** (AC 16) : chacun prouve-t-il ce qu'il annonce, ou peut-il passer à vide ? Les
mutations m1-m6 sont-elles tuables par les tests listés ? Une mutation que rien ne tuerait est
un finding.
6. **Le manuel** : les lignes citées (AC 17) existent-elles et disent-elles ce qu'on veut changer ?
Contrôle aussi le **PDF aplati** (`pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '`,
vers `/tmp/claude-1000/-home-gcorbaz-devel-kesh/ca5ce2e2-67a3-4eeb-817f-c2de35620a1c/scratchpad/`).
Une autre phrase du manuel ou de l'admin-manual, de l'api-external, du README, promet-elle
l'ancien comportement ?
7. **Le découpage** (fiche mère) : quelque chose de 25-4-a appartient-il en fait à b ou c, ou
l'inverse ? La latence de #455 est-elle correctement établie ?

## Ce que tu rends

- **Findings** : sévérité (CRITICAL / HIGH / MEDIUM / LOW), l'endroit exact de la fiche, **la
preuve** (commande et résultat, code lu), la correction proposée.
- ⛔ **La liste des axes réellement exercés ET de ceux qui ne l'ont pas été.** Un « 0 finding »
sans elle ne compte pas.

## Interdits

⛔ N'écris aucun fichier du dépôt ; n'exécute aucune commande qui écrit dans le dépôt ou dans une
base — `scripts/prepare-release.sh`, `scripts/regen-test-schema.sh`, `scripts/install-hooks.sh`,
`scripts/test-fast.sh`, `scripts/mem-guard.sh`, `make`, `latexmk`, tout `git commit`/`push`/`add`/
`stash`/`reset`/`rebase`/`checkout`/`switch`/`worktree`, `sqlx migrate`, `cargo test`/`nextest`,
`npm run`, `npx playwright`. Autorisés : lecture, `grep`, `git log`/`show`/`diff`, `gh issue view`,
`pdftotext` vers le scratchpad, `cargo check`.
66 changes: 66 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-a-validate-prompt-p2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Prompt — validation P2, Story 25-4-a (le résiduel juste)

*Versionné le 2026-09-26. **Une lentille** (Haiku), contexte frais.*

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-propager-le-residuel`. Fiche à valider :
`_bmad-output/implementation-artifacts/25-4-a-residuel-juste.md`. Fiche mère (inventaire,
découpage) : `25-4-propager-le-residuel.md`. Issues : `gh issue view 455`, `gh issue view 456`.
Contexte de la grandeur : `24-2-encaissement-client.md` § D3, D4, AC 5-7. Règles du dépôt :
`CLAUDE.md`. Checklist BMAD : `.claude/skills/bmad-create-story/checklist.md`.

## Axes — tous obligatoires

1. **Chaque référence `fichier:ligne`** existe et dit ce que la fiche affirme — relis le code.
2. **La formule** : la sous-requête TTC de l'avoir prescrite (AC 1-2) concorde-t-elle réellement,
centime par centime, avec l'écriture de l'avoir (`generate_credit_note_journal_lines`,
`line_vat_amount` — lis `kesh-core`, sens d'arrondi de `ROUND` MariaDB vs Rust) ? Et avec
`INVOICE_TTC_SUBQUERY_SQL` ? Un écart d'un centime possible est un finding.
3. **La garde** (AC 9-11) : inventorie **tous** les chemins qui créent un règlement ou un avoir
(pars du symptôme : `grep -rn "INSERT INTO invoice_settlements\|create_credit_note\|INSERT INTO credit_notes" crates/`),
et leur sérialisation (verrou pessimiste ou optimiste). La fiche en nomme trois : en manque-t-il ?
Le raisonnement REPEATABLE READ de § Courses est-il juste ?
4. **L'état hérité** : l'import d'une sauvegarde ramène-t-il vraiment l'état (règlement + avoir) ?
Les textes prescrits (AC 17) le disent-ils juste ? D'autres lecteurs de `amount_due` ou des
constantes changent-ils de valeur avec l'AC 1 (inventaire : `grep -rn "INVOICE_CREDITED\|amount_due" crates/ frontend/src`) ?
5. **Les tests** (AC 16) : chacun prouve-t-il ce qu'il annonce, ou peut-il passer à vide ? Les
mutations m1-m6 sont-elles tuables par les tests listés ? Une mutation que rien ne tuerait est
un finding.
6. **Le manuel** : les lignes citées (AC 17) existent-elles et disent-elles ce qu'on veut changer ?
Contrôle aussi le **PDF aplati** (`pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '`,
vers `/tmp/claude-1000/-home-gcorbaz-devel-kesh/ca5ce2e2-67a3-4eeb-817f-c2de35620a1c/scratchpad/`).
Une autre phrase du manuel ou de l'admin-manual, de l'api-external, du README, promet-elle
l'ancien comportement ?
7. **Le découpage** (fiche mère) : quelque chose de 25-4-a appartient-il en fait à b ou c, ou
l'inverse ? La latence de #455 est-elle correctement établie ?

## Ce que tu rends

- **Findings** : sévérité (CRITICAL / HIGH / MEDIUM / LOW), l'endroit exact de la fiche, **la
preuve** (commande et résultat, code lu), la correction proposée.
- ⛔ **La liste des axes réellement exercés ET de ceux qui ne l'ont pas été.** Un « 0 finding »
sans elle ne compte pas.

## Interdits

⛔ N'écris aucun fichier du dépôt ; n'exécute aucune commande qui écrit dans le dépôt ou dans une
base — `scripts/prepare-release.sh`, `scripts/regen-test-schema.sh`, `scripts/install-hooks.sh`,
`scripts/test-fast.sh`, `scripts/mem-guard.sh`, `make`, `latexmk`, tout `git commit`/`push`/`add`/
`stash`/`reset`/`rebase`/`checkout`/`switch`/`worktree`, `sqlx migrate`, `cargo test`/`nextest`,
`npm run`, `npx playwright`. Autorisés : lecture, `grep`, `git log`/`show`/`diff`, `gh issue view`,
`pdftotext` vers le scratchpad, `cargo check`.

## Contexte P1 — à vérifier, pas à re-signaler

La passe 1 a trouvé 1 HIGH (récit « #455 latent » faux : `get_invoice` rend `amountDue` aux clés
API), 3 MEDIUM (`error_code()` et non `code()` ; AC 14 aligné sur le précédent « Dévalider » ;
AC 13, `monter` sert quinze cas et un avoir `issued` exige une écriture) et 1 LOW. Les corrections
sont dans `git diff 0f4b9ec0 HEAD -- _bmad-output/implementation-artifacts/25-4-*.md` — **diff unique
aplati, à lire en priorité** : une correction introduit souvent le défaut suivant.

**Tes priorités** : (1) le **gabarit « détacher, créditer, rattacher »** de l'AC 13 — est-il
réalisable (contraintes d'unicité et FK d'`invoice_settlements`, `company_id`, écriture de
règlement qui pointe l'ancienne facture ?) et compatible avec les quatre paires combinées ?
(2) l'AC 14 révisé — le dialogue d'avoir affiche-t-il vraiment le message du serveur, et que
voit l'utilisateur sur une facture **entièrement** payée, où le bouton était masqué jusqu'ici ?
(3) l'e2e `get_credited_invoice_reports_zero_amount_due` — la forme JSON exacte de `amountDue`
(sérialisation de `Decimal`) pour que l'assertion ne soit pas fragile.
49 changes: 49 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-a-validate-prompt-p3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Prompt — validation P3 CIBLÉE, Story 25-4-a (le résiduel juste)

*Versionné le 2026-09-27. **Une lentille** (Opus), contexte frais. Passe **ciblée** (CLAUDE.md
§ « La passe ciblée ») : la P2 n'a trouvé qu'un défaut **né de la correction P1** ; ce qu'il reste à
relire est la remédiation, pas la story entière.*

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-propager-le-residuel`. Fiche :
`_bmad-output/implementation-artifacts/25-4-a-residuel-juste.md`. **Périmètre** : le diff aplati
des remédiations P1 et P2 —
`git diff 0f4b9ec0 451e2cc2 -- _bmad-output/implementation-artifacts/25-4-a-residuel-juste.md _bmad-output/implementation-artifacts/25-4-propager-le-residuel.md`
(ignore les paragraphes de la fiche mère qui consignent les arbitrages de Guy sur 25-4-b : **ne pas
les contester**).

## La lentille : chasseur de régressions de remédiation

Pour chaque passage réécrit en P1 ou P2 :

1. **Est-il vrai contre le code ?** Relis les sites qu'il cite : `get_invoice`
(`crates/kesh-api/src/routes/invoices.rs`), `docs/api-external.md`, le bouton et le dialogue
d'avoir (`frontend/src/routes/(app)/invoices/[id]/+page.svelte`), la fixture `monter` et
`la_precedence_de_l_annulation_lecture_et_ecriture` (`crates/kesh-db/tests/invoice_settlement.rs`),
la migration `20260827000001_invoice_settlements.sql`, `settlement_cancel_blocker`
(`invoice_settlements_write.rs`), `kesh-api/Cargo.toml` (`serde-str`).
2. **Le gabarit « détacher, créditer, rattacher » (AC 13)** : exécute-le **mentalement** pas à pas
contre `create_credit_note` et les quatre paires combinées de `monter`. Une FK, une contrainte,
un audit, un contrôle de `company_id`, une lecture de `invoice_settlements` par
`create_credit_note` ou par les motifs montés **après** peut-il le casser ? L'écriture de
règlement porte-t-elle quelque part l'identifiant de la facture d'origine (description, audit,
`invoice_settlements` seul) ?
3. **AC 14 révisé** : cohérent avec l'AC 11, l'AC 12, les tests de l'AC 16 et la mutation m6/m7 ?
Un test de l'AC 16 porte-t-il encore l'ancienne logique (« bouton absent ») ?
4. **AC 8 révisé** : l'assertion prescrite peut-elle passer à vide (`null`, champ absent) ?
5. **Propagation** : chaque correction a-t-elle été reportée partout où le symptôme était écrit
(tâches T1-T9, tableau « Où regarder », Change Log, fiche mère, `sprint-status.yaml`) ? Greppe la
**valeur** (`code()`, `:98`, `937-990`, `latent`, `masqué`), pas la formulation.

## Ce que tu rends

- **Findings** : sévérité, endroit exact, **preuve** (commande et résultat, code lu), correction.
- ⛔ **La liste des axes réellement exercés ET de ceux qui ne l'ont pas été.**

## Interdits

⛔ N'écris aucun fichier du dépôt ; aucune commande qui écrit dans le dépôt ou dans une base —
`scripts/prepare-release.sh`, `scripts/regen-test-schema.sh`, `scripts/install-hooks.sh`,
`scripts/test-fast.sh`, `scripts/mem-guard.sh`, `make`, `latexmk`, tout `git commit`/`push`/`add`/
`stash`/`reset`/`rebase`/`checkout`/`switch`/`worktree`, `sqlx migrate`, `cargo test`/`nextest`,
`npm run`, `npx playwright`. Autorisés : lecture, `grep`, `git log`/`show`/`diff`, `gh issue view`,
`cargo check`.
Loading
Loading