fix: l'export de donnees detruit les configurations d'import #331

Closed
opened 2026-08-12 20:14:34 +00:00 by maximus · 0 comments
Owner

Refs: spec-decisions-import-csv-format.md + spec-plan-import-csv-format.md (racine du repo).

Contexte

Decouvert au re-ancrage de la spec dans le code, hors de la revue initiale.

src/services/dataExportService.ts ne serialise que categories, suppliers, keywords et transactions. Ni import_sources ni import_config_templates ne sont exportes. A l'import, le service fait DELETE FROM import_sources (:265 et :362) puis cree une source factice « Data Import » avec column_mapping = "{}" pour rattacher les transactions.

Consequence : exporter puis reimporter ses donnees detruit definitivement toutes les configurations d'import. Apres une restauration de sauvegarde, chaque source doit etre reconfiguree entierement a la main.

C'est une troisieme voie de perte du format, independante du bug racine et de la derive, et la plus radicale des trois. La laisser ouverte viderait le chantier de son sens.

Taches

  • Serialiser import_sources et import_config_templates dans le format d'export SREF
  • Restaurer les sources a l'import au lieu du DELETE suivi d'une source factice
  • La source factice « Data Import » n'est plus creee que pour rattacher des transactions orphelines
  • Retrocompatibilite : une sauvegarde produite avant ce changement ne porte aucun de ces tableaux — l'import doit alors conserver le comportement actuel plutot qu'echouer
  • Tests de cycle export -> import preservant les configurations
  • Test d'import d'une sauvegarde au format anterieur

Criteres d'acceptation

  • Exporter puis reimporter ses donnees preserve toutes les configurations de sources et tous les modeles
  • Une sauvegarde produite avant ce chantier s'importe sans erreur

Depends on #330


Revision /review-spec — 2026-08-13

Corrections a appliquer, issues de la revue 3 experts :

  • La restauration SREF n'est enveloppee dans aucune transaction — verifie : zero occurrence de withTransaction dans dataExportService.ts. Le service enchaine DELETE FROM transactions / imported_files / import_sources / keywords / suppliers / categories (:263-268, :360-362) puis des db.execute d'insertion. Cette issue ajoute deux boucles d'insertion sur des tables a UNIQUE(name) et une cle etrangere : la moindre violation abandonne la restauration a mi-course et detruit l'historique financier sans retour arriere.
    Fix : envelopper purge + restauration des deux fonctions dans withTransaction, et ajouter un critere d'acceptation — une restauration qui echoue a la ligne N laisse le profil intact.
  • import_config_templates n'est dans aucune des deux listes de purge : reinserer des modeles restaures dans un profil qui en possede deja echoue sur UNIQUE constraint failed: import_config_templates.name. Restaurer dans un profil existant est le chemin normal, pas un cas theorique.
    Fix : specifier l'ordre (modeles avant sources) et la strategie d'identifiants — purger aussi la table, ou upsert par nom et remapper import_sources.template_id.
  • Liste blanche sur amount_mode et sign_convention a la frontiere d'import, avec message lisible. Le CHECK en base (#323) rattrape le cas, mais une erreur de contrainte SQLite n'est pas un message utilisateur.

Fichiers concernes

  • src/services/dataExportService.ts — serialisation, restauration, withTransaction
  • src/services/db.ts — reference du contrat withTransaction
  • src/i18n/locales/fr.json + en.json — messages de refus de liste blanche

Decisions prises en planification

  • Emplacement du code partage : le codec formatToRow/formatFromRow et mapRow vivent dans src/utils/importFormat.ts — meme dossier que amountParser, dateParser et csvAutoDetect, qui portent deja la logique pure du domaine. Les types restent dans src/shared/types/.

  • Aucune correction retroactive des transactions deja importees a l'envers : la voie de reparation est deleteImportWithTransactions puis re-import. Ne jamais muter des montants deja ecrits.

  • L'import reste entierement en edition Free — aucun gating a ajouter.

  • Les specs spec-decisions-import-csv-format.md et spec-plan-import-csv-format.md sont committees a la racine (force-add, precedent PR #295) : elles sont lisibles depuis un worktree.

  • Le format SREF porte un champ de version explicite. A l'import, son absence signifie « format anterieur » : les tableaux import_sources et import_config_templates manquants sont traites comme vides, et l'import se comporte comme aujourd'hui.

Spec source

spec-plan-import-csv-format.md + spec-decisions-import-csv-format.md (racine du repo, committees).

Refs: `spec-decisions-import-csv-format.md` + `spec-plan-import-csv-format.md` (racine du repo). ## Contexte Decouvert au re-ancrage de la spec dans le code, hors de la revue initiale. `src/services/dataExportService.ts` ne serialise que `categories`, `suppliers`, `keywords` et `transactions`. Ni `import_sources` ni `import_config_templates` ne sont exportes. A l'import, le service fait `DELETE FROM import_sources` (`:265` et `:362`) puis cree une source factice « Data Import » avec `column_mapping = "{}"` pour rattacher les transactions. **Consequence : exporter puis reimporter ses donnees detruit definitivement toutes les configurations d'import.** Apres une restauration de sauvegarde, chaque source doit etre reconfiguree entierement a la main. C'est une troisieme voie de perte du format, independante du bug racine et de la derive, et la plus radicale des trois. La laisser ouverte viderait le chantier de son sens. ## Taches - [ ] Serialiser `import_sources` et `import_config_templates` dans le format d'export SREF - [ ] Restaurer les sources a l'import au lieu du `DELETE` suivi d'une source factice - [ ] La source factice « Data Import » n'est plus creee que pour rattacher des transactions orphelines - [ ] **Retrocompatibilite** : une sauvegarde produite avant ce changement ne porte aucun de ces tableaux — l'import doit alors conserver le comportement actuel plutot qu'echouer - [ ] Tests de cycle export -> import preservant les configurations - [ ] Test d'import d'une sauvegarde au format anterieur ## Criteres d'acceptation - [ ] Exporter puis reimporter ses donnees preserve toutes les configurations de sources et tous les modeles - [ ] Une sauvegarde produite avant ce chantier s'importe sans erreur Depends on #330 --- ## Revision /review-spec — 2026-08-13 Corrections a appliquer, issues de la revue 3 experts : - **La restauration SREF n'est enveloppee dans aucune transaction** — verifie : zero occurrence de `withTransaction` dans `dataExportService.ts`. Le service enchaine `DELETE FROM transactions / imported_files / import_sources / keywords / suppliers / categories` (`:263-268`, `:360-362`) puis des `db.execute` d'insertion. Cette issue ajoute deux boucles d'insertion sur des tables a `UNIQUE(name)` et une cle etrangere : **la moindre violation abandonne la restauration a mi-course et detruit l'historique financier sans retour arriere.** Fix : envelopper purge + restauration des deux fonctions dans `withTransaction`, et ajouter un critere d'acceptation — une restauration qui echoue a la ligne N laisse le profil intact. - **`import_config_templates` n'est dans aucune des deux listes de purge** : reinserer des modeles restaures dans un profil qui en possede deja echoue sur `UNIQUE constraint failed: import_config_templates.name`. Restaurer dans un profil existant est le chemin normal, pas un cas theorique. Fix : specifier l'ordre (modeles avant sources) et la strategie d'identifiants — purger aussi la table, ou upsert par nom et remapper `import_sources.template_id`. - **Liste blanche sur `amount_mode` et `sign_convention` a la frontiere d'import**, avec message lisible. Le `CHECK` en base (#323) rattrape le cas, mais une erreur de contrainte SQLite n'est pas un message utilisateur. --- ## Fichiers concernes - `src/services/dataExportService.ts` — serialisation, restauration, `withTransaction` - `src/services/db.ts` — reference du contrat `withTransaction` - `src/i18n/locales/fr.json` + `en.json` — messages de refus de liste blanche ## Decisions prises en planification - **Emplacement du code partage** : le codec `formatToRow`/`formatFromRow` et `mapRow` vivent dans `src/utils/importFormat.ts` — meme dossier que `amountParser`, `dateParser` et `csvAutoDetect`, qui portent deja la logique pure du domaine. Les types restent dans `src/shared/types/`. - **Aucune correction retroactive** des transactions deja importees a l'envers : la voie de reparation est `deleteImportWithTransactions` puis re-import. Ne jamais muter des montants deja ecrits. - **L'import reste entierement en edition Free** — aucun gating a ajouter. - Les specs `spec-decisions-import-csv-format.md` et `spec-plan-import-csv-format.md` sont **committees a la racine** (force-add, precedent PR #295) : elles sont lisibles depuis un worktree. - **Le format SREF porte un champ de version explicite.** A l'import, son absence signifie « format anterieur » : les tableaux `import_sources` et `import_config_templates` manquants sont traites comme vides, et l'import se comporte comme aujourd'hui. ## Spec source `spec-plan-import-csv-format.md` + `spec-decisions-import-csv-format.md` (racine du repo, committees).
maximus added this to the planned-2026-08-12-import-csv-format milestone 2026-08-12 20:14:34 +00:00
maximus added the
status:ready
type:bug
source:human
labels 2026-08-12 20:14:34 +00:00
maximus added
status:in-progress
and removed
status:ready
labels 2026-08-13 19:00:11 +00:00
maximus added
status:approved
and removed
status:in-progress
labels 2026-08-14 15:43:01 +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#331
No description provided.