Onboarding : commande Tauri create_sample_import_folders, gabarits CSV d'exemple et test de détection #354
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#354
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Vague
planned-2026-10-03-onboarding-phase1(séance/plan-rundu 2026-10-03, spec +/review-specdu 2026-09-25, verdict APPROUVÉ après intégration). Les fichiersspec-decisions-onboarding-phase1.md/spec-plan-onboarding-phase1.mdsont ignorés par git : ce corps est auto-suffisant, ne pas chercher le spec. Analyse d'origine :docs/analyse-onboarding-2026-09.md.Règles de la vague : pile linéaire (chaque PR part de la précédente) ; ne pas toucher
CHANGELOG.md/CHANGELOG.fr.mdavant #357 qui les centralise ; FR + EN pour toute clé i18n (.claude/rules/i18n.md) ; aucune migration DB ; aucune chaîne en dur dans les composants.Objectif
Nouvelle commande Rust qui écrit deux sous-dossiers de CSV réalistes (Desjardins compte chèques, Tangerine carte de crédit) dans le dossier d'import, dates recalculées sur les deux derniers mois complets, jamais d'écrasement. Les mêmes gabarits sont validés par vitest.
Tâches
src/__fixtures__/samples/exemple-desjardins.csvetexemple-tangerine.csvavec le contenu exact ci-dessous (jetons{{M1}}= mois complet précédent,{{M2}}= celui d'avant, rendusMM/YYYY)src-tauri/src/commands/fs_commands.rs:#[tauri::command] pub fn create_sample_import_folders(import_folder: String, today: String) -> Result<Vec<String>, String>avec doc-comment ;NaiveDate::parse_from_str(&today, "%Y-%m-%d")(chrono 0.4.43 compilé avecstd/serdeseulement :Local::now()etUtc::now()indisponibles, d'où l'argument) ; M1 = 1er du mois detodaymoins 1 mois, M2 = moins 2 (checked_sub_months) ;Errsiimport_foldern'est pas un dossier ;Errnommant le dossier si « Exemple Desjardins » ou « Exemple Tangerine » existe déjà, avant toute écriture ; gabarits viainclude_str!("../../../src/__fixtures__/samples/exemple-desjardins.csv")(chemin relatif àsrc-tauri/src/commands/) ; remplacement des jetons ;fs::create_dir+fs::writedereleve-YYYY-MM.csv(YYYY-MM de M1) dans chaque dossier ; retour = les deux noms de dossiers (pas les chemins)tauri::generate_handler![...]desrc-tauri/src/lib.rs:435-478#[cfg(test)]dansfs_commands.rsavec un helperfn sandbox(name: &str) -> PathBuf=std::env::temp_dir().join(format!("simpl-resultat-samples-{}-{}", std::process::id(), name)),create_dir_allau début,remove_dir_allà la fin y compris sur les cheminsErr(les cas d'un même binaire tournent en parallèle dans un seul processus ;token_store.rs:382àprocess::id()seul ne suffit pas). Cas : dossier absent →Err; « Exemple Desjardins » déjà présent →Erret « Exemple Tangerine » non créé ; succès avectoday = "2026-09-25"→ deux fichiersreleve-2026-08.csv, aucun{{résiduel, toutes les datesDD/MM/YYYYen08/2026ou07/2026;today = "pas-une-date"→Err;today = "2027-01-15"→12/2026et11/2026, fichiersreleve-2026-12.csvsrc/__fixtures__/samples/index.ts(nouveau) :readSampleTemplate(name: "desjardins" | "tangerine"): string(readFileSync(resolve(import.meta.dirname, ...))) etrenderSampleTemplate(raw, m1: "MM/YYYY", m2: "MM/YYYY"). Ne pas toucher àsrc/__fixtures__/csv/index.tsni àCsvFixtureName: le corpus est gelé à 15 parcsvAutoDetect.test.ts:264et six boucles (csvAutoDetect.test.ts:265, 274, 281, 957, 1074,bankSignatures.test.ts:315) passent chaque nom brut à la détectionsrc/__integration__/onboarding-samples.test.ts(nouveau) : pour chaque gabarit rendu avecm1="08/2026",m2="07/2026":detectImportFormat→status: "ok",bank="desjardins"/"tangerine",config.signConvention === "negative_expense",config.amountMode === "single", score 40/40 ; parsing complet avec la config → 0 ligne en erreur, somme des montants +740,00 (Desjardins) et −368,46 (Tangerine) ; puisvi.mock("../services/db")avecselectrenvoyant les 180 lignesINSERT INTO keywordsextraites desrc-tauri/src/database/consolidated_schema.sqlparreadFileSync+ regex (patterncategorizationService.test.ts:9), appel decategorizeBatch(descriptions)→ exactement 33 (Desjardins) et 36 (Tangerine) lignes aveccategory_idnon nul, chacune ≥ 80 %, et les lignes hors seed listées ci-dessous non catégoriséescheck-frontenda tourné (les gabarits sont soussrc/, la denylistsrc-tauri/**decheck-frontend.yml:15reste intacte)Gabarits
Lignes hors seed, à classer à la main (case 5 de la liste) : Desjardins → GARDERIE LES PETITS PAS ×2, PAIEMENT VISA TANGERINE ×2, VIREMENT INTERAC RECU, CLINIQUE DENTAIRE ST-LAMBERT, RETRAITE QUEBEC ALLOC FAM (7) ; Tangerine → DOLLARAMA ×2, PAIEMENT - MERCI ×2 (4).
exemple-desjardins.csv:exemple-tangerine.csv:Fichiers concernés
src/__fixtures__/samples/exemple-desjardins.csv,exemple-tangerine.csv,index.ts(nouveaux)src/__integration__/onboarding-samples.test.ts(nouveau)src-tauri/src/commands/fs_commands.rssrc-tauri/src/lib.rsDepends on
(aucune)
Critères d'acceptation
cargo test: les cinq cas Rust passent, y compris lancés en parallèle (cargo test -- --test-threads=4)onboarding-samples.test.tsvert avec les valeurs figées (banque, 40/40, 0 erreur, +740,00 / −368,46, 33 / 36 catégorisées, hors seed non catégorisées)csvAutoDetect.test.tsetbankSignatures.test.tsinchangés et verts (CSV_FIXTURE_NAMEStoujours 15)check-rustetcheck-frontendont tous deux tourné sur la PRReview caveats
CsvFixtureNameintact.src/pour la CI frontend.remove_dir_allsur échec partiel : la vérification des deux dossiers avant toute écriture suffit ; un échec d'écriture après création reste possible sur disque plein et laisse un dossier vide, accepté.Décisions prises en planification
is_manually_categorized = 1) et non « règle créée » ni « transactions catégorisées » : le seed IPC met 180 mots-clés dans tout profil neuf et le wizard catégorise pendant l'import (useImportWizard.ts:1016).planned-2026-09-24-paiementss'exécute avant celle-ci (fichiers partagés :fr.json,en.json, CHANGELOG,architecture.md,guide-utilisateur.md) ; partir d'unmainqui contient déjà ses clés.todayvient du webview (date localeYYYY-MM-DD), jamais de l'horloge Rust : commande déterministe et testable.Spec source
spec-plan-onboarding-phase1.md (local, ignoré par git)
Onboarding: create_sample_import_folders Tauri command, sample CSV templates and detection testto Onboarding : commande Tauri create_sample_import_folders, gabarits CSV d'exemple et test de détection