feat(categories): merge custom categories into the standard taxonomy #296
No reviewers
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#296
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-259-merge-custom-categories"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #259
Problème
Les catégories personnalisées (absentes du seed v2) sans correspondance standard étaient affichées en texte brut dans l'assistant de migration, sans aucun choix, puis re-parentées d'office sous « Catégories personnalisées (migration) ». Aucun moyen de proposer une cible manuellement.
Solution
Le bloc préservé rend maintenant le même
MappingRowque les lignes du seed. Choisir une feuille standard fusionne la catégorie custom : ses transactions, budgets, mots-clés et fournisseurs sont réassignés vers la feuille, et la custom est désactivée. Laisser le champ vide conserve le comportement précédent et ne bloque jamais le bouton « Suivant ».Changements
useCategoryMigration.ts) —RESOLVE_ROWrésout dansplan.rowsETplan.preserved; le garde-fou du bouton « Suivant » (unresolved) ne compte que les lignes du seed.categoryMigrationService.ts) — helper partagéisResolvedTarget; le mapping de réécriture inclut les préservées résolues ; le fourre-tout n'est créé que s'il reste une custom non fusionnée ; les customs fusionnées sont désactivées au lieu d'être re-parentées. Les boucles génériques (étapes 3-7) sont inchangées.StepSimulate.tsx) — bloc préservé enMappingRow(picker feuilles-seulement déjà en place).Tests
GO_NEXTavance malgré une custom non fusionnée.[leaf, custom]vérifiés sur tx/budgets/keywords/suppliers) ; soft-delete ; pas de fourre-tout vide quand tout est fusionné ; régression — fusion d'une custom parente avec enfant custom non résolu → enfant re-parenté sous le fourre-tout, parent désactivé, aucun orphelin.Hors scope
Signalés MINOR par le plan-checker, laissés à une éventuelle suite (l'issue demande de réutiliser
MappingRowtel quel) : badge « À réviser » rouge sur une custom non fusionnée, et undo d'une fusion vers l'état « préservée ».Revue /pr-review — APPROVE
Fusion des catégories personnalisées dans la taxonomie standard. Le câblage sur les 3 couches (reducer, writer, UI) est cohérent, la sémantique de fusion est correcte et le cas piège parent/enfant est couvert par un test de régression. Aucun problème bloquant.
Vérifié
useCategoryMigration.ts) —RESOLVE_ROWapplique la cible viaapplyTargetsurrowsETpreserved(no-op sur le bucket qui ne contient pas la ligne, ids globalement uniques → pas de collision de clé).unresolved(garde du bouton « Suivant ») recalculé surrowsseulement → une custom laissée non fusionnée ne bloque jamais. 3 nouveaux tests ciblent exactement ces 3 invariants.categoryMigrationService.ts) —mappingconstruit depuis[...plan.rows, ...plan.preserved]: les customs fusionnées passent par le même réécriture tx/budgets/mots-clés/fournisseurs (étapes 3-7). Le fourre-tout 2000 n'est créé que sihasUnmergedPreserved. L'étape 8 saute les fusionnées (isResolvedTarget → continue), l'étape 9 les désactive. Gestion de collision budget/keyword robuste (re-requête par itération), ordre de Map déterministe.StepSimulate.tsx) — bloc préservé enMappingRow, picker feuilles-seulement (une custom ne peut fusionner que vers une feuille = sémantique correcte).TransactionPreviewPanelinterroge parv2CategoryIduniquement → une ligne préservée désormais cliquable (cible nulle) est sûre.selectedRowgérait déjàplan.preserved.reason.preserved/needsReview/chooseTarget/editTargetAriaprésentes ;preserved.txCountretirée et non référencée ailleurs ;preserved.title/bodyconservées et toujours utilisées ; FR + EN à jour.Fixes #259.Suggestions (non bloquantes)