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 @@ -42,6 +42,8 @@ Le contenu est rédigé en français à destination des **fiduciaires, PME, ind

⚠️ **Le rappel PDF ne part qu'avec un rappel envoyé par e-mail.** Pour une mise en demeure envoyée hors de Kesh ou un contact sans e-mail, le PDF imprimable reste celui de la facture, au montant total ([#477](https://github.com/guycorbaz/kesh/issues/477)). ⚠️ **Un modèle de rappel personnalisé** qui écrit `{reminderFee}` en toutes lettres affiche toujours « 0.00 » sans frais : la nouvelle variable `{feeNotice}` est vide dans ce cas.

- **Le rapprochement bancaire ne reconnaissait pas le virement qui soldait une facture déjà réglée en partie ([#420](https://github.com/guycorbaz/kesh/issues/420)).** Une facture de 1 000.— TTC réglée de 400.— n'était même pas proposée pour un virement de 600.— — exactement ce que le client devait encore —, parce que la recherche comparait le montant d'origine : il fallait rapprocher à la main un paiement parfaitement identifiable. Le rapprochement cherche et note désormais les factures sur leur **reste dû** ; la proposition affiche ce reste, suivi du total d'origine (« 600, reste dû sur 1000 ») quand la facture est déjà réglée en partie. *(API : le champ `invoiceAmount` des propositions porte désormais le reste dû — identique au TTC tant que rien n'est réglé — et le nouveau champ `invoiceTotalTtc` le total d'origine, seulement quand les deux diffèrent.)* Le manuel décrit enfin le score tel qu'il est calculé — il annonçait un score gradué, un critère de date et des seuils de confiance qui n'existent pas.

### 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*.
Expand Down

Large diffs are not rendered by default.

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

*Versionné le 2026-09-30. Trois lentilles en parallèle, **Sonnet**, contexte frais. Diff : le commit
d'implémentation seul, `git diff 7aa56d2f 63a6d6a7 -- . ':!*.pdf'` (1142 lignes), écrit dans
`/tmp/claude-1000/-home-gcorbaz-devel-kesh/379e6f94-8029-42cb-9720-fa27c2fb204c/scratchpad/25-4-c-p1.diff`.*

## Commun aux trois lentilles

**Rendu** : findings avec sévérité (CRITICAL/HIGH/MEDIUM/LOW), endroit exact (`fichier:ligne`),
**preuve** (code lu cité, commande et sortie), correction proposée. ⛔ **La liste des axes réellement
exercés ET de ceux qui ne l'ont pas été** — un rapport sans elle ne compte pas.

**Interdits** : n'écrire 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`, `gh issue create`/`comment`/`edit`. Autorisés : lecture, `grep`,
`git log`/`show`/`diff`, `gh issue view`, `pdftotext` vers le scratchpad, `cargo check`.

## Lentille 1 — Blind Hunter (`bmad-review-adversarial-general`)

Reçoit **le diff seul**, aucun contexte projet. Revue adversariale générale : défauts logiques, SQL,
cas limites, tests qui ne prouvent pas ce qu'ils annoncent, incohérences entre commentaires et code.

## Lentille 2 — Edge Case Hunter (`bmad-review-edge-case-hunter`)

Reçoit le diff **et** l'accès en lecture au dépôt. Parcourir chaque branche et chaque frontière :

- la requête de `find_unpaid_invoices_for_window` (`crates/kesh-db/src/repositories/reconciliation.rs`) :
ambiguïté de colonnes avec les trois tables dérivées, `HAVING` sans `GROUP BY` sur des `LEFT JOIN`,
facture sans ligne, avoir émis (facture `cancelled`), reste négatif, `LIMIT 50` ;
- **tous les lecteurs** de `UnpaidInvoiceCandidate` et de `invoice_amount` / `invoiceAmount` —
`grep -rn "total_ttc\|amount_due\|invoiceAmount\|invoiceTotalTtc\|UnpaidInvoiceCandidate" crates/ frontend/src` ;
- le re-score à l'acceptation (`accept_one_invoice`, `crates/kesh-api/src/routes/reconciliation.rs`) :
ordre des gardes (score avant trop-perçu), reste nul ou négatif, facture sans ligne ;
- `invoiceTotalTtc` : égalité `Decimal` à échelles différentes (`600.0000` contre `600`), sérialisation ;
- le frontend (`ReconciliationProposals.svelte`) : rendu, espaces, i18n (4 catalogues, clé
`reconciliation-labels-amount-due-of`), garde `i18n-keys.test.ts` ;
- le Playwright (`frontend/tests/e2e/reconciliation-amount-due.spec.ts`) : dépendance à l'état partagé
de la base, collisions de montants, exercice couvrant le 2026-05-10, sélection du compte bancaire.

## Lentille 3 — Acceptance Auditor

Reçoit le diff, la fiche `_bmad-output/implementation-artifacts/25-4-c-residuel-au-rapprochement.md`
et l'accès en lecture au dépôt. Vérifier chaque AC (1 à 6) contre le code, les « Ce qu'il ne faut pas
faire » (aucun `FOR UPDATE`, aucun arrondi, forme jointe, score binaire), le Dev Agent Record
(affirme-t-il seulement ce qui a tourné ? décomptes recomptés depuis la source ?).

⛔ **Le manuel** : `docs/manual/fr/user-manual.tex` (section *Réconciliation bancaire* et le
paragraphe *Ce que réclame un rappel*) et `docs/manual/fr/marketing-brochure.tex:167` — chaque
affirmation contre le code (critères, poids, fenêtre, tolérance, « créditrice, en CHF », « pas de
seuil ni d'acceptation automatique », QR du rappel, versement reste + frais). **Contrôler le PDF**,
aplati : `pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '` (et la brochure),
vers le scratchpad. Le CHANGELOG `[0.12.1]` dit-il vrai ?
66 changes: 66 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-c-review-prompt-p2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Prompts — revue de code P2, Story 25-4-c (le résiduel au rapprochement)

*Versionné le 2026-09-30. Deux lentilles en parallèle (Blind Hunter, Edge Case Hunter), **Haiku 4.5**, contexte frais. Diff : l'implémentation et la remédiation P1
`git diff 7aa56d2f 8d33460c -- . ':(exclude)*.pdf' ':(exclude)_bmad-output'` (diff UNIQUE aplati, implémentation + remédiation P1 — règle Haiku du CLAUDE.md), écrit dans
`/tmp/claude-1000/-home-gcorbaz-devel-kesh/379e6f94-8029-42cb-9720-fa27c2fb204c/scratchpad/25-4-c-p2.diff`.*

## Commun aux trois lentilles

**Rendu** : findings avec sévérité (CRITICAL/HIGH/MEDIUM/LOW), endroit exact (`fichier:ligne`),
**preuve** (code lu cité, commande et sortie), correction proposée. ⛔ **La liste des axes réellement
exercés ET de ceux qui ne l'ont pas été** — un rapport sans elle ne compte pas.

**Interdits** : n'écrire 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`, `gh issue create`/`comment`/`edit`. Autorisés : lecture, `grep`,
`git log`/`show`/`diff`, `gh issue view`, `pdftotext` vers le scratchpad, `cargo check`.

## Lentille 1 — Blind Hunter (`bmad-review-adversarial-general`)

Reçoit **le diff seul**, aucun contexte projet. Revue adversariale générale : défauts logiques, SQL,
cas limites, tests qui ne prouvent pas ce qu'ils annoncent, incohérences entre commentaires et code.

## Lentille 2 — Edge Case Hunter (`bmad-review-edge-case-hunter`)

Reçoit le diff **et** l'accès en lecture au dépôt. Parcourir chaque branche et chaque frontière :

- la requête de `find_unpaid_invoices_for_window` (`crates/kesh-db/src/repositories/reconciliation.rs`) :
ambiguïté de colonnes avec les trois tables dérivées, `HAVING` sans `GROUP BY` sur des `LEFT JOIN`,
facture sans ligne, avoir émis (facture `cancelled`), reste négatif, `LIMIT 50` ;
- **tous les lecteurs** de `UnpaidInvoiceCandidate` et de `invoice_amount` / `invoiceAmount` —
`grep -rn "total_ttc\|amount_due\|invoiceAmount\|invoiceTotalTtc\|UnpaidInvoiceCandidate" crates/ frontend/src` ;
- le re-score à l'acceptation (`accept_one_invoice`, `crates/kesh-api/src/routes/reconciliation.rs`) :
ordre des gardes (score avant trop-perçu), reste nul ou négatif, facture sans ligne ;
- `invoiceTotalTtc` : égalité `Decimal` à échelles différentes (`600.0000` contre `600`), sérialisation ;
- le frontend (`ReconciliationProposals.svelte`) : rendu, espaces, i18n (4 catalogues, clé
`reconciliation-labels-amount-due-of`), garde `i18n-keys.test.ts` ;
- le Playwright (`frontend/tests/e2e/reconciliation-amount-due.spec.ts`) : dépendance à l'état partagé
de la base, collisions de montants, exercice couvrant le 2026-05-10, sélection du compte bancaire.

## Lentille 3 — Acceptance Auditor

Reçoit le diff, la fiche `_bmad-output/implementation-artifacts/25-4-c-residuel-au-rapprochement.md`
et l'accès en lecture au dépôt. Vérifier chaque AC (1 à 6) contre le code, les « Ce qu'il ne faut pas
faire » (aucun `FOR UPDATE`, aucun arrondi, forme jointe, score binaire), le Dev Agent Record
(affirme-t-il seulement ce qui a tourné ? décomptes recomptés depuis la source ?).

⛔ **Le manuel** : `docs/manual/fr/user-manual.tex` (section *Réconciliation bancaire* et le
paragraphe *Ce que réclame un rappel*) et `docs/manual/fr/marketing-brochure.tex:167` — chaque
affirmation contre le code (critères, poids, fenêtre, tolérance, « créditrice, en CHF », « pas de
seuil ni d'acceptation automatique », QR du rappel, versement reste + frais). **Contrôler le PDF**,
aplati : `pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '` (et la brochure),
vers le scratchpad. Le CHANGELOG `[0.12.1]` dit-il vrai ?

## Spécifique à la P2

- La lentille 3 (Acceptance Auditor) n'est pas rejouée : elle a rendu 0 finding en P1, preuves à l'appui.
- ⚠️ **Toute affirmation qu'un code est ABSENT, ou qu'un anti-pattern est PRÉSENT, doit citer le
`grep -nF` qui le prouve, avec sa sortie** — lu sur le fichier courant du dépôt (lentille 2) ou sur
le diff (lentille 1), jamais sur un numéro de ligne de hunk.
- Poids particulier sur ce qu'a écrit la remédiation P1 : l'emplacement de l'entrée #420 dans
`CHANGELOG.md` (section `### Fixed` de `[0.12.1]`, rendu Markdown), les libellés EN/DE de
`reconciliation-labels-amount-due-of`, et la boucle de remplacements du Playwright (la contrepartie
`<Nm>` = le nom du contact : le score de contact rend-il le test moins probant ? la fixture
contient-elle chaque motif exactement là où on l'attend ?).
63 changes: 63 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-c-validate-prompt-p1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Prompt — validation P1, Story 25-4-c (le résiduel au rapprochement)

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

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-c-residuel-au-rapprochement` (sur `main`, b2
mergée). Fiche à valider : `_bmad-output/implementation-artifacts/25-4-c-residuel-au-rapprochement.md`.
Mère : `25-4-propager-le-residuel.md`. Sœurs : `25-4-a-residuel-juste.md`,
`25-4-b1-residuel-aux-agregats.md`, `25-4-b2-residuel-aux-rappels.md`. Issues : `gh issue view 420`,
`gh issue view 476`. Contexte : `24-2-encaissement-client.md`, les stories de l'Epic 8 sur le
rapprochement (`ls _bmad-output/implementation-artifacts/8-*`). Règles : `CLAUDE.md` (notamment le
§ *Pattern batch*). Checklist : `.claude/skills/bmad-create-story/checklist.md`.

Les arbitrages Q1–Q3 de la fiche sont **retenus** : ne pas les contester, en contester la mise en œuvre.

## Axes — tous obligatoires

1. **Chaque référence `fichier:ligne`** existe et dit ce que la fiche affirme.
2. **Inventaire des sites qui comparent un montant bancaire à une facture client** — pars du
symptôme, pas de la liste de la fiche :
`grep -rn "total_ttc\|amount_due\|invoice_amount\|invoiceAmount\|amount_score\|OVERPAYMENT" crates/ frontend/src`.
Pour chaque site : couvert par la fiche, légitimement au TTC, ou oublié (au moins MEDIUM).
Existe-t-il d'autres chemins qui rapprochent ou règlent une facture client (import CAMT avec
référence QR, accept_batch, règlement manuel, page de la facture, tableau de bord) ?
3. **La forme jointe (AC 1)** : `amount_due_derived_joins()` et `INVOICE_AMOUNT_DUE_DERIVED_SQL`
s'insèrent-ils réellement dans la requête de `find_unpaid_invoices_for_window` (GROUP BY, HAVING,
paramètres liés, `company_id` des tables dérivées) ? Le scoping multi-tenant reste-t-il prouvé ?
4. **Le re-score (AC 2)** : `amount_due` scalaire dans la transaction — verrou, isolation, ordre des
gardes (score avant trop-perçu). Une course entre deux acceptations concurrentes sur la même
facture change-t-elle de comportement ?
5. **L'arrondi (AC 5, 6)** : les cinq sites sont-ils les seuls ? Cherche toute comparaison
`<= 0`, `> amount_due`, `== Decimal::ZERO` sur un reste dû (`grep -rn "due_after\|amount_due" crates/`).
La stratégie `MidpointAwayFromZero` est-elle cohérente avec la QR émise par la b2 (le rappel) et
par la facture ? Un reste de 0.004 : arrondi à 0.00, la facture est-elle soldée — et qui pose
`paid_at`, l'audit `invoice.paid` ? Le reste **affiché** (AC 3) est-il arrondi aussi ?
6. **L'affichage (AC 3, Q3)** : le libellé « reste dû sur » — clé i18n, 4 locales,
`lint-i18n-ownership`, formatage suisse des montants ; le type frontend doit-il porter le TTC en
plus du reste (champ API nouveau → documentation `api-external` s'il y en a) ?
7. **Les tests (AC 7)** : chacun est-il faisable et prouve-t-il ce qu'il annonce ? Le cas 10.0050 :
peut-on réellement fabriquer une facture dont le reste dû brut a 4 décimales (lignes, TVA) ?
L'E2E Playwright : peut-on monter un règlement partiel puis un import bancaire ? Mutations tuables ?
8. **Le manuel (AC 8)** : lignes citées, et **PDF aplati**
(`pdftotext docs/manual/fr/user-manual.pdf - | tr '\n' ' ' | tr -s ' '`, vers
`/tmp/claude-1000/-home-gcorbaz-devel-kesh/379e6f94-8029-42cb-9720-fa27c2fb204c/scratchpad/`).
Le paragraphe du score est-il bien faux sur le code, point par point ? D'autres textes (manuels
de/en/it, admin-manual, README, website, CHANGELOG) décrivent-ils le rapprochement sur le TTC ?
9. **Le périmètre** : cinq modules annoncés — recompte-les depuis les tâches. Quelque chose de la
25-4-d (solder le reste) appartient-il ici, ou l'inverse ?

## Ce que tu rends

- **Findings** : sévérité (CRITICAL/HIGH/MEDIUM/LOW), endroit exact, **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é.** Un rapport sans elle
ne compte pas.

## 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`.
56 changes: 56 additions & 0 deletions _bmad-output/implementation-artifacts/25-4-c-validate-prompt-p2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Prompt — validation P2, Story 25-4-c (le résiduel au rapprochement)

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

Dépôt `/home/gcorbaz/devel/kesh`, branche `story/25-4-c-residuel-au-rapprochement`. Fiche à valider :
`_bmad-output/implementation-artifacts/25-4-c-residuel-au-rapprochement.md` — **lis le fichier dans
son état actuel**, ne raisonne pas sur un diff. Ce que la passe 1 a changé : `git show 36f9ce31 --
_bmad-output/implementation-artifacts/25-4-c-residuel-au-rapprochement.md` (à lire comme contexte ;
les numéros de ligne font foi dans le fichier courant, pas dans le diff). Règles : `CLAUDE.md`.

Les arbitrages Q1–Q3 sont **retenus** : ne pas les contester, en contester la mise en œuvre.

## Axes — tous obligatoires

1. **La remédiation de la passe 1** — c'est là que la sévérité se déplace :
- AC 5 : le helper « sur `Money::round_to_centimes()` » est-il réalisable depuis `kesh-db`
(`crates/kesh-db/Cargo.toml`, API de `Money` dans `crates/kesh-core/src/types/money.rs`) ?
Rebrancher `reminder_amount_due` (`crates/kesh-api/src/routes/invoice_pdf_service.rs:112`)
change-t-il son comportement (refus ≤ 0, tests `:892-900`) ?
- AC 5, dialogue : comment le frontend obtient-il le reste arrondi (`amountDue` est une chaîne à
4 décimales) ? `Big` arrondit-il dans le même sens que `MidpointAwayFromZero` (mode par défaut
de big.js) ? Le message d'erreur et ses clés i18n restent-ils justes ?
- AC 6 : l'annulation laissant 0.0040 — ce scénario est-il **constructible** (règlements de
quels montants, sur quelle facture) ? Sinon l'AC promet un test impossible.
- AC 5-bis : lis `accept_one_invoice` (`crates/kesh-api/src/routes/reconciliation.rs`, env.
`:1056-1600`), `settle_invoice` (`invoice_settlements_write.rs:40-260`) et
`reconciliation_cancel.rs:250-330`. **Quel ordre de verrous prennent-ils réellement**
(bank_transactions, invoices, fiscal_years, journal) ? L'AC le laisse au dev : faut-il le
trancher dans la fiche ? Un test de concurrence est-il faisable avec `#[sqlx::test]` (deux
transactions, pool) — existe-t-il un précédent dans le dépôt (`grep -rn "tokio::join\|join!" crates/*/tests`) ?
2. **Sites encore oubliés** : `grep -rn "amountDue\|amount_due\|due_after\|due_before" crates/ frontend/src`
— toute comparaison du reste dû à zéro ou à un montant, hors des sept sites de l'AC 5, est-elle
légitime ou oubliée ?
3. **Faisabilité des tests (AC 7)** — axe non exercé en P1 : l'E2E Playwright peut-il monter une
facture partiellement réglée puis un import bancaire ? Cherche les helpers existants
(`frontend/tests/e2e/`, fixtures CAMT, `authedApiContext`). Les mutations annoncées sont-elles
tuables par les tests prévus ?
4. **Cohérence interne** : numéros d'AC référencés par les tâches, section « Arbitrages », Change
Log, modules (recompte), aucune phrase contradictoire entre l'inventaire et les AC.

## Ce que tu rends

- **Findings** : sévérité, endroit exact, **preuve** (commande exécutée et sa sortie, ou code lu cité),
correction proposée. Pour toute affirmation qu'un élément est **absent**, cite le `grep -nF` qui le
prouve.
- ⛔ **La liste des axes réellement exercés ET de ceux qui ne l'ont pas été.** Un rapport sans elle
ne compte pas.

## 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