Budget : sous-catégories en fin de groupe au dépli, et sous-totaux en bas rattachés aux mauvaises lignes (buildBudgetYearRows, reorderRows) #424

Closed
opened 2026-10-12 21:06:33 +00:00 by maximus · 1 comment
Owner

La grille Budget émet ses lignes par niveaux : une sous-catégorie dépliée s'affiche en fin de groupe au lieu de sous son parent. Avec les sous-totaux en bas, reorderRows rattache des lignes au mauvais sous-total, dans la grille comme dans les rapports Budget vs réel et Comparables. Cette issue émet la grille en profondeur et corrige reorderRows. Signalé par Max en testant la v0.17.1 (#422).

Planifié le 2026-10-12 (/plan-run, jalon planned-2026-10-12-retours-onboarding-v0171), après /analyze et une revue /review-spec (sécurité, architecture, technique) dont les constats sont intégrés ci-dessous. Corps autosuffisant : la spec (spec-plan-retours-onboarding-v0171.md) est locale et ignorée par git. L'ancien corps est archivé en commentaire.

Préalable : ce jalon s'exécute après le merge de planned-2026-10-10-fiabilite-tests (#408, #409, #395, #389). Les numéros de ligne cités sont lus sur main à 8b5b3b1 et ont pu bouger : se fier aux noms de fonctions, aux clés et aux textes cités.

Contexte

buildBudgetYearRows (src/hooks/useBudget.ts:106-383) émet chaque groupe de premier niveau par niveaux : son tri final (:360-380) range toutes les lignes de profondeur 1 avant toutes celles de profondeur 2, puis par nom ; avant lui, le tri alphabétique de allChildRows (:335-340) défait déjà l'ordre [sous-total, ...enfants] que rend buildLevel2Group (:235). Les feuilles de profondeur 2 sortent donc après toutes les lignes de profondeur 1 du groupe, et celles de plusieurs parents intermédiaires se mêlent.

Ordre rendu par la vraie fonction sur la taxonomie d'un profil neuf (consolidated_schema.sql, 150 catégories), section Revenus tout dépliée, sous-totaux en haut :

Revenus
    Emploi                      (sous-total)
    Gouvernemental              (sous-total)
    Revenus de placement        (sous-total)
    Autres revenus
        Allocations familiales      <- Gouvernemental
        Assurance-emploi / RQAP     <- Gouvernemental
        Crédits TPS/TVQ             <- Gouvernemental
        Gains en capital            <- Revenus de placement
        Intérêts & dividendes       <- Revenus de placement
        Paie régulière              <- Emploi
        Primes & bonus              <- Emploi
        Remboursement impôt         <- Gouvernemental
        Revenus locatifs            <- Revenus de placement
        Travail autonome            <- Emploi

La taxonomie standard a des parents intermédiaires dans chaque groupe ; l'ancienne (profil par défaut) en a un, Dépenses récurrentes → Assurances → Assurance-auto, -habitation, -vie (migration v7).

Sous-totaux en bas. reorderRows (src/utils/reorderRows.ts) range dans le bloc du sous-total courant toute ligne qui le suit, y compris une feuille de même profondeur. Sur l'ordre actuel, Emploi et Gouvernemental paraissent vides et « Revenus de placement » ferme un bloc de dix feuilles. Et même sur l'ordre en profondeur visé, une feuille qui suit un sous-groupe frère tombe dans son bloc (vérifié par sonde : « Retrait cash » au-dessus du sous-total « Impôts & taxes » ; même cas pour « Transferts internes » après « Remboursement de dette »). Le même utilitaire sert BudgetVsActualTable et ComparePeriodTable, qui mêlent déjà feuilles et sous-groupes.

Origine. Le tri date de l'ajout du 3ᵉ niveau (a04813c, 2026-02-25). #289 l'a épinglé comme invariant : src/hooks/useBudget.test.ts:65-89 affirme l'ordre défectueux (« Hydro after Rent »). Le repli ne dépend pas de l'ordre (marche des ancêtres, src/utils/collapsibleRows.ts). Le rapport Budget vs réel construit déjà l'arbre en profondeur (src/services/budgetService.ts:374-467) ; il n'est pas réutilisable tel quel (asynchrone, et il écarte les lignes à zéro que la grille doit montrer).

Travail à faire

  • buildBudgetYearRows émet en profondeur, par blocs :
    • un bloc par enfant d'un groupe : une feuille seule, ou un sous-groupe = [sous-total, …ses enfants] (ce que rend déjà buildLevel2Group) ;
    • les blocs d'un groupe sont triés une fois, avant l'émission : le bloc « (direct) » en tête, puis par localeCompare du nom de la feuille ou du sous-total, feuilles et sous-groupes mêlés (comme budgetService.ts:435), puis concaténés ;
    • les groupes de premier niveau (bloc [parent, …] ou feuille seule) sont triés par type (TYPE_ORDER), puis sort_order, puis nom, et concaténés. Plus aucun comparateur ne s'applique à des lignes à l'intérieur d'un groupe : le tri par profondeur disparaît.
  • reorderRows : dans reorderGroup, une ligne dont la profondeur est inférieure ou égale à parentDepth et qui n'est pas un parent de ce niveau ferme le bloc en cours (le parent courant est vidé avec ses enfants) avant d'être émise. Corrige du même coup le mode « sous-totaux en bas » de Budget vs réel et Comparables.
  • Réécrire le commentaire d'invariant (useBudget.ts:87-105), le commentaire de collapsibleRows.ts qui décrit la grille comme « level-ordered », et celui de collapsibleRows.test.ts (« the order the budget grid produces ») ; le cas bfsTree reste, comme preuve que le repli ne dépend pas de l'ordre.
  • BudgetTable.render.test.tsx et budgetOnboardingTarget.test.ts ne changent pas : leurs lignes sont construites à la main, à deux niveaux.

Fichiers concernés

  • src/hooks/useBudget.ts, src/hooks/useBudget.test.ts
  • src/utils/reorderRows.ts, src/utils/reorderRows.test.ts (nouveau)
  • src/utils/collapsibleRows.ts, src/utils/collapsibleRows.test.ts (commentaires)
  • CHANGELOG.md, CHANGELOG.fr.md

Depends on

Aucune.

Tests

  • Remplacer les deux tests d'ordre par niveaux (useBudget.test.ts:65-89) par l'invariant en profondeur : chaque ligne suit son parent, et toutes les lignes entre un parent et la fin de son sous-arbre sont ses descendantes.
  • Ordre exact sur deux fixtures : la forme Revenus (une feuille de profondeur 1 qui passe en tête, trois sous-groupes) et la forme « Finances & obligations » (feuilles avant et après des sous-groupes, dont « Retrait cash » après « Impôts & taxes »).
  • reorderRows.test.ts : sous-totaux en bas, une feuille qui suit un sous-groupe frère reste hors de son bloc, chaque sous-total suit ses propres feuilles, à deux et trois niveaux ; sous-totaux en haut : liste inchangée.
  • Recaler les ordres attendus qui dépendent de l'ancien ordre (useBudget.test.ts:101-108).
  • Mutations : remettre le tri par profondeur dans le builder, et retirer la fermeture de bloc dans reorderRows, rougissent chacune au moins un test.

Critères d'acceptation

  • Tout déplié, chaque sous-catégorie s'affiche directement sous son parent, dans les deux taxonomies et dans les deux positions des sous-totaux.
  • Déplier un seul parent intermédiaire affiche ses enfants juste sous lui.
  • Avec les sous-totaux en bas, chaque sous-total suit ses propres lignes, dans la grille Budget et dans les rapports Budget vs réel et Comparables.
  • Sous-totaux, totaux de section et lignes Résultat inchangés ; la carte Budget du parcours désigne toujours une cellule d'une feuille visible.
  • npm run build et npm test verts.

Review caveats

  • 🔴 Technique, résolu : reorderRows plaçait encore une feuille qui suit un sous-groupe frère dans son bloc ; la correction est dans cette issue.
  • 🟡 Architecture, résolu : le mécanisme est fixé (blocs triés avant émission, plus de comparateur interne) et l'ordre des frères est verrouillé par un test d'ordre exact ; un test de parité avec getBudgetVsActualData n'est pas retenu.

Décisions prises en planification

  • Ordre des frères : celui du rapport Budget vs réel, « (direct) » en tête puis feuilles et sous-groupes mêlés par nom (Max, 2026-10-12). Changement visible : dans Revenus, « Autres revenus » passe en tête.
  • reorderRows corrigé ici, ce qui répare aussi les rapports (constat de revue, Max, 2026-10-12).
  • Indépendante du parcours : premier maillon de la pile, mergeable seule en correctif.

Conventions

  • Toute chaîne en FR et en EN (src/i18n/locales/fr.json, en.json) ; les textes de ce corps s'écrivent mot pour mot (FR validé par Max le 2026-10-12, EN rédigé sur le même contenu).
  • Phrase de carte : un contrôle cité passe par StepCardText.labels (src/utils/onboardingPath.ts), traduit par StepCard ; jamais recopié dans la phrase. Guillemets « » en FR et “ ” en EN autour de chaque libellé de contrôle interpolé ; {{filter, lowercase}} sans guillemets.
  • CHANGELOG : une entrée sous ## [Unreleased] dans CHANGELOG.md et CHANGELOG.fr.md.
  • Tests de rendu : renderToStaticMarkup (pas de jsdom) et le faux t partagé livré par #389.
  • Journal : aucune ligne avec un chemin absolu, un nom de relevé ni un nom de dossier d'import (règle de useImportWizard.ts:423-425 : le Journal part avec un rapport de feedback).
  • Aucune migration ; npm run build (il vérifie aussi les types des fichiers de test) et npm test verts.
  • Guide Markdown (docs/guide-utilisateur.md) : repérer une ligne par son texte cité, pas par son numéro.

CHANGELOG

Fixed / Corrigé : FR « Budget : une sous-catégorie dépliée s'affiche sous sa catégorie parente, et non plus en fin de groupe. Avec les sous-totaux en bas, chaque sous-total suit ses propres lignes, dans la grille Budget comme dans les rapports Budget vs réel et Comparables. » EN "Budget: an expanded subcategory now shows under its parent category instead of at the end of the group. With subtotals at the bottom, each subtotal follows its own rows, in the Budget grid as in the Budget vs Actual and Compare reports."

Spec source

spec-plan-retours-onboarding-v0171.md (local, ignoré par git) ; décisions dans spec-decisions-retours-onboarding-v0171.md.

La grille Budget émet ses lignes par niveaux : une sous-catégorie dépliée s'affiche en fin de groupe au lieu de sous son parent. Avec les sous-totaux en bas, `reorderRows` rattache des lignes au mauvais sous-total, dans la grille comme dans les rapports Budget vs réel et Comparables. Cette issue émet la grille en profondeur et corrige `reorderRows`. Signalé par Max en testant la v0.17.1 (#422). > Planifié le 2026-10-12 (`/plan-run`, jalon `planned-2026-10-12-retours-onboarding-v0171`), après `/analyze` et une revue `/review-spec` (sécurité, architecture, technique) dont les constats sont intégrés ci-dessous. Corps autosuffisant : la spec (`spec-plan-retours-onboarding-v0171.md`) est locale et ignorée par git. L'ancien corps est archivé en commentaire. > > **Préalable :** ce jalon s'exécute après le merge de `planned-2026-10-10-fiabilite-tests` (#408, #409, #395, #389). Les numéros de ligne cités sont lus sur `main` à `8b5b3b1` et ont pu bouger : se fier aux noms de fonctions, aux clés et aux textes cités. ## Contexte `buildBudgetYearRows` (`src/hooks/useBudget.ts:106-383`) émet chaque groupe de premier niveau **par niveaux** : son tri final (`:360-380`) range toutes les lignes de profondeur 1 avant toutes celles de profondeur 2, puis par nom ; avant lui, le tri alphabétique de `allChildRows` (`:335-340`) défait déjà l'ordre `[sous-total, ...enfants]` que rend `buildLevel2Group` (`:235`). Les feuilles de profondeur 2 sortent donc après toutes les lignes de profondeur 1 du groupe, et celles de plusieurs parents intermédiaires se mêlent. Ordre rendu par la vraie fonction sur la taxonomie d'un profil neuf (`consolidated_schema.sql`, 150 catégories), section Revenus tout dépliée, sous-totaux en haut : ``` Revenus Emploi (sous-total) Gouvernemental (sous-total) Revenus de placement (sous-total) Autres revenus Allocations familiales <- Gouvernemental Assurance-emploi / RQAP <- Gouvernemental Crédits TPS/TVQ <- Gouvernemental Gains en capital <- Revenus de placement Intérêts & dividendes <- Revenus de placement Paie régulière <- Emploi Primes & bonus <- Emploi Remboursement impôt <- Gouvernemental Revenus locatifs <- Revenus de placement Travail autonome <- Emploi ``` La taxonomie standard a des parents intermédiaires dans chaque groupe ; l'ancienne (profil par défaut) en a un, Dépenses récurrentes → Assurances → Assurance-auto, -habitation, -vie (migration v7). **Sous-totaux en bas.** `reorderRows` (`src/utils/reorderRows.ts`) range dans le bloc du sous-total courant toute ligne qui le suit, y compris une feuille de même profondeur. Sur l'ordre actuel, Emploi et Gouvernemental paraissent vides et « Revenus de placement » ferme un bloc de dix feuilles. Et même sur l'ordre en profondeur visé, une feuille qui suit un sous-groupe frère tombe dans son bloc (vérifié par sonde : « Retrait cash » au-dessus du sous-total « Impôts & taxes » ; même cas pour « Transferts internes » après « Remboursement de dette »). Le même utilitaire sert `BudgetVsActualTable` et `ComparePeriodTable`, qui mêlent déjà feuilles et sous-groupes. **Origine.** Le tri date de l'ajout du 3ᵉ niveau (`a04813c`, 2026-02-25). #289 l'a épinglé comme invariant : `src/hooks/useBudget.test.ts:65-89` affirme l'ordre défectueux (« Hydro after Rent »). Le repli ne dépend pas de l'ordre (marche des ancêtres, `src/utils/collapsibleRows.ts`). Le rapport Budget vs réel construit déjà l'arbre en profondeur (`src/services/budgetService.ts:374-467`) ; il n'est pas réutilisable tel quel (asynchrone, et il écarte les lignes à zéro que la grille doit montrer). ## Travail à faire - [ ] `buildBudgetYearRows` émet en profondeur, par blocs : - un bloc par enfant d'un groupe : une feuille seule, ou un sous-groupe = `[sous-total, …ses enfants]` (ce que rend déjà `buildLevel2Group`) ; - les blocs d'un groupe sont triés une fois, avant l'émission : le bloc « (direct) » en tête, puis par `localeCompare` du nom de la feuille ou du sous-total, feuilles et sous-groupes mêlés (comme `budgetService.ts:435`), puis concaténés ; - les groupes de premier niveau (bloc `[parent, …]` ou feuille seule) sont triés par type (`TYPE_ORDER`), puis `sort_order`, puis nom, et concaténés. Plus aucun comparateur ne s'applique à des lignes à l'intérieur d'un groupe : le tri par profondeur disparaît. - [ ] `reorderRows` : dans `reorderGroup`, une ligne dont la profondeur est inférieure ou égale à `parentDepth` et qui n'est pas un parent de ce niveau ferme le bloc en cours (le parent courant est vidé avec ses enfants) avant d'être émise. Corrige du même coup le mode « sous-totaux en bas » de Budget vs réel et Comparables. - [ ] Réécrire le commentaire d'invariant (`useBudget.ts:87-105`), le commentaire de `collapsibleRows.ts` qui décrit la grille comme « level-ordered », et celui de `collapsibleRows.test.ts` (« the order the budget grid produces ») ; le cas `bfsTree` reste, comme preuve que le repli ne dépend pas de l'ordre. - [ ] `BudgetTable.render.test.tsx` et `budgetOnboardingTarget.test.ts` ne changent pas : leurs lignes sont construites à la main, à deux niveaux. ## Fichiers concernés - `src/hooks/useBudget.ts`, `src/hooks/useBudget.test.ts` - `src/utils/reorderRows.ts`, `src/utils/reorderRows.test.ts` (nouveau) - `src/utils/collapsibleRows.ts`, `src/utils/collapsibleRows.test.ts` (commentaires) - `CHANGELOG.md`, `CHANGELOG.fr.md` ## Depends on Aucune. ## Tests - Remplacer les deux tests d'ordre par niveaux (`useBudget.test.ts:65-89`) par l'invariant en profondeur : chaque ligne suit son parent, et toutes les lignes entre un parent et la fin de son sous-arbre sont ses descendantes. - Ordre exact sur deux fixtures : la forme Revenus (une feuille de profondeur 1 qui passe en tête, trois sous-groupes) et la forme « Finances & obligations » (feuilles avant et après des sous-groupes, dont « Retrait cash » après « Impôts & taxes »). - `reorderRows.test.ts` : sous-totaux en bas, une feuille qui suit un sous-groupe frère reste hors de son bloc, chaque sous-total suit ses propres feuilles, à deux et trois niveaux ; sous-totaux en haut : liste inchangée. - Recaler les ordres attendus qui dépendent de l'ancien ordre (`useBudget.test.ts:101-108`). - Mutations : remettre le tri par profondeur dans le builder, et retirer la fermeture de bloc dans `reorderRows`, rougissent chacune au moins un test. ## Critères d'acceptation - [ ] Tout déplié, chaque sous-catégorie s'affiche directement sous son parent, dans les deux taxonomies et dans les deux positions des sous-totaux. - [ ] Déplier un seul parent intermédiaire affiche ses enfants juste sous lui. - [ ] Avec les sous-totaux en bas, chaque sous-total suit ses propres lignes, dans la grille Budget et dans les rapports Budget vs réel et Comparables. - [ ] Sous-totaux, totaux de section et lignes Résultat inchangés ; la carte Budget du parcours désigne toujours une cellule d'une feuille visible. - [ ] `npm run build` et `npm test` verts. ## Review caveats - 🔴 Technique, résolu : `reorderRows` plaçait encore une feuille qui suit un sous-groupe frère dans son bloc ; la correction est dans cette issue. - 🟡 Architecture, résolu : le mécanisme est fixé (blocs triés avant émission, plus de comparateur interne) et l'ordre des frères est verrouillé par un test d'ordre exact ; un test de parité avec `getBudgetVsActualData` n'est pas retenu. ## Décisions prises en planification - Ordre des frères : celui du rapport Budget vs réel, « (direct) » en tête puis feuilles et sous-groupes mêlés par nom (Max, 2026-10-12). Changement visible : dans Revenus, « Autres revenus » passe en tête. - `reorderRows` corrigé ici, ce qui répare aussi les rapports (constat de revue, Max, 2026-10-12). - Indépendante du parcours : premier maillon de la pile, mergeable seule en correctif. ## Conventions - Toute chaîne en FR et en EN (`src/i18n/locales/fr.json`, `en.json`) ; les textes de ce corps s'écrivent mot pour mot (FR validé par Max le 2026-10-12, EN rédigé sur le même contenu). - Phrase de carte : un contrôle cité passe par `StepCardText.labels` (`src/utils/onboardingPath.ts`), traduit par `StepCard` ; jamais recopié dans la phrase. Guillemets « » en FR et “ ” en EN autour de chaque libellé de contrôle interpolé ; `{{filter, lowercase}}` sans guillemets. - CHANGELOG : une entrée sous `## [Unreleased]` dans `CHANGELOG.md` et `CHANGELOG.fr.md`. - Tests de rendu : `renderToStaticMarkup` (pas de jsdom) et le faux `t` partagé livré par #389. - Journal : aucune ligne avec un chemin absolu, un nom de relevé ni un nom de dossier d'import (règle de `useImportWizard.ts:423-425` : le Journal part avec un rapport de feedback). - Aucune migration ; `npm run build` (il vérifie aussi les types des fichiers de test) et `npm test` verts. - Guide Markdown (`docs/guide-utilisateur.md`) : repérer une ligne par son texte cité, pas par son numéro. ## CHANGELOG Fixed / Corrigé : FR « Budget : une sous-catégorie dépliée s'affiche sous sa catégorie parente, et non plus en fin de groupe. Avec les sous-totaux en bas, chaque sous-total suit ses propres lignes, dans la grille Budget comme dans les rapports Budget vs réel et Comparables. » EN "Budget: an expanded subcategory now shows under its parent category instead of at the end of the group. With subtotals at the bottom, each subtotal follows its own rows, in the Budget grid as in the Budget vs Actual and Compare reports." ## Spec source `spec-plan-retours-onboarding-v0171.md` (local, ignoré par git) ; décisions dans `spec-decisions-retours-onboarding-v0171.md`.
maximus added the
status:ready
type:bug
source:human
labels 2026-10-12 21:06:33 +00:00
Author
Owner

Planification du 2026-10-12 (/plan-run, jalon planned-2026-10-12-retours-onboarding-v0171) : le corps est réécrit pour être autosuffisant (décisions de Max, constats de /review-spec intégrés). Corps précédent ci-dessous.

Corps précédent (titre : Budget : au dépli, les sous-catégories d'un parent intermédiaire s'affichent en fin de groupe (ordre par niveaux de buildBudgetYearRows))

Contexte

Signalé par Max en testant la v0.17.1 (#422, point 5) : « pour le budget, lorsqu'on déplie, les catégories ne sont pas sous le parent mais plutôt à la fin de la section ». Analysé le 2026-10-12 sur main à 1954502 ; reproduit en appelant la vraie fonction sur la taxonomie d'un profil neuf.

Cause. buildBudgetYearRows (src/hooks/useBudget.ts:106-383) émet chaque groupe de premier niveau par niveaux (largeur d'abord). Son tri final (:360-380) range, dans un même groupe, toutes les lignes de profondeur 1 avant toutes celles de profondeur 2, puis par nom. Avant lui, le tri alphabétique de allChildRows (:335-340) défait déjà l'ordre [sous-total, ...enfants] que rend buildLevel2Group (:235). Deux effets :

  • les feuilles de profondeur 2 sortent après toutes les lignes de profondeur 1 du groupe, feuilles comprises : sous la dernière ligne de profondeur 1, pas sous leur parent ;
  • les feuilles de plusieurs parents intermédiaires se mêlent par ordre alphabétique.

Ordre rendu sur la taxonomie d'un profil neuf (consolidated_schema.sql, 150 catégories), section Revenus tout dépliée, sous-totaux en haut (défaut) :

Revenus
    Emploi                      (sous-total)
    Gouvernemental              (sous-total)
    Revenus de placement        (sous-total)
    Autres revenus
        Allocations familiales      <- Gouvernemental
        Assurance-emploi / RQAP     <- Gouvernemental
        Crédits TPS/TVQ             <- Gouvernemental
        Gains en capital            <- Revenus de placement
        Intérêts & dividendes       <- Revenus de placement
        Paie régulière              <- Emploi
        Primes & bonus              <- Emploi
        Remboursement impôt         <- Gouvernemental
        Revenus locatifs            <- Revenus de placement
        Travail autonome            <- Emploi

Revenus est le seul groupe de sa section : déplier Emploi y affiche Paie régulière, Primes & bonus et Travail autonome tout en bas de la section, après Autres revenus. C'est le constat de Max. La taxonomie standard a des parents intermédiaires dans chaque groupe ; l'ancienne taxonomie (profil par défaut) en a un, Dépenses récurrentes → Assurances → Assurance-auto, -habitation, -vie (migration v7, src-tauri/src/lib.rs).

Sous-totaux en bas. reorderRows (src/utils/reorderRows.ts) suppose un ordre en profondeur (un parent suivi de son sous-arbre). Sur l'ordre par niveaux, il rattache les lignes au mauvais sous-total. Même section :

    Emploi                      (sous-total, vide)
    Gouvernemental              (sous-total, vide)
    Autres revenus
        (les dix feuilles des trois parents)
    Revenus de placement        (sous-total, ferme le bloc)
Revenus                         (sous-total)

Origine. Le tri date de l'ajout du 3ᵉ niveau (a04813c, 2026-02-25). #289 (repli multi-niveaux) l'a épinglé comme invariant : src/hooks/useBudget.test.ts:65-89 affirme l'ordre défectueux (« Hydro after Rent »), et le commentaire de useBudget.ts:91-100 interdit de passer en profondeur sans revoir BudgetTable. Or le repli ne dépend pas de l'ordre (marche des ancêtres, src/utils/collapsibleRows.ts) : rien ne justifie plus l'ordre par niveaux.

Modèle. Le rapport Budget vs réel construit déjà l'arbre en profondeur : buildSubGroup récursif, enfants par ordre alphabétique, « (direct) » en tête, puis un tri par type seul qui garde l'ordre de l'arbre (src/services/budgetService.ts:374-467).

Travail à faire

  • Émettre les lignes en profondeur dans buildBudgetYearRows : chaque parent suivi de son sous-arbre. Les groupes de premier niveau gardent leur ordre (type, puis sort_order, puis nom). Les frères suivent la règle de budgetService.ts : « (direct) » en tête, puis par nom, feuilles et sous-groupes mêlés. C'est un changement visible à la profondeur 1, où la grille met aujourd'hui les parents avant les feuilles : il aligne la grille sur le rapport Budget vs réel.
  • Réécrire le commentaire d'invariant de useBudget.ts:87-105, et celui de collapsibleRows.ts qui décrit la grille comme « level-ordered ».
  • Remplacer les tests d'ordre par niveaux (useBudget.test.ts:65-89) par l'invariant en profondeur, et recaler les ordres attendus qui en dépendent (useBudget.test.ts:101-108).
  • Vérifier que budgetOnboardingTarget (première feuille visible, carte Budget du parcours) et ses tests restent justes.
  • CHANGELOG : entrée « Fixed » / « Corrigé » dans CHANGELOG.md et CHANGELOG.fr.md.

Fichiers concernés

  • src/hooks/useBudget.ts : tri de allChildRows et tri final, commentaire d'invariant.
  • src/hooks/useBudget.test.ts : tests d'ordre.
  • src/utils/collapsibleRows.ts : commentaire seulement.
  • src/utils/collapsibleRows.test.ts : le cas bfsTree (:56-124) reste une preuve valable que le repli ne dépend pas de l'ordre ; seul son commentaire « the order the budget grid produces » devient faux.
  • src/components/budget/BudgetTable.render.test.tsx : fixture « in the order buildBudgetYearRows emits them » (:68), à recaler si besoin.
  • CHANGELOG.md, CHANGELOG.fr.md.

Surface de test

  • Tests existants : src/hooks/useBudget.test.ts, src/utils/collapsibleRows.test.ts, src/components/budget/BudgetTable.render.test.tsx, src/components/budget/budgetOnboardingTarget.test.ts.
  • Test de régression requis : oui.
    • Chaque ligne suit son parent, et toutes les lignes entre un parent et la fin de son sous-arbre sont ses descendantes. Sur la fixture actuelle, et sur une fixture à plusieurs parents intermédiaires dans un même groupe (le cas Revenus ci-dessus).
    • reorderRows(…, false) sur la sortie du builder : chaque sous-total intermédiaire suit ses propres feuilles.
    • Mutation à rejouer : remettre le tri par profondeur doit rougir ces tests.

Critères d'acceptation

  • Tout déplié, chaque sous-catégorie s'affiche directement sous son parent, dans les deux taxonomies et dans les deux positions des sous-totaux.
  • Déplier un seul parent intermédiaire affiche ses enfants juste sous lui.
  • Sous-totaux, totaux de section et lignes Résultat inchangés (les sommes ne dépendent pas de l'ordre).
  • La carte Budget du parcours désigne toujours une cellule d'une feuille visible.
  • npm test et npm run build verts.

Complexité estimée

Simple à moyenne : une fonction pure et ses tests, avec un modèle existant dans budgetService.ts.

Questions ouvertes

Aucune. Indépendante des autres issues issues de #422 ; livrable seule, en correctif.

Planification du 2026-10-12 (`/plan-run`, jalon `planned-2026-10-12-retours-onboarding-v0171`) : le corps est réécrit pour être autosuffisant (décisions de Max, constats de `/review-spec` intégrés). Corps précédent ci-dessous. <details><summary>Corps précédent (titre : Budget : au dépli, les sous-catégories d'un parent intermédiaire s'affichent en fin de groupe (ordre par niveaux de buildBudgetYearRows))</summary> ## Contexte Signalé par Max en testant la v0.17.1 (#422, point 5) : « pour le budget, lorsqu'on déplie, les catégories ne sont pas sous le parent mais plutôt à la fin de la section ». Analysé le 2026-10-12 sur `main` à `1954502` ; reproduit en appelant la vraie fonction sur la taxonomie d'un profil neuf. **Cause.** `buildBudgetYearRows` (`src/hooks/useBudget.ts:106-383`) émet chaque groupe de premier niveau **par niveaux** (largeur d'abord). Son tri final (`:360-380`) range, dans un même groupe, toutes les lignes de profondeur 1 avant toutes celles de profondeur 2, puis par nom. Avant lui, le tri alphabétique de `allChildRows` (`:335-340`) défait déjà l'ordre `[sous-total, ...enfants]` que rend `buildLevel2Group` (`:235`). Deux effets : - les feuilles de profondeur 2 sortent après toutes les lignes de profondeur 1 du groupe, feuilles comprises : sous la dernière ligne de profondeur 1, pas sous leur parent ; - les feuilles de plusieurs parents intermédiaires se mêlent par ordre alphabétique. Ordre rendu sur la taxonomie d'un profil neuf (`consolidated_schema.sql`, 150 catégories), section Revenus tout dépliée, sous-totaux en haut (défaut) : ``` Revenus Emploi (sous-total) Gouvernemental (sous-total) Revenus de placement (sous-total) Autres revenus Allocations familiales <- Gouvernemental Assurance-emploi / RQAP <- Gouvernemental Crédits TPS/TVQ <- Gouvernemental Gains en capital <- Revenus de placement Intérêts & dividendes <- Revenus de placement Paie régulière <- Emploi Primes & bonus <- Emploi Remboursement impôt <- Gouvernemental Revenus locatifs <- Revenus de placement Travail autonome <- Emploi ``` Revenus est le seul groupe de sa section : déplier Emploi y affiche Paie régulière, Primes & bonus et Travail autonome tout en bas de la section, après Autres revenus. C'est le constat de Max. La taxonomie standard a des parents intermédiaires dans chaque groupe ; l'ancienne taxonomie (profil par défaut) en a un, Dépenses récurrentes → Assurances → Assurance-auto, -habitation, -vie (migration v7, `src-tauri/src/lib.rs`). **Sous-totaux en bas.** `reorderRows` (`src/utils/reorderRows.ts`) suppose un ordre en profondeur (un parent suivi de son sous-arbre). Sur l'ordre par niveaux, il rattache les lignes au mauvais sous-total. Même section : ``` Emploi (sous-total, vide) Gouvernemental (sous-total, vide) Autres revenus (les dix feuilles des trois parents) Revenus de placement (sous-total, ferme le bloc) Revenus (sous-total) ``` **Origine.** Le tri date de l'ajout du 3ᵉ niveau (`a04813c`, 2026-02-25). #289 (repli multi-niveaux) l'a épinglé comme invariant : `src/hooks/useBudget.test.ts:65-89` affirme l'ordre défectueux (« Hydro after Rent »), et le commentaire de `useBudget.ts:91-100` interdit de passer en profondeur sans revoir `BudgetTable`. Or le repli ne dépend pas de l'ordre (marche des ancêtres, `src/utils/collapsibleRows.ts`) : rien ne justifie plus l'ordre par niveaux. **Modèle.** Le rapport Budget vs réel construit déjà l'arbre en profondeur : `buildSubGroup` récursif, enfants par ordre alphabétique, « (direct) » en tête, puis un tri par type seul qui garde l'ordre de l'arbre (`src/services/budgetService.ts:374-467`). ## Travail à faire - [ ] Émettre les lignes en profondeur dans `buildBudgetYearRows` : chaque parent suivi de son sous-arbre. Les groupes de premier niveau gardent leur ordre (type, puis `sort_order`, puis nom). Les frères suivent la règle de `budgetService.ts` : « (direct) » en tête, puis par nom, feuilles et sous-groupes mêlés. C'est un changement visible à la profondeur 1, où la grille met aujourd'hui les parents avant les feuilles : il aligne la grille sur le rapport Budget vs réel. - [ ] Réécrire le commentaire d'invariant de `useBudget.ts:87-105`, et celui de `collapsibleRows.ts` qui décrit la grille comme « level-ordered ». - [ ] Remplacer les tests d'ordre par niveaux (`useBudget.test.ts:65-89`) par l'invariant en profondeur, et recaler les ordres attendus qui en dépendent (`useBudget.test.ts:101-108`). - [ ] Vérifier que `budgetOnboardingTarget` (première feuille visible, carte Budget du parcours) et ses tests restent justes. - [ ] CHANGELOG : entrée « Fixed » / « Corrigé » dans `CHANGELOG.md` et `CHANGELOG.fr.md`. ## Fichiers concernés - `src/hooks/useBudget.ts` : tri de `allChildRows` et tri final, commentaire d'invariant. - `src/hooks/useBudget.test.ts` : tests d'ordre. - `src/utils/collapsibleRows.ts` : commentaire seulement. - `src/utils/collapsibleRows.test.ts` : le cas `bfsTree` (`:56-124`) reste une preuve valable que le repli ne dépend pas de l'ordre ; seul son commentaire « the order the budget grid produces » devient faux. - `src/components/budget/BudgetTable.render.test.tsx` : fixture « in the order `buildBudgetYearRows` emits them » (`:68`), à recaler si besoin. - `CHANGELOG.md`, `CHANGELOG.fr.md`. ## Surface de test - Tests existants : `src/hooks/useBudget.test.ts`, `src/utils/collapsibleRows.test.ts`, `src/components/budget/BudgetTable.render.test.tsx`, `src/components/budget/budgetOnboardingTarget.test.ts`. - Test de régression requis : oui. - Chaque ligne suit son parent, et toutes les lignes entre un parent et la fin de son sous-arbre sont ses descendantes. Sur la fixture actuelle, et sur une fixture à plusieurs parents intermédiaires dans un même groupe (le cas Revenus ci-dessus). - `reorderRows(…, false)` sur la sortie du builder : chaque sous-total intermédiaire suit ses propres feuilles. - Mutation à rejouer : remettre le tri par profondeur doit rougir ces tests. ## Critères d'acceptation - [ ] Tout déplié, chaque sous-catégorie s'affiche directement sous son parent, dans les deux taxonomies et dans les deux positions des sous-totaux. - [ ] Déplier un seul parent intermédiaire affiche ses enfants juste sous lui. - [ ] Sous-totaux, totaux de section et lignes Résultat inchangés (les sommes ne dépendent pas de l'ordre). - [ ] La carte Budget du parcours désigne toujours une cellule d'une feuille visible. - [ ] `npm test` et `npm run build` verts. ## Complexité estimée Simple à moyenne : une fonction pure et ses tests, avec un modèle existant dans `budgetService.ts`. ## Questions ouvertes Aucune. Indépendante des autres issues issues de #422 ; livrable seule, en correctif. </details>
maximus changed title from Budget : au dépli, les sous-catégories d'un parent intermédiaire s'affichent en fin de groupe (ordre par niveaux de buildBudgetYearRows) to Budget : sous-catégories en fin de groupe au dépli, et sous-totaux en bas rattachés aux mauvaises lignes (buildBudgetYearRows, reorderRows) 2026-10-12 23:24:33 +00:00
maximus added this to the planned-2026-10-12-retours-onboarding-v0171 milestone 2026-10-12 23:24:33 +00:00
maximus added
status:in-progress
and removed
status:ready
labels 2026-10-14 00:38:59 +00:00
maximus added
status:review
and removed
status:in-progress
labels 2026-10-14 00:44:27 +00:00
maximus added
status:approved
and removed
status:review
labels 2026-10-14 23:48:42 +00:00
maximus removed the
status:approved
label 2026-10-16 00:38:15 +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#424
No description provided.