feat(budget) : adopter le repli multi-niveaux sur la grille Budget #289

Open
opened 2026-07-14 00:41:40 +00:00 by maximus · 0 comments
Owner

Refs: spec-decisions-collapse-multi-niveaux.md + spec-plan-collapse-multi-niveaux.md (plan v2)

Depends on

  • #288 (socle du repli multi-niveaux — cette issue en est le consommateur)

Contexte

La grille Budget (src/components/budget/BudgetTable.tsx) est hierarchique (elle lit deja depth/is_parent/parent_id, indente sur 4 niveaux) mais fut deliberement exclue du repli par #278. Avec ~150 lignes d'un bloc, cette decision est revue : la grille adopte le meme repli multi-niveaux, meme defaut (tout replie).

Compromis assume

Seules les feuilles sont editables (BudgetTable.tsx:105 filtre !r.is_parent ; les parents l.175 ne rendent que du texte). Tout replie ⇒ la page ouvre sur 11 lignes racines sans champ de saisie visible. Accepte : page compacte, etat persiste (cout paye une seule fois), « Tout deplier » a un clic et visible d'emblee.

Correction critique heritee de /review-spec

Le plan v1 croyait la grille Budget alimentee par budgetService.buildSubGroup. Faux : elle est construite par le hook useBudget.ts:134-365, un 3e builder que le plan v1 ignorait. Son tri final (l.345-365) est par niveau (depth croissant), PAS DFS. C'est ce qui a casse l'algo v1. L'algo v2 (remontee d'ancetres, cf. #288) est order-independant → aucun changement de tri requis, mais l'invariant doit etre acte par un test.

Travail a faire

  • src/hooks/useBudget.tslire et documenter l'invariant d'ordre (tri par niveau, l.345-365). Avec la remontee d'ancetres, aucun changement de tri — mais l'acter par un test (la v1 s'y etait trompee). Ajouter src/hooks/useBudget.ts aux fichiers concernes.
  • BudgetTable.tsx — brancher useCollapsibleGroups ; declarer BUDGET_COLLAPSE_ACCESSORS + BUDGET_EXPANDED_KEY inline au module scope (comme ComparePeriodTable:64 et BudgetVsActualTable:35). Ne PAS creer budgetTableModel.ts : overTimeTableModel.ts existe pour de la vraie logique (groupOverTimeSections), pas pour 3 lambdas.
  • Chevron + aria-expanded sur toute ligne parente dans renderRow (l.168-205) — parents = texte pur aujourd'hui.
  • Bouton « Tout deplier / Tout replier » (reutiliser reports.collapse.expandAll/.collapseAll).
  • Remplacer le sous-total de section fait-main (l.301-311) par sumLeavesForType de budgetTableResults.ts:42 — deja teste, prouve le critere « sous-totaux sur lignes brutes ».
  • Corriger la collision localStorage : BudgetTable.tsx:21 et BudgetVsActualTable.tsx:30 declarent tous deux STORAGE_KEY = "subtotals-position" → prefixer celle du budget en budget-subtotals-position (comme ComparePeriodTable:60 prefixe deja la sienne). Effet de bord : la preference de position revient a son defaut une fois.
  • CHANGELOG.md + CHANGELOG.fr.md.

Fichiers concernes

  • src/hooks/useBudget.ts (lu + teste)
  • src/components/budget/BudgetTable.tsx
  • src/components/budget/budgetTableResults.ts (lu — sumLeavesForType:42)
  • src/i18n/locales/{fr,en}.json, CHANGELOG.md, CHANGELOG.fr.md

Tests

  • budgetTableResults : sumLeavesForType couvre deja les sous-totaux de section — le brancher prouve l'invariant.
  • Regression : replier un parent n'altere aucune valeur saisie ; totaux de section + lignes de resultat (#278) identiques replie/deplie.
  • Regression : ordre des lignes de useBudget est par niveau (documente l'invariant que la v1 a suppose a tort).
  • Regression : deplacer les sous-totaux dans la grille Budget n'affecte plus le rapport reel-vs-budget.

Review caveats

  • 🔴 3e builder (useBudget) absent du plan v1 → ajoute ici. C'est la source de l'ordre par niveau.
  • 🟡 budgetTableModel.ts : abandonne (accesseurs inline comme les 2 autres tables).
  • 🟡 Sous-total fait-main (l.301-311) duplique sumLeavesForType → remplacer.

Decisions prises en planification

  • Grille Budget : defaut replie comme les rapports (uniformite), malgre l'absence de champs visibles au 1er rendu. Tranche avec Max.
  • Persistance user_preferences (heritee de #288).

Criteres d'acceptation

  • Toute categorie parente de la grille repliable a n'importe quel niveau
  • La grille s'ouvre entierement repliee ; « Tout deplier » visible d'emblee
  • Aucune valeur de budget alteree par un repli ; totaux de section + lignes de resultat inchanges
  • Sous-totaux de section via sumLeavesForType (plus de calcul fait-main)
  • Position des sous-totaux de la grille independante de celle du rapport reel-vs-budget

Spec source

spec-plan-collapse-multi-niveaux.md (v2)

Refs: `spec-decisions-collapse-multi-niveaux.md` + `spec-plan-collapse-multi-niveaux.md` (plan **v2**) ## Depends on - #288 (socle du repli multi-niveaux — cette issue en est le consommateur) ## Contexte La grille Budget (`src/components/budget/BudgetTable.tsx`) est **hierarchique** (elle lit deja `depth`/`is_parent`/`parent_id`, indente sur 4 niveaux) mais fut **deliberement exclue du repli** par #278. Avec ~150 lignes d'un bloc, cette decision est revue : la grille adopte le meme repli multi-niveaux, meme defaut (tout replie). ## Compromis assume **Seules les feuilles sont editables** (`BudgetTable.tsx:105` filtre `!r.is_parent` ; les parents l.175 ne rendent que du texte). Tout replie ⇒ la page ouvre sur 11 lignes racines **sans champ de saisie visible**. Accepte : page compacte, etat **persiste** (cout paye une seule fois), « Tout deplier » a un clic et visible d'emblee. ## Correction critique heritee de /review-spec > Le plan v1 croyait la grille Budget alimentee par `budgetService.buildSubGroup`. **Faux** : elle est construite par le hook **`useBudget.ts:134-365`**, un 3e builder que le plan v1 ignorait. Son tri final (l.345-365) est par **niveau** (`depth` croissant), PAS DFS. C'est ce qui a casse l'algo v1. L'algo v2 (remontee d'ancetres, cf. #288) est **order-independant** → aucun changement de tri requis, mais l'invariant doit etre **acte par un test**. ## Travail a faire - [ ] `src/hooks/useBudget.ts` — **lire et documenter l'invariant d'ordre** (tri par niveau, l.345-365). Avec la remontee d'ancetres, **aucun changement de tri** — mais l'acter par un test (la v1 s'y etait trompee). Ajouter `src/hooks/useBudget.ts` aux fichiers concernes. - [ ] `BudgetTable.tsx` — brancher `useCollapsibleGroups` ; declarer `BUDGET_COLLAPSE_ACCESSORS` + `BUDGET_EXPANDED_KEY` **inline au module scope** (comme ComparePeriodTable:64 et BudgetVsActualTable:35). **Ne PAS creer `budgetTableModel.ts`** : overTimeTableModel.ts existe pour de la vraie logique (`groupOverTimeSections`), pas pour 3 lambdas. - [ ] Chevron + `aria-expanded` sur **toute** ligne parente dans `renderRow` (l.168-205) — parents = texte pur aujourd'hui. - [ ] Bouton « Tout deplier / Tout replier » (reutiliser `reports.collapse.expandAll`/`.collapseAll`). - [ ] **Remplacer le sous-total de section fait-main** (l.301-311) par `sumLeavesForType` de `budgetTableResults.ts:42` — deja teste, *prouve* le critere « sous-totaux sur lignes brutes ». - [ ] **Corriger la collision localStorage** : `BudgetTable.tsx:21` et `BudgetVsActualTable.tsx:30` declarent tous deux `STORAGE_KEY = "subtotals-position"` → prefixer celle du budget en `budget-subtotals-position` (comme ComparePeriodTable:60 prefixe deja la sienne). Effet de bord : la preference de position revient a son defaut une fois. - [ ] CHANGELOG.md + CHANGELOG.fr.md. ## Fichiers concernes - `src/hooks/useBudget.ts` (lu + teste) - `src/components/budget/BudgetTable.tsx` - `src/components/budget/budgetTableResults.ts` (lu — `sumLeavesForType:42`) - `src/i18n/locales/{fr,en}.json`, `CHANGELOG.md`, `CHANGELOG.fr.md` ## Tests - `budgetTableResults` : `sumLeavesForType` couvre deja les sous-totaux de section — le brancher *prouve* l'invariant. - Regression : replier un parent n'altere aucune valeur saisie ; totaux de section + lignes de resultat (#278) identiques replie/deplie. - Regression : ordre des lignes de `useBudget` est par niveau (documente l'invariant que la v1 a suppose a tort). - Regression : deplacer les sous-totaux dans la grille Budget **n'affecte plus** le rapport reel-vs-budget. ## Review caveats - 🔴 **3e builder (`useBudget`)** absent du plan v1 → ajoute ici. C'est la source de l'ordre par niveau. - 🟡 **`budgetTableModel.ts`** : abandonne (accesseurs inline comme les 2 autres tables). - 🟡 **Sous-total fait-main** (l.301-311) duplique `sumLeavesForType` → remplacer. ## Decisions prises en planification - Grille Budget : defaut **replie** comme les rapports (uniformite), malgre l'absence de champs visibles au 1er rendu. Tranche avec Max. - Persistance `user_preferences` (heritee de #288). ## Criteres d'acceptation - [ ] Toute categorie parente de la grille repliable a n'importe quel niveau - [ ] La grille s'ouvre entierement repliee ; « Tout deplier » visible d'emblee - [ ] Aucune valeur de budget alteree par un repli ; totaux de section + lignes de resultat inchanges - [ ] Sous-totaux de section via `sumLeavesForType` (plus de calcul fait-main) - [ ] Position des sous-totaux de la grille **independante** de celle du rapport reel-vs-budget ## Spec source spec-plan-collapse-multi-niveaux.md (v2)
maximus added this to the planned-2026-07-15-collapse-multi-niveaux milestone 2026-07-14 00:41:40 +00:00
maximus added the
status:ready
type:feature
source:human
labels 2026-07-14 00:41:40 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#289
No description provided.