fix: checklist step 5, secondary-profile migrations and Linux database paths (#390) #394
33 changed files with 5855 additions and 78 deletions
|
|
@ -1,7 +1,16 @@
|
|||
---
|
||||
paths: ["**/migrations/**", "**/*.sql", "**/lib.rs"]
|
||||
paths: ["**/migrations/**", "**/*.sql", "**/lib.rs", "**/profile_db.rs"]
|
||||
---
|
||||
Ne JAMAIS modifier une migration SQL existante. Toujours creer une nouvelle migration.
|
||||
Les checksums sont verifies au demarrage (SHA-384 dans `_sqlx_migrations`).
|
||||
Les migrations sont inline dans `lib.rs` via `tauri_plugin_sql::Migration`.
|
||||
Les checksums sont verifies au demarrage (SHA-384 dans `_sqlx_migrations`) et epingles par le test `migration_checksums_match_the_released_ones`.
|
||||
Les migrations sont inline dans `lib.rs`, rendues par `migrations()` via `tauri_plugin_sql::Migration`.
|
||||
Le schema consolide (`consolidated_schema.sql`) sert uniquement pour les nouveaux profils.
|
||||
|
||||
Depuis #390 (ADR 0021), chaque nouvelle migration atteint deux chemins :
|
||||
- le profil par defaut, migre par tauri-plugin-sql (sqlx) ;
|
||||
- les profils secondaires, rattrapes a l'ouverture par `database::profile_db` (rusqlite), cles etrangeres actives comme sous sqlx.
|
||||
|
||||
Une migration doit donc rester correcte sur les deux, et :
|
||||
- tout changement de schema se reporte dans `consolidated_schema.sql` (le test des etats publies compare chaque profil rattrape a un profil neuf) ;
|
||||
- toute correction de donnees (seed, mots-cles, categories) se reporte AUSSI dans `consolidated_schema.sql` : un nouveau profil nait avec l'historique complet et ne rejoue jamais les migrations ;
|
||||
- ne pas ajouter de marqueur a `infer_floor` : il ne sert qu'aux bases creees avant #390.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
## [Non publié]
|
||||
|
||||
### Corrigé
|
||||
|
||||
- Classer une transaction à la main sur la page Transactions coche désormais l'étape « Classer une transaction à la main » de la liste de démarrage. L'application enregistrait cette marque sous une forme que la liste ne savait pas compter. Les transactions classées à la main avant cette version sont comptées dès l'ouverture du profil, et une sauvegarde exportée entre-temps les restaure correctement (#390).
|
||||
- Les profils autres que le profil par défaut reçoivent désormais les mises à jour de leur base de données. Jusqu'ici, chacun gardait la structure de base de la version qui l'avait créé, et des fonctions ajoutées depuis pouvaient y échouer : dans un profil créé avant la 0.15.0, par exemple, le format d'import enregistré sur une source. À l'ouverture d'un tel profil, l'application garde d'abord une copie de sa base dans le dossier `migration-backups`, à côté des bases, puis applique les mises à jour manquantes. La copie est supprimée avec le profil, et chaque mise à jour est inscrite dans les journaux (Paramètres → Système) (#390).
|
||||
- Sous Linux, supprimer un profil supprime désormais sa base de données, qui restait sur le disque dans `~/.config/com.simpl.resultat/` ; le fichier d'un profil supprimé avec la version 0.17.0 ou antérieure peut être supprimé à la main. Les colonnes de rendement des comptes du Bilan affichent désormais les rendements sous Linux, où chaque cellule affichait un tiret (#390).
|
||||
|
||||
## [0.17.0] - 2026-10-05
|
||||
|
||||
### Ajouté
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Categorizing a transaction by hand on the Transactions page now ticks the "Categorize a transaction by hand" step of the getting-started checklist. The app stored that mark in a form the checklist could not count. Transactions you categorized by hand before this version are counted as soon as the profile is opened, and a backup exported in the meantime restores them correctly (#390).
|
||||
- Profiles other than the default one now receive database updates. Until now each one kept the database layout of the version that created it, so features added since could fail in it: in a profile created before 0.15.0, for instance, the import format saved on a source. When such a profile is opened, the app first keeps a copy of its database in the `migration-backups` folder next to the databases, then applies the missing updates. The copy is deleted with the profile, and each update is written to the logs (Settings → System) (#390).
|
||||
- On Linux, deleting a profile now deletes its database, which used to stay on disk in `~/.config/com.simpl.resultat/`; the file of a profile deleted with version 0.17.0 or earlier can be deleted by hand. The return columns of the Balance sheet accounts now show the returns on Linux, where every cell showed a dash (#390).
|
||||
|
||||
## [0.17.0] - 2026-10-05
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -65,11 +65,12 @@ src-tauri/
|
|||
│ ├── commands/ # 3 modules, 17 commandes Tauri
|
||||
│ │ ├── fs_commands.rs # Système de fichiers (6 commandes)
|
||||
│ │ ├── export_import_commands.rs # Export/import chiffré (5 commandes)
|
||||
│ │ └── profile_commands.rs # Gestion des profils (6 commandes)
|
||||
│ │ └── profile_commands.rs # Gestion des profils (8 commandes)
|
||||
│ ├── database/ # Schémas SQL et migrations
|
||||
│ │ ├── schema.sql # Schéma initial (v1)
|
||||
│ │ ├── seed_categories.sql # Seed catégories (v2)
|
||||
│ │ └── consolidated_schema.sql # Schéma complet (nouveaux profils)
|
||||
│ │ ├── consolidated_schema.sql # Schéma complet (nouveaux profils)
|
||||
│ │ └── profile_db.rs # Rattrapage des profils secondaires (ADR 0021)
|
||||
│ ├── lib.rs # Point d'entrée, 17 migrations inline, plugins
|
||||
│ └── main.rs
|
||||
└── Cargo.toml
|
||||
|
|
@ -120,7 +121,7 @@ src-tauri/
|
|||
|
||||
- **20 tables** SQLite, **24 index** (voir `docs/architecture.md` pour le détail). Le module Bilan en représente 7 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`, puis `balance_securities` + `balance_snapshot_holdings` ajoutées en Étape 2 — détail par titre) et 9 index. Ces deux comptes sont inchangés depuis v13 : v14-v16 ajoutent 2 tables + 2 index (déjà comptés), v17 est un `ALTER TABLE` pur
|
||||
- **17 migrations inline** dans `lib.rs` (v1→v17, via `tauri_plugin_sql::Migration`). Étape 2 du Bilan (détail par titre) : v14 (`balance_securities` + `balance_snapshot_holdings` + 2 index), v15 (`balance_accounts.kind` + `detailed_since` + backfill), v16 (conversion des comptes cotés existants en détaillés 1-position) — voir [ADR 0015](docs/adr/0015-balance-detail-par-titre.md). Import : v17 (`import_sources.amount_mode` + `sign_convention`, les deux avec `CHECK`, + `header_signature` + `template_id`) — voir [ADR 0019](docs/adr/0019-format-import-persiste.md)
|
||||
- **Schéma consolidé** (`consolidated_schema.sql`) pour l'initialisation des nouveaux profils
|
||||
- **Schéma consolidé** (`consolidated_schema.sql`) pour l'initialisation des nouveaux profils, suivi de l'historique complet des migrations. tauri-plugin-sql ne migre que le profil par défaut : les profils secondaires rattrapent leurs migrations à chaque ouverture (`prepare_profile_db`, copie préalable, clés étrangères actives) — voir [ADR 0021](docs/adr/0021-migrations-profils-secondaires.md). Les bases vivent sous `app_config_dir()` (`profile_db_path`), qui n'est pas `app_data_dir()` sous Linux
|
||||
- Les migrations appliquées sont protégées par checksum — ne jamais modifier une migration existante, toujours en créer une nouvelle
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -40,3 +40,7 @@ Les 6 migrations actuelles :
|
|||
- **Immutabilité** : une migration appliquée ne peut jamais être modifiée (erreur de checksum), ce qui force la création de nouvelles migrations correctives
|
||||
- **Synchronisation manuelle** : le fichier `consolidated_schema.sql` doit être mis à jour manuellement après chaque nouvelle migration
|
||||
- **Pas de rollback** : les migrations sont unidirectionnelles (pas de `down`)
|
||||
|
||||
## Amendement #390 (2026-10-06)
|
||||
|
||||
Le schéma consolidé **crée** un profil secondaire, il ne le tient pas à jour. tauri-plugin-sql n'applique les migrations qu'à la base enregistrée par `add_migrations`, celle du profil par défaut (`simpl_resultat.db`). Jusqu'à #390, un profil secondaire gardait le schéma de la version qui l'avait créé. Depuis #390, un nouveau profil reçoit à sa création l'historique complet de `_sqlx_migrations`, et la commande `prepare_profile_db` applique à chaque ouverture les versions qui manquent à un profil secondaire. Voir l'[ADR 0021](0021-migrations-profils-secondaires.md). Les six migrations listées plus haut sont celles de 2025 ; il y en a dix-sept à la v0.17.0.
|
||||
|
|
|
|||
|
|
@ -38,3 +38,12 @@ Architecture :
|
|||
- **Pas de vue agrégée** : impossible de voir les données de tous les profils en même temps
|
||||
- **Synchronisation du schéma** : chaque base doit être au même niveau de migration (géré par le plugin sql au démarrage)
|
||||
- **Fichier `profiles.json` externe** : les métadonnées des profils ne sont pas dans SQLite, ce qui crée une dépendance à un fichier JSON séparé
|
||||
|
||||
## Amendement #390 (2026-10-06)
|
||||
|
||||
Deux affirmations des conséquences étaient fausses jusqu'à #390 :
|
||||
|
||||
- « Les migrations s'appliquent indépendamment à chaque base » et « géré par le plugin sql au démarrage » : le plugin ne migre que la base du profil par défaut. Un profil secondaire gardait le schéma de la version qui l'avait créé. Il rattrape désormais ses migrations à chaque ouverture ([ADR 0021](0021-migrations-profils-secondaires.md)).
|
||||
- « Supprimer un profil = supprimer un fichier `.db` » : sous Linux, la commande cherchait la base sous `app_data_dir()` alors que le plugin la range sous `app_config_dir()`, et le fichier restait sur le disque. La suppression vise désormais le dossier du plugin et emporte aussi les fichiers annexes de SQLite et les copies prises avant un rattrapage.
|
||||
|
||||
`profiles.json` reste dans le répertoire de données de l'application (`app_data_dir()`) ; les bases sont dans le répertoire de configuration (`app_config_dir()`), qui n'est le même dossier que sous Windows et macOS.
|
||||
|
|
|
|||
90
docs/adr/0021-migrations-profils-secondaires.md
Normal file
90
docs/adr/0021-migrations-profils-secondaires.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# ADR 0021 — Les profils secondaires rattrapent leurs migrations à l'ouverture
|
||||
|
||||
- Status: **Accepted**
|
||||
- Date: 2026-10-06
|
||||
- Issues: #390
|
||||
- Modifie l'[ADR 0003](0003-sqlx-migrations.md) (le schéma consolidé crée un profil, il ne le tient pas à jour) et l'[ADR 0005](0005-multi-profile-db.md) (« les migrations s'appliquent indépendamment à chaque base » était faux pour les profils secondaires)
|
||||
|
||||
## Contexte
|
||||
|
||||
Le constat de départ est un bug d'onboarding : classer une transaction à la main ne cochait pas la case 5 de la liste de démarrage. `updateTransactionCategory` liait le booléen JS `true`, que tauri-plugin-sql 2.3.2 transmet à sqlx comme une valeur JSON, donc stockée en texte `'true'`. La liste compte `is_manually_categorized = 1` et ne trouvait rien. Corriger les valeurs déjà en base par une migration v18 a fait apparaître deux défauts plus anciens.
|
||||
|
||||
**Les profils secondaires ne reçoivent aucune migration.** Le plugin associe la liste des migrations à une URL (`add_migrations("sqlite:simpl_resultat.db", …)`) et la retire au premier `Database.load`. Un profil secondaire (`profile_<id>.db`, depuis la v0.3.0) est créé par `initializeNewProfileDb` avec le schéma consolidé de la version qui le crée, puis n'en reçoit plus aucune. Un profil secondaire créé avant la v0.15.0 n'a donc pas les colonnes de format de `import_sources` (v17), et un profil créé avant la v0.10.0 n'a ni `balance_securities` ni `balance_accounts.kind`. Les commentaires de `consolidated_schema.sql` et de `get_new_profile_init_sql`, ainsi que l'ADR 0005, affirmaient le contraire.
|
||||
|
||||
**Trois commandes cherchaient les bases au mauvais endroit sous Linux.** Le plugin range les bases sous `app_config_dir()` (`wrapper.rs` : `DbPool::connect` puis `path_mapper`). `repair_migrations`, `delete_profile_db` et `compute_account_return` les cherchaient sous `app_data_dir()`, là où vivent `profiles.json` et les fichiers de licence. C'est le même dossier sous Windows et macOS, pas sous Linux (`~/.config/com.simpl.resultat` et `~/.local/share/com.simpl.resultat`). Sous Linux, `repair_migrations` ne faisait donc rien, supprimer un profil laissait sa base sur le disque, et le rendement d'un compte du Bilan échouait.
|
||||
|
||||
## Décision
|
||||
|
||||
**À chaque ouverture d'un profil, avant `Database.load`, la commande `prepare_profile_db` amène un profil secondaire à la dernière migration, avec la même liste que le profil par défaut, et répare les drapeaux texte de tous les profils.** Neuf règles la tiennent ; le code est dans `src-tauri/src/database/profile_db.rs`.
|
||||
|
||||
### 1. Une seule liste de migrations
|
||||
|
||||
`migrations()` (lib.rs) sert le plugin et le rattrapage. Le test `migration_checksums_match_the_released_ones` épingle le SHA-384 de chaque version, calculé avant que la liste soit sortie de `run()`. L'historique d'un profil secondaire vit dans la même table `_sqlx_migrations` que celui du profil par défaut, au format sqlx : même DDL, même checksum.
|
||||
|
||||
### 2. Un nouveau profil naît avec son historique
|
||||
|
||||
`get_new_profile_init_sql` renvoie le schéma consolidé, puis `history_sql`, qui inscrit toutes les versions avec leur checksum. Le plugin exécute les deux dans le même flux. Un profil créé depuis #390 n'a donc jamais rien à déduire : les versions suivantes l'atteignent par le rattrapage.
|
||||
|
||||
### 3. Un profil sans historique : un plancher déduit du schéma
|
||||
|
||||
Les profils créés avant #390 n'ont pas d'historique. Ils forment un ensemble fermé, un état par schéma consolidé qu'une version publiée a livré, et chaque état est conservé en fixture sous `src-tauri/src/database/fixtures/` :
|
||||
|
||||
| État | Versions qui l'ont créé | Plancher |
|
||||
|---|---|---|
|
||||
| A1 | v0.3.0 à v0.8.3, sauf v0.4.0 | 6 |
|
||||
| A2 | v0.4.0 (seed à trois niveaux, retiré en v0.4.1) | 6 |
|
||||
| B | v0.8.4 | 8 |
|
||||
| C et D | v0.9.0, v0.9.1 (même schéma ; v11 ne touche que des données) | 10 |
|
||||
| E | v0.10.0 à v0.14.0 | 16 |
|
||||
| F | v0.15.0 à v0.17.x | 17 |
|
||||
|
||||
`infer_floor` reconnaît l'état par la dernière colonne ou table ajoutée, en partant de la plus récente. Le plancher vient du schéma, jamais de l'historique : une première écriture interrompue ne peut donc pas faire passer une version inférieure pour une version à appliquer. C'est ce qui interdit de rejouer le seed v2 (`DELETE FROM categories`) sur une base remplie. Un schéma qu'aucun marqueur ne reconnaît n'est pas touché. Aucun marqueur ne s'ajoute après la v17, puisqu'aucune base sans historique ne peut porter une version postérieure.
|
||||
|
||||
### 4. Une copie avant la première écriture
|
||||
|
||||
Quand une version reste à appliquer, la base est d'abord copiée par `VACUUM INTO` vers `<dossier des bases>/migration-backups/<profil>-before-v<N>.db`. Le chemin est lié, jamais formaté dans le SQL, ce qui tient un dossier comme `C:\Users\L'Heureux`. La copie est écrite en `.tmp`, synchronisée sur disque, puis renommée : un fichier final existant est donc complet, et il est gardé tel quel. Une copie qui échoue arrête tout avant la moindre écriture. La copie est supprimée avec le profil.
|
||||
|
||||
Elle reste dans le dossier des bases, pas dans `~/Documents/Simpl-Resultat/backups/` que la sauvegarde manuelle utilise : ce dossier est souvent synchronisé vers un service en ligne (OneDrive sous Windows), et une copie automatique en clair d'une base financière n'a rien à y faire.
|
||||
|
||||
### 5. Des écritures atomiques
|
||||
|
||||
L'historique, soit la table et chaque version jusqu'au plancher, est écrit en une transaction. Chaque version à appliquer s'exécute ensuite dans sa propre transaction. La première erreur arrête le rattrapage et les versions déjà appliquées restent inscrites.
|
||||
|
||||
### 6. Les clés étrangères restent actives
|
||||
|
||||
Comme sqlx pour le profil par défaut. Une version qui échoue sur une clé étrangère est reprise une fois sans elles. Les lignes qu'elle laisse sans parent repassent à NULL quand leur clé déclare `ON DELETE SET NULL` ; toute autre violation annule la version. Le cas réel est la v7, qui ajoute trois sous-catégories sous la catégorie 31 : un profil A dont les catégories viennent d'une restauration plus récente n'a plus de catégorie 31, et les trois sous-catégories deviennent des catégories racines. Couper les clés pour tout le rattrapage aurait laissé ces parents introuvables, et la restauration d'une sauvegarde de ce profil aurait échoué.
|
||||
|
||||
### 7. L'échec reste ouvert
|
||||
|
||||
Un rattrapage interrompu est écrit au Journal et le profil s'ouvre comme avant #390. Les messages nomment des fichiers, jamais le dossier : il contient le nom d'utilisateur du système, et une ligne d'erreur du Journal peut être jointe à une rétroaction (Loi 25).
|
||||
|
||||
### 8. Un seul dossier des bases
|
||||
|
||||
`profile_db_path` résout `app_config_dir()`, le dossier du plugin, pour les quatre commandes qui ouvrent une base. Il n'accepte que les deux formes de nom que l'application a jamais données : `simpl_resultat.db` et `profile_<hex>.db`.
|
||||
|
||||
### 9. Les drapeaux texte sont réparés partout
|
||||
|
||||
À chaque ouverture, dans tous les profils, `'true'` devient 1 et tout autre texte 0. L'opération est idempotente. Côté TypeScript, `toSqlFlag` empêche d'écrire de nouveau un booléen, y compris à la restauration d'une sauvegarde qui porte encore `"true"`.
|
||||
|
||||
## Conséquences
|
||||
|
||||
### Positives
|
||||
|
||||
- Un profil secondaire ancien retrouve le schéma courant à sa prochaine ouverture, et chaque migration future l'atteint.
|
||||
- Sous Linux, supprimer un profil supprime enfin sa base, ses fichiers annexes et ses copies.
|
||||
- Les règles sont éprouvées sur les sept états réels, avec des données d'utilisateur : comptes du Bilan convertis par v12 à v16, source d'import complétée par v17, drapeau réparé.
|
||||
|
||||
### Négatives et points de vigilance
|
||||
|
||||
- **Une correction de données livrée seulement en migration n'atteint pas un nouveau profil**, qui naît avec l'historique complet. Elle doit aussi entrer dans `consolidated_schema.sql` (règle `.claude/rules/sql-migrations.md`). Le test qui compare chaque état rattrapé à un profil neuf ne regarde que le schéma.
|
||||
- **Deux moteurs appliquent les mêmes migrations** : sqlx pour le profil par défaut, rusqlite pour les autres. Le SQL est le même et les clés étrangères sont actives des deux côtés. La reprise sans clés étrangères n'existe que du côté rusqlite.
|
||||
- **La commande est synchrone.** Tauri l'exécute sur le fil principal, ce qui sérialise deux ouvertures du même profil (React StrictMode monte deux fois en développement). L'interface attend pendant un rattrapage, une fois par profil ancien, et la durée est écrite au Journal.
|
||||
- **Le test qui distingue les deux dossiers ne voit l'écart que sous Linux**, la plateforme de la CI. La vérification à la main sous Linux reste due.
|
||||
- **Les profils supprimés sous Linux avant ce correctif** ont laissé leur base dans `~/.config/com.simpl.resultat/`. Rien ne supprime automatiquement un fichier que `profiles.json` ne cite pas : un `profiles.json` abîmé coûterait alors de vrais profils.
|
||||
|
||||
## Alternatives écartées
|
||||
|
||||
- **Une migration v18 de données**, proposée par le corps de #390 : elle n'aurait réparé que le profil par défaut.
|
||||
- **Enregistrer chaque profil auprès du plugin au démarrage** (`add_migrations` par URL dans `setup`) : l'état des migrations du plugin est privé et figé au démarrage, un profil créé en cours de session n'y figurerait pas, et sqlx aurait rejoué v1 et v2 sur une base sans historique.
|
||||
- **Un rattrapage côté TypeScript** : le plugin n'expose aucune transaction (voir `db.ts`), et ni `VACUUM INTO` ni les clés étrangères ne seraient testables hors de Tauri.
|
||||
- **Des clés étrangères coupées pendant tout le rattrapage** : les actions `ON DELETE` ne joueraient plus comme sur le profil par défaut, et les lignes sans parent feraient échouer la restauration d'une sauvegarde de ce profil.
|
||||
|
|
@ -44,7 +44,7 @@ simpl-resultat/
|
|||
│ ├── pages/ # 14 pages (dont 4 sous-pages rapports)
|
||||
│ ├── services/ # 25 services métier (19 détaillés dans la section « Services TypeScript »)
|
||||
│ ├── shared/ # Types, constantes, matrice d'entitlements (entitlements.ts), gate profils (profileGate.ts), CTA d'upsell (upsellCta.ts), URL d'achat (purchaseUrl.ts), échéance de licence (licenseExpiry.ts)
|
||||
│ ├── utils/ # 13 utilitaires purs (parsing montants/dates, détection CSV, codec de format d'import, dictionnaire lexical, signatures de banques, charts)
|
||||
│ ├── utils/ # 14 utilitaires purs (parsing montants/dates, détection CSV, codec de format d'import, dictionnaire lexical, signatures de banques, charts, drapeaux SQL 0/1)
|
||||
│ ├── i18n/ # Config i18next + locales FR/EN
|
||||
│ ├── __fixtures__/ # csv/ : corpus de détection (15 cas figés) ; samples/ : gabarits du dossier d'exemple embarqués par Rust
|
||||
│ ├── App.tsx # Router principal
|
||||
|
|
@ -61,7 +61,9 @@ simpl-resultat/
|
|||
│ │ ├── database/ # Schémas SQL et migrations
|
||||
│ │ │ ├── schema.sql
|
||||
│ │ │ ├── seed_categories.sql
|
||||
│ │ │ └── consolidated_schema.sql
|
||||
│ │ │ ├── consolidated_schema.sql
|
||||
│ │ │ ├── profile_db.rs # Rattrapage des profils secondaires (#390, ADR 0021)
|
||||
│ │ │ └── fixtures/ # Schémas de création des profils publiés (tests)
|
||||
│ │ ├── lib.rs # Point d'entrée, migrations, plugins
|
||||
│ │ └── main.rs
|
||||
│ ├── capabilities/ # Permissions Tauri
|
||||
|
|
@ -164,13 +166,22 @@ Les migrations sont définies inline dans `src-tauri/src/lib.rs` via `tauri_plug
|
|||
|
||||
v17 est purement additive : elle n'ajoute **ni table ni index** (20 tables / 24 index inchangés). Le `CHECK` d'`amount_mode` admet `absolute_indicator` dès maintenant, pour que le troisième mode de montant puisse être livré sans nouvelle migration, alors que l'application le **refuse** encore explicitement (voir plus bas). `LIKE` plutôt que `json_extract` : la migration ne dépend d'aucune extension JSON1 dans le SQLite embarqué. `sign_convention` n'est délibérément pas backfillée — son `DEFAULT` restitue la valeur que le code codait en dur, la seule convention passée inférable.
|
||||
|
||||
Pour les **nouveaux profils**, le fichier `consolidated_schema.sql` contient le schéma complet avec toutes les migrations pré-appliquées (pas besoin de rejouer les migrations).
|
||||
La liste est rendue par `migrations()` (lib.rs) ; tauri-plugin-sql ne l'applique qu'à la base du **profil par défaut** (`simpl_resultat.db`, seule URL passée à `add_migrations`). Un test épingle le SHA-384 de chaque version.
|
||||
|
||||
Les **profils secondaires** (`profile_<id>.db`) sont créés par `get_new_profile_init_sql` : le fichier `consolidated_schema.sql`, qui porte le schéma complet, puis `history_sql`, qui inscrit toutes les versions dans `_sqlx_migrations` au format sqlx. Le plugin ne les migre jamais. Depuis #390, `prepare_profile_db` les rattrape à chaque ouverture, avant `Database.load` ([ADR 0021](adr/0021-migrations-profils-secondaires.md), `src-tauri/src/database/profile_db.rs`) :
|
||||
|
||||
- une base sans historique (créée avant #390) reçoit un **plancher** déduit de son schéma (`infer_floor`) : 6, 8, 10, 16 ou 17 selon la version qui l'a créée, tous rejoués en test depuis `database/fixtures/`. Aucune version au plus égale au plancher n'est rejouée ;
|
||||
- avant la première version à appliquer, une copie `VACUUM INTO` est prise dans `migration-backups/` à côté des bases, puis supprimée avec le profil ;
|
||||
- chaque version s'applique dans sa transaction, clés étrangères actives comme sous sqlx. Une version qui bute sur une clé est reprise une fois sans elles, et ses lignes sans parent repassent à NULL si la clé déclare `ON DELETE SET NULL` ;
|
||||
- la même commande répare dans tous les profils les drapeaux `is_manually_categorized` stockés en texte (`'true'` → 1).
|
||||
|
||||
Le dossier des bases est celui du plugin : `app_config_dir()`, résolu par `profile_db_path` (`profile_commands.rs`). Il diffère de `app_data_dir()`, où vit `profiles.json`, sous Linux seulement (`~/.config/com.simpl.resultat` et `~/.local/share/com.simpl.resultat`).
|
||||
|
||||
## Services TypeScript (19)
|
||||
|
||||
| Service | Responsabilité |
|
||||
|---------|---------------|
|
||||
| `db.ts` | Wrapper de connexion (tauri-plugin-sql) |
|
||||
| `db.ts` | Wrapper de connexion (tauri-plugin-sql). `connectToProfile` appelle `repair_migrations` puis `prepare_profile_db` avant `Database.load`, et écrit au Journal ce que la préparation a changé (`describePreparation`, noms de fichiers seulement, #390) ; un échec est écrit au Journal et le profil s'ouvre quand même |
|
||||
| `profileService.ts` | Gestion des profils |
|
||||
| `categoryService.ts` | CRUD catégories hiérarchiques |
|
||||
| `transactionService.ts` | CRUD et filtrage des transactions ; détection d'erreurs FK RESTRICT pour transactions liées à un compte de bilan (typed `TransactionLinkedToBalanceError`) ; `getTransactionCount` (compte brut de la table, sans filtre — signal des états vides de Transactions et Budget, #351/#353) |
|
||||
|
|
@ -340,7 +351,7 @@ Depuis le chantier #297-#301, l'accès aux modules est gaté par l'édition de l
|
|||
|
||||
Modules Free — jamais gatés, aucune `FeatureKey` : Dashboard, Import, Transactions, Catégories, hub `/reports` + `/reports/trends`, Export/Import, Paramètres, Changelog, docs. Le déclassement d'édition est **non destructif** : les données des modules verrouillés restent en base et redeviennent accessibles avec une clé valide.
|
||||
|
||||
## Commandes Tauri (38)
|
||||
## Commandes Tauri (39)
|
||||
|
||||
### `fs_commands.rs` — Système de fichiers (7)
|
||||
|
||||
|
|
@ -360,15 +371,18 @@ Modules Free — jamais gatés, aucune `FeatureKey` : Dashboard, Import, Transac
|
|||
- `read_import_file` — Lecture fichier chiffré
|
||||
- `is_file_encrypted` — Vérification magic SREF
|
||||
|
||||
### `profile_commands.rs` — Gestion des profils (7)
|
||||
### `profile_commands.rs` — Gestion des profils (8)
|
||||
|
||||
Les commandes qui ouvrent une base passent par `profile_db_path` : dossier du plugin (`app_config_dir()`) et nom de fichier validé (`simpl_resultat.db` ou `profile_<hex>.db`, #390).
|
||||
|
||||
- `load_profiles` — Chargement depuis `profiles.json`
|
||||
- `save_profiles` — Sauvegarde de la configuration
|
||||
- `delete_profile_db` — Suppression du fichier de base de données
|
||||
- `get_new_profile_init_sql` — Récupération du schéma consolidé
|
||||
- `delete_profile_db` — Suppression de la base d'un profil secondaire, de ses fichiers annexes SQLite (`-wal`, `-shm`, `-journal`) et de ses copies `migration-backups/` (#390)
|
||||
- `get_new_profile_init_sql` — Schéma consolidé suivi de l'historique complet des migrations (`history_sql`, #390)
|
||||
- `hash_pin` — Hachage Argon2id du PIN (format `argon2id:salt:hash`)
|
||||
- `verify_pin` — Vérification du PIN (supporte Argon2id et legacy SHA-256 pour rétrocompatibilité)
|
||||
- `repair_migrations` — Réparation des checksums de migration (rusqlite)
|
||||
- `prepare_profile_db` — Avant chaque ouverture : rattrapage des migrations d'un profil secondaire (copie préalable) et réparation des drapeaux de classement manuel de tout profil. Rend un rapport sans chemin (`ProfilePreparation`). Synchrone, donc sérialisée sur le fil principal — [ADR 0021](adr/0021-migrations-profils-secondaires.md)
|
||||
|
||||
### `license_commands.rs` — Licence et activation machine (11)
|
||||
|
||||
|
|
@ -427,7 +441,7 @@ Module privé appelé uniquement par `auth_commands.rs` et `license_commands.rs`
|
|||
|
||||
### `balance_commands.rs` — Bilan (1)
|
||||
|
||||
- `compute_account_return(account_id, period_start, period_end, db_filename)` — Calcul Modified Dietz d'un compte sur une période. Ouvre une connexion `rusqlite` courte sur le fichier DB du profil actif, lit le snapshot ≤ `period_start`, le snapshot ≥ `period_end` et tous les `balance_account_transfers` JOIN `transactions` dans la fenêtre, puis appelle `return_calculator::modified_dietz`. Retourne `AccountReturn { value_start, value_end, net_contributions, return_pct, annualized_pct, is_partial, has_no_transfers_warning }`. Voir [ADR 0008](adr/0008-modified-dietz-pour-rendement.md).
|
||||
- `compute_account_return(account_id, period_start, period_end, db_filename)` — Calcul Modified Dietz d'un compte sur une période. Ouvre une connexion `rusqlite` courte sur le fichier DB du profil actif (résolu par `profile_db_path` ; sous Linux, l'ancien chemin `app_data_dir()` faisait échouer le calcul, #390), lit le snapshot ≤ `period_start`, le snapshot ≥ `period_end` et tous les `balance_account_transfers` JOIN `transactions` dans la fenêtre, puis appelle `return_calculator::modified_dietz`. Retourne `AccountReturn { value_start, value_end, net_contributions, return_pct, annualized_pct, is_partial, has_no_transfers_warning }`. Voir [ADR 0008](adr/0008-modified-dietz-pour-rendement.md).
|
||||
|
||||
Le module privé `return_calculator.rs` (déclaré dans `commands/mod.rs` mais non exposé comme commande) contient la logique pure Modified Dietz et ses tests `#[cfg(test)] mod tests` co-localisés (TDD, 7 cas : nominal / pas de snapshot début / partial / créé en cours / vidé / sans transferts / annualisation).
|
||||
|
||||
|
|
@ -480,6 +494,7 @@ Les modules payants sont enveloppés dans des **layout-routes pathless `RequireF
|
|||
- **Timeout au démarrage** : `App.tsx` applique un timeout de 10 secondes sur `connectActiveProfile()` — affiche `ErrorPage` au lieu d'un spinner infini si la connexion DB échoue
|
||||
- **Retry au démarrage** : `connectActiveProfile()` réessaie jusqu'à 3 fois avec 1s de délai avant d'afficher l'erreur
|
||||
- **Réparation de migrations** : `repair_migrations` (Rust/rusqlite) supprime les checksums invalides de `_sqlx_migrations` avant le chargement de la DB
|
||||
- **Préparation du profil** : `prepare_profile_db` (Rust/rusqlite) rattrape les migrations d'un profil secondaire et répare les drapeaux texte avant le chargement ; un échec est écrit au Journal, le profil s'ouvre quand même (#390)
|
||||
- **Log viewer** : `logService.ts` capture les `console.log/warn/error` dans un buffer circulaire (500 entrées, persisté en `sessionStorage`), affiché dans la page Paramètres via `LogViewerCard`
|
||||
|
||||
| Route | Page | Description |
|
||||
|
|
@ -590,3 +605,4 @@ Les ADRs documentent les décisions techniques structurantes. Ils vivent dans `d
|
|||
| [0018](adr/0018-suppression-advisories-non-atteignables.md) | Suppression d'advisories non atteignables : admission sur preuve par cible livrée, clé par ID, garde-fou bloquant | 2026-07-27 | Accepted |
|
||||
| [0019](adr/0019-format-import-persiste.md) | Le format d'import est une donnée persistée intégralement, jamais re-devinée | 2026-08-13 | Accepted |
|
||||
| [0020](adr/0020-identifiant-machine-derive.md) | Identifiant machine dérivé : un hachage à clé fixe remplace l'identifiant du système auprès du serveur de licences | 2026-10-01 | Accepted |
|
||||
| [0021](adr/0021-migrations-profils-secondaires.md) | Les profils secondaires rattrapent leurs migrations à l'ouverture | 2026-10-06 | Accepted |
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ Gérez plusieurs profils indépendants, chacun avec sa propre base de données.
|
|||
- Un profil par défaut est créé automatiquement au premier lancement
|
||||
- Le NIP est demandé à chaque fois que vous accédez à un profil protégé
|
||||
- La suppression d'un profil supprime définitivement toutes ses données — cette action est irréversible
|
||||
- À l'ouverture d'un profil créé par une version antérieure, l'application met sa base à jour après en avoir gardé une copie dans le dossier `migration-backups`, à côté des bases (sous Linux `~/.config/com.simpl.resultat/`, sous Windows `%APPDATA%\com.simpl.resultat\`). La copie est supprimée avec le profil
|
||||
- Sous Linux, les versions jusqu'à la 0.17.0 laissaient sur le disque la base d'un profil supprimé (`~/.config/com.simpl.resultat/profile_….db`) ; vous pouvez supprimer ce fichier à la main
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ hmac = "0.12"
|
|||
ed25519-dalek = { version = "2", features = ["pkcs8", "rand_core"] }
|
||||
# HTTP mock server for balance_commands fetch_price tests (Issue #155).
|
||||
mockito = "1.6"
|
||||
# MockRuntime for the profile database folder test (#390). The `test`
|
||||
# feature adds no crate (`test = []` in tauri's manifest).
|
||||
tauri = { version = "2", features = ["test"] }
|
||||
|
||||
[features]
|
||||
# Dev-only escape hatch: when enabled, the SR_DEV_EDITION env var forces the
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
//! `Authorization`, `Accept`, and `User-Agent` headers.
|
||||
//!
|
||||
//! Database access pattern:
|
||||
//! - All reads use `rusqlite::Connection::open(app_data_dir / db_filename)`,
|
||||
//! matching the existing `repair_migrations` helper in `profile_commands.rs`.
|
||||
//! - All reads open the file `profile_db_path` resolves (`profile_commands.rs`):
|
||||
//! the folder where tauri-plugin-sql keeps the databases, which is NOT
|
||||
//! `app_data_dir` on Linux (#390).
|
||||
//! - The frontend passes `db_filename` (the active profile DB), exactly
|
||||
//! like it does for `repair_migrations` and `delete_profile_db`. Keeps
|
||||
//! the active-profile resolution where it already lives (in TS) and
|
||||
|
|
@ -258,16 +259,10 @@ pub fn compute_account_return(
|
|||
let start_date = parse_iso_date(&period_start, "period_start")?;
|
||||
let end_date = parse_iso_date(&period_end, "period_end")?;
|
||||
|
||||
let app_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|e| format!("Cannot get app data dir: {}", e))?;
|
||||
let db_path = app_dir.join(&db_filename);
|
||||
let db_path = super::profile_commands::profile_db_path(&app, &db_filename)?;
|
||||
if !db_path.exists() {
|
||||
return Err(format!(
|
||||
"Profile database not found: {}",
|
||||
db_path.display()
|
||||
));
|
||||
// The file name only: the folder holds the OS user name.
|
||||
return Err(format!("Profile database not found: {}", db_filename));
|
||||
}
|
||||
|
||||
let conn = Connection::open(&db_path)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ use rand::RngCore;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256, Sha384};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use subtle::ConstantTimeEq;
|
||||
use tauri::Manager;
|
||||
|
||||
use crate::database;
|
||||
use crate::database::profile_db;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Profile {
|
||||
|
|
@ -32,6 +34,49 @@ fn get_profiles_path(app: &tauri::AppHandle) -> Result<std::path::PathBuf, Strin
|
|||
Ok(app_dir.join("profiles.json"))
|
||||
}
|
||||
|
||||
/// Folder where tauri-plugin-sql keeps every profile database.
|
||||
///
|
||||
/// The plugin opens `sqlite:<file>` under `app_config_dir()` (tauri-plugin-sql
|
||||
/// 2.3.2, `wrapper.rs`: `DbPool::connect` then `path_mapper`), not under
|
||||
/// `app_data_dir()`, where `profiles.json` and the licence files live. Both
|
||||
/// are the same folder on Windows and macOS, not on Linux (`~/.config/<id>`
|
||||
/// and `~/.local/share/<id>`): until #390, every command that looked for a
|
||||
/// profile database under `app_data_dir()` found nothing on Linux.
|
||||
pub(crate) fn profile_db_dir<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> Result<PathBuf, String> {
|
||||
app.path()
|
||||
.app_config_dir()
|
||||
.map_err(|e| format!("Cannot get app config dir: {}", e))
|
||||
}
|
||||
|
||||
/// Path of a profile database, from the bare file name the webview passes.
|
||||
pub(crate) fn profile_db_path<R: tauri::Runtime>(
|
||||
app: &tauri::AppHandle<R>,
|
||||
db_filename: &str,
|
||||
) -> Result<PathBuf, String> {
|
||||
profile_db_path_in(&profile_db_dir(app)?, db_filename)
|
||||
}
|
||||
|
||||
/// Accept only the two shapes the app ever gives a profile database:
|
||||
/// `simpl_resultat.db` and `profile_<hex>.db` (ProfileContext, since v0.3.0).
|
||||
/// `Path::join` with an absolute value would replace the folder, and these
|
||||
/// commands write and delete.
|
||||
pub(crate) fn profile_db_path_in(dir: &Path, db_filename: &str) -> Result<PathBuf, String> {
|
||||
if !is_profile_db_filename(db_filename) {
|
||||
return Err("invalid_profile_db_filename".to_string());
|
||||
}
|
||||
Ok(dir.join(db_filename))
|
||||
}
|
||||
|
||||
fn is_profile_db_filename(name: &str) -> bool {
|
||||
if name == database::DEFAULT_PROFILE_DB {
|
||||
return true;
|
||||
}
|
||||
match name.strip_prefix("profile_").and_then(|rest| rest.strip_suffix(".db")) {
|
||||
Some(id) => !id.is_empty() && id.bytes().all(|b| b.is_ascii_hexdigit()),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_default_config() -> ProfilesConfig {
|
||||
let now = chrono_now();
|
||||
let default_id = "default".to_string();
|
||||
|
|
@ -92,35 +137,63 @@ pub fn save_profiles(app: tauri::AppHandle, config: ProfilesConfig) -> Result<()
|
|||
fs::write(&path, json).map_err(|e| format!("Cannot write profiles.json: {}", e))
|
||||
}
|
||||
|
||||
/// Delete a secondary profile's database, with its SQLite side files and the
|
||||
/// copies a catch-up took (#390): the guide promises that deleting a profile
|
||||
/// deletes all its data.
|
||||
#[tauri::command]
|
||||
pub fn delete_profile_db(app: tauri::AppHandle, db_filename: String) -> Result<(), String> {
|
||||
if db_filename == "simpl_resultat.db" {
|
||||
if db_filename == database::DEFAULT_PROFILE_DB {
|
||||
return Err("Cannot delete the default profile database".to_string());
|
||||
}
|
||||
let db_path = profile_db_path(&app, &db_filename)?;
|
||||
delete_profile_files(&db_path, &db_filename)
|
||||
}
|
||||
|
||||
let app_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|e| format!("Cannot get app data dir: {}", e))?;
|
||||
let db_path = app_dir.join(&db_filename);
|
||||
|
||||
if db_path.exists() {
|
||||
fs::remove_file(&db_path)
|
||||
.map_err(|e| format!("Cannot delete database file: {}", e))?;
|
||||
fn delete_profile_files(db_path: &Path, db_filename: &str) -> Result<(), String> {
|
||||
for suffix in ["", "-wal", "-shm", "-journal"] {
|
||||
let path = db_path.with_file_name(format!("{}{}", db_filename, suffix));
|
||||
if path.exists() {
|
||||
fs::remove_file(&path).map_err(|e| format!("Cannot delete database file: {}", e))?;
|
||||
}
|
||||
}
|
||||
if let Some(dir) = db_path.parent() {
|
||||
profile_db::remove_backups(
|
||||
&dir.join(profile_db::MIGRATION_BACKUP_DIR),
|
||||
db_filename.trim_end_matches(".db"),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// SQL that creates a secondary profile, run by the webview through the
|
||||
/// plugin (`initializeNewProfileDb`).
|
||||
#[tauri::command]
|
||||
pub fn get_new_profile_init_sql() -> Result<Vec<String>, String> {
|
||||
// Brand-new profiles ship with the v1 IPC-aligned category taxonomy: the
|
||||
// consolidated schema bakes the v1 seed (categories + keywords + the
|
||||
// categories_schema_version='v1' preference) directly. The legacy v2 seed
|
||||
// migration still runs first because tauri-plugin-sql applies every
|
||||
// declared migration on `Database.load`; the consolidated script then
|
||||
// deletes the v2 rows and re-inserts the v1 rows in the 1000+ id range.
|
||||
Ok(vec![database::CONSOLIDATED_SCHEMA.to_string()])
|
||||
// The consolidated schema is the whole database: tauri-plugin-sql runs no
|
||||
// migration for a `profile_<id>.db`, only the default profile's URL is
|
||||
// registered (lib.rs). It carries the v1 IPC-aligned taxonomy (categories,
|
||||
// keywords, categories_schema_version='v1'). The second statement writes
|
||||
// the complete migration history, so later versions reach the profile
|
||||
// through `prepare_profile_db` without inferring anything (#390).
|
||||
Ok(vec![
|
||||
database::CONSOLIDATED_SCHEMA.to_string(),
|
||||
profile_db::history_sql(&crate::migrations()),
|
||||
])
|
||||
}
|
||||
|
||||
/// Bring a profile database up to date and repair legacy values before the
|
||||
/// webview opens it (#390, ADR 0021). Secondary profiles catch up on the
|
||||
/// migrations they missed; every profile gets its text manual-categorization
|
||||
/// flags repaired. Sync on purpose: Tauri runs sync commands on the main
|
||||
/// thread, which serializes two opens of the same profile (React StrictMode
|
||||
/// mounts twice in development).
|
||||
#[tauri::command]
|
||||
pub fn prepare_profile_db(
|
||||
app: tauri::AppHandle,
|
||||
db_filename: String,
|
||||
) -> Result<profile_db::ProfilePreparation, String> {
|
||||
let db_path = profile_db_path(&app, &db_filename)?;
|
||||
profile_db::prepare_at(&db_path, &db_filename, &crate::migrations())
|
||||
}
|
||||
|
||||
// Argon2id parameters for PIN hashing (same as export_import_commands.rs)
|
||||
|
|
@ -225,11 +298,7 @@ fn hex_decode(hex: &str) -> Result<Vec<u8>, String> {
|
|||
/// of destructive migrations (e.g., migration 2 which DELETEs categories/keywords).
|
||||
#[tauri::command]
|
||||
pub fn repair_migrations(app: tauri::AppHandle, db_filename: String) -> Result<bool, String> {
|
||||
let app_dir = app
|
||||
.path()
|
||||
.app_data_dir()
|
||||
.map_err(|e| format!("Cannot get app data dir: {}", e))?;
|
||||
let db_path = app_dir.join(&db_filename);
|
||||
let db_path = profile_db_path(&app, &db_filename)?;
|
||||
|
||||
if !db_path.exists() {
|
||||
return Ok(false);
|
||||
|
|
@ -375,4 +444,91 @@ mod tests {
|
|||
let decoded = hex_decode(&encoded).unwrap();
|
||||
assert_eq!(original, decoded);
|
||||
}
|
||||
|
||||
// -- profile database location (#390) ------------------------------------
|
||||
|
||||
#[test]
|
||||
fn profile_databases_live_where_the_sql_plugin_opens_them() {
|
||||
// tauri-plugin-sql resolves `sqlite:<file>` under app_config_dir().
|
||||
// On Linux (the CI platform) that differs from app_data_dir(), so
|
||||
// going back to the data folder turns this red.
|
||||
let app = tauri::test::mock_app();
|
||||
let path = profile_db_path(app.handle(), "profile_0a1b2c3d.db").unwrap();
|
||||
assert_eq!(path.parent(), Some(app.path().app_config_dir().unwrap().as_path()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_db_path_accepts_the_two_shapes_the_app_uses() {
|
||||
let dir = Path::new("/profiles");
|
||||
assert_eq!(
|
||||
profile_db_path_in(dir, "simpl_resultat.db"),
|
||||
Ok(dir.join("simpl_resultat.db"))
|
||||
);
|
||||
assert_eq!(
|
||||
profile_db_path_in(dir, "profile_0a1b2c3d.db"),
|
||||
Ok(dir.join("profile_0a1b2c3d.db"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_db_path_refuses_anything_else() {
|
||||
let dir = Path::new("/profiles");
|
||||
for name in [
|
||||
"",
|
||||
"/etc/passwd",
|
||||
"../simpl_resultat.db",
|
||||
"profile_.db",
|
||||
"profile_0a1b/../x.db",
|
||||
"profile_0a1b2c3d.sqlite",
|
||||
"profile_0a1b2c3d.db.bak",
|
||||
"PROFILE_0a1b2c3d.db",
|
||||
"profile_xyz.db",
|
||||
"C:\\Users\\x\\profile_0a1b2c3d.db",
|
||||
] {
|
||||
assert_eq!(
|
||||
profile_db_path_in(dir, name),
|
||||
Err("invalid_profile_db_filename".to_string()),
|
||||
"{:?}",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deleting_a_profile_removes_its_files_and_only_its_files() {
|
||||
let dir = profile_db::TestDir::new("delete");
|
||||
let backups = dir.join(profile_db::MIGRATION_BACKUP_DIR);
|
||||
fs::create_dir_all(&backups).unwrap();
|
||||
for name in [
|
||||
"profile_0a1b2c3d.db",
|
||||
// The only side file this app produces: sqlx leaves SQLite's
|
||||
// rollback journal by default, `-wal`/`-shm` come with WAL.
|
||||
"profile_0a1b2c3d.db-journal",
|
||||
"profile_0a1b2c3d.db-wal",
|
||||
"profile_0a1b2c3d.db-shm",
|
||||
"profile_99999999.db",
|
||||
] {
|
||||
fs::write(dir.join(name), b"x").unwrap();
|
||||
}
|
||||
for name in ["profile_0a1b2c3d-before-v7.db", "profile_99999999-before-v17.db"] {
|
||||
fs::write(backups.join(name), b"x").unwrap();
|
||||
}
|
||||
|
||||
delete_profile_files(&dir.join("profile_0a1b2c3d.db"), "profile_0a1b2c3d.db").unwrap();
|
||||
|
||||
let mut left: Vec<String> = fs::read_dir(&dir)
|
||||
.unwrap()
|
||||
.chain(fs::read_dir(&backups).unwrap())
|
||||
.map(|e| e.unwrap().file_name().into_string().unwrap())
|
||||
.collect();
|
||||
left.sort();
|
||||
assert_eq!(
|
||||
left,
|
||||
vec![
|
||||
"migration-backups".to_string(),
|
||||
"profile_99999999-before-v17.db".to_string(),
|
||||
"profile_99999999.db".to_string(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,12 +15,11 @@ CREATE TABLE IF NOT EXISTS import_sources (
|
|||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
-- Full import format (migration v17). These four columns are INERT on the
|
||||
-- production path: this script runs AFTER tauri-plugin-sql has applied every
|
||||
-- migration and only uses CREATE TABLE IF NOT EXISTS, so a brand-new profile
|
||||
-- actually receives them from v17. They are mirrored here to keep this file
|
||||
-- the tested reference definition -- a parity test compares it against the
|
||||
-- v1->v17 chain so the DEFAULT and CHECK of the two cannot drift apart.
|
||||
-- Full import format (migration v17). A secondary profile receives these
|
||||
-- four columns from this script, not from v17: tauri-plugin-sql runs no
|
||||
-- migration on a `profile_<id>.db` (#390, ADR 0021). A parity test compares
|
||||
-- this definition with the v1->v17 chain so the DEFAULT and CHECK of the
|
||||
-- two cannot drift apart.
|
||||
-- `amount_mode` admits 'absolute_indicator' from the start so the third mode
|
||||
-- can ship without another migration. `template_id` is a provenance tag
|
||||
-- only, never re-read as format: the eight format columns above are
|
||||
|
|
@ -374,9 +373,9 @@ INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('balance_starter_pro
|
|||
-- ============================================================================
|
||||
-- Seed v1 — IPC Statistique Canada-aligned, 3 levels, Canada/Québec
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Reset any pre-existing category data (possible when tauri-plugin-sql runs
|
||||
-- the historical v2 seed migration on this fresh DB before this script
|
||||
-- executes). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- Reset any pre-existing category data. Defensive only: tauri-plugin-sql runs
|
||||
-- no migration on a secondary profile's database, so no v2 seed precedes this
|
||||
-- script (#390). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- (1000+ range) so existing references in migrations v3-v7 stay inert.
|
||||
-- ============================================================================
|
||||
DELETE FROM keywords;
|
||||
|
|
|
|||
824
src-tauri/src/database/fixtures/consolidated_v0.10.0.sql
Normal file
824
src-tauri/src/database/fixtures/consolidated_v0.10.0.sql
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
-- Consolidated schema for new profile databases
|
||||
-- This file bakes in the base schema + all migrations (v3-v8) and pre-seeds
|
||||
-- the v1 IPC-aligned category taxonomy so that brand-new profiles immediately
|
||||
-- use the new standard. Existing profiles keep their v2 seed and are only
|
||||
-- tagged via the migration (categories_schema_version = 'v2').
|
||||
-- Used ONLY for initializing new profile databases (not for the default profile).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS imported_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
file_hash TEXT NOT NULL,
|
||||
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
row_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'completed',
|
||||
notes TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
||||
UNIQUE(source_id, filename)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'expense',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_inputable INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
i18n_key TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
normalized_name TEXT NOT NULL,
|
||||
category_id INTEGER,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS keywords (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
keyword TEXT NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
UNIQUE(keyword, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
category_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
source_id INTEGER,
|
||||
file_id INTEGER,
|
||||
original_description TEXT,
|
||||
notes TEXT,
|
||||
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
||||
is_split INTEGER NOT NULL DEFAULT 0,
|
||||
parent_transaction_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
date DATE NOT NULL,
|
||||
is_recurring INTEGER NOT NULL DEFAULT 0,
|
||||
recurrence_rule TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
adjustment_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
description TEXT,
|
||||
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
month INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(category_id, year, month)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(template_id, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_config_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
date_format TEXT NOT NULL DEFAULT 'DD/MM/YYYY',
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
column_mapping TEXT NOT NULL,
|
||||
amount_mode TEXT NOT NULL DEFAULT 'single',
|
||||
sign_convention TEXT NOT NULL DEFAULT 'negative_expense',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
||||
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
||||
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- Balance sheet (Bilan) — Migration v9 mirror for new profiles
|
||||
-- ============================================================================
|
||||
-- 5 tables + 7 indexes + seeded categories. Kept in sync with
|
||||
-- `balance_schema.sql` (the source of truth applied by Migration v9 in lib.rs).
|
||||
-- New profiles created from this consolidated schema get the balance feature
|
||||
-- preinstalled without needing to replay v9 separately.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key TEXT NOT NULL UNIQUE,
|
||||
i18n_key TEXT NOT NULL,
|
||||
kind TEXT NOT NULL CHECK(kind IN ('simple','priced')),
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_seed INTEGER NOT NULL DEFAULT 0,
|
||||
asset_type TEXT CHECK(asset_type IS NULL OR asset_type IN ('stock','crypto')),
|
||||
-- User-facing override for the category label (migration v12). When set,
|
||||
-- the UI shows this verbatim; otherwise it falls back to t(i18n_key).
|
||||
custom_label TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
balance_category_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT,
|
||||
currency TEXT NOT NULL DEFAULT 'CAD' CHECK(currency = 'CAD'),
|
||||
notes TEXT,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
archived_at DATETIME,
|
||||
-- Fiscal envelope / tax shelter (migration v12). NULL = no envelope (e.g.
|
||||
-- a chequing account or crypto wallet). NOT an automobile type.
|
||||
vehicle_type TEXT CHECK(vehicle_type IS NULL OR vehicle_type IN ('unregistered','tfsa','rrsp','rrif','fhsa','resp')),
|
||||
-- Entry mode (migration v15). 'simple' = one denormalized value per
|
||||
-- snapshot line; 'detailed' = a basket of per-security holdings (see
|
||||
-- balance_snapshot_holdings). Accounts under a priced category are backfilled
|
||||
-- to 'detailed' below. `detailed_since` is the authoritative pivot date from
|
||||
-- which detailed entry is expected — NULL until the conversion flow sets it.
|
||||
kind TEXT NOT NULL DEFAULT 'simple' CHECK (kind IN ('simple','detailed')),
|
||||
detailed_since DATE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (balance_category_id) REFERENCES balance_categories(id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_date DATE NOT NULL UNIQUE,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshot_lines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_id INTEGER NOT NULL,
|
||||
account_id INTEGER NOT NULL,
|
||||
quantity REAL,
|
||||
unit_price REAL,
|
||||
value REAL NOT NULL,
|
||||
price_source TEXT,
|
||||
price_fetched_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (snapshot_id) REFERENCES balance_snapshots(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE RESTRICT,
|
||||
UNIQUE(snapshot_id, account_id),
|
||||
CHECK (
|
||||
(quantity IS NULL AND unit_price IS NULL)
|
||||
OR (quantity IS NOT NULL AND unit_price IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_account_transfers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL,
|
||||
transaction_id INTEGER NOT NULL,
|
||||
direction TEXT NOT NULL CHECK(direction IN ('in','out')),
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE RESTRICT,
|
||||
UNIQUE(transaction_id, account_id)
|
||||
);
|
||||
|
||||
-- Détail par titre (Bilan Étape 2, migration v14). Kept in sync with
|
||||
-- `balance_holdings_schema.sql` (the source of truth applied by Migration v14
|
||||
-- in lib.rs). balance_securities is the instrument catalogue (symbol normalized
|
||||
-- upper/trim, COLLATE NOCASE UNIQUE); balance_snapshot_holdings is the per-title
|
||||
-- breakdown of a detailed account's snapshot line.
|
||||
CREATE TABLE IF NOT EXISTS balance_securities (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
symbol TEXT NOT NULL COLLATE NOCASE UNIQUE,
|
||||
name TEXT,
|
||||
currency TEXT NOT NULL DEFAULT 'CAD',
|
||||
asset_type TEXT NOT NULL CHECK (asset_type IN ('stock','crypto')),
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshot_holdings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_line_id INTEGER NOT NULL REFERENCES balance_snapshot_lines(id) ON DELETE CASCADE,
|
||||
security_id INTEGER NOT NULL REFERENCES balance_securities(id) ON DELETE RESTRICT,
|
||||
quantity REAL NOT NULL,
|
||||
unit_price REAL NOT NULL,
|
||||
value REAL NOT NULL,
|
||||
book_cost REAL,
|
||||
price_source TEXT,
|
||||
price_fetched_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE (snapshot_line_id, security_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_category ON balance_accounts(balance_category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_active ON balance_accounts(is_active) WHERE is_active = 1;
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_snapshot ON balance_snapshot_lines(snapshot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_account ON balance_snapshot_lines(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_account ON balance_account_transfers(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_transaction ON balance_account_transfers(transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshots_date ON balance_snapshots(snapshot_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_holdings_line ON balance_snapshot_holdings(snapshot_line_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_holdings_security ON balance_snapshot_holdings(security_id);
|
||||
|
||||
-- Asset classes only (Bilan axe véhicule, Étape 1). The former `tfsa` / `rrsp`
|
||||
-- seeds were fiscal envelopes, not asset classes — they now live on the account
|
||||
-- as `vehicle_type` (see balance_accounts.vehicle_type). New profiles ship with
|
||||
-- exactly 5 asset classes: Liquidités, Fonds/FNB, Actions, Crypto, Autres.
|
||||
INSERT OR IGNORE INTO balance_categories (key, i18n_key, kind, sort_order, is_seed, asset_type) VALUES
|
||||
('cash', 'balance.category.cash', 'simple', 10, 1, NULL),
|
||||
('fund', 'balance.category.fund', 'simple', 40, 1, NULL),
|
||||
('other', 'balance.category.other', 'simple', 50, 1, NULL),
|
||||
('stock', 'balance.category.stock', 'priced', 60, 1, 'stock'),
|
||||
('crypto', 'balance.category.crypto', 'priced', 70, 1, 'crypto');
|
||||
|
||||
-- Starter accounts (Issue #179): 4 plain accounts seeded for new profiles so
|
||||
-- /balance lands non-empty. They are NOT marked as seed (no is_seed column on
|
||||
-- balance_accounts) — once created they are indistinguishable from
|
||||
-- user-created accounts and can be renamed/archived freely. Existing profiles
|
||||
-- get the same 4 proposed via StarterAccountsModal on first /balance visit.
|
||||
--
|
||||
-- Bilan axe véhicule (Étape 1): the CELI / REER starters are no longer linked
|
||||
-- to a `tfsa` / `rrsp` category (those seeds are gone). They now attach to the
|
||||
-- `other` asset class and carry the envelope in `vehicle_type`. Linking them to
|
||||
-- a deleted key would make the subselect return NULL → NOT NULL violation →
|
||||
-- broken new-profile init, so the asset class MUST resolve to `other`.
|
||||
INSERT INTO balance_accounts (balance_category_id, name, currency, is_active, vehicle_type) VALUES
|
||||
((SELECT id FROM balance_categories WHERE key = 'cash'), 'Compte chèque', 'CAD', 1, NULL),
|
||||
((SELECT id FROM balance_categories WHERE key = 'other'), 'CELI', 'CAD', 1, 'tfsa'),
|
||||
((SELECT id FROM balance_categories WHERE key = 'other'), 'REER', 'CAD', 1, 'rrsp'),
|
||||
((SELECT id FROM balance_categories WHERE key = 'other'), 'Compte non-enregistré', 'CAD', 1, NULL);
|
||||
|
||||
-- Détail par titre (migration v15 mirror): accounts under a priced category are
|
||||
-- detailed-entry by default. The 4 starters above all sit under simple asset
|
||||
-- classes (cash / other), so this is currently a no-op — kept at parity with the
|
||||
-- v15 backfill so any future priced starter is stamped correctly.
|
||||
UPDATE balance_accounts SET kind = 'detailed'
|
||||
WHERE balance_category_id IN (SELECT id FROM balance_categories WHERE kind = 'priced');
|
||||
|
||||
-- Default preferences (new profiles ship with the v1 IPC taxonomy)
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|
||||
INSERT OR REPLACE INTO user_preferences (key, value) VALUES ('categories_schema_version', 'v1');
|
||||
-- Suppress StarterAccountsModal on first /balance visit for new profiles
|
||||
-- (Issue #179). The 4 starter accounts are already seeded above, so the
|
||||
-- modal would only show 4 collision rows with no actionable choice. Pre-
|
||||
-- writing the pref skips that briefly-empty UX entirely. Suggestion S1
|
||||
-- from PR #185 review (#187).
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('balance_starter_proposed', '{"shown_at":"seed","accepted":[]}');
|
||||
|
||||
-- ============================================================================
|
||||
-- Seed v1 — IPC Statistique Canada-aligned, 3 levels, Canada/Québec
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Reset any pre-existing category data (possible when tauri-plugin-sql runs
|
||||
-- the historical v2 seed migration on this fresh DB before this script
|
||||
-- executes). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- (1000+ range) so existing references in migrations v3-v7 stay inert.
|
||||
-- ============================================================================
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- LEVEL 1 — Roots (9 IPC components + Revenus + Transferts)
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1000, 'Revenus', NULL, 'income', '#16a34a', 0, 1, 'categoriesSeed.revenus.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1100, 'Alimentation', NULL, 'expense', '#ea580c', 0, 2, 'categoriesSeed.alimentation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1200, 'Logement', NULL, 'expense', '#dc2626', 0, 3, 'categoriesSeed.logement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1300, 'Ménage & ameublement', NULL, 'expense', '#ca8a04', 0, 4, 'categoriesSeed.menage.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1400, 'Vêtements & chaussures', NULL, 'expense', '#d946ef', 0, 5, 'categoriesSeed.vetements.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1500, 'Transport', NULL, 'expense', '#2563eb', 0, 6, 'categoriesSeed.transport.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1600, 'Santé & soins personnels', NULL, 'expense', '#f43f5e', 0, 7, 'categoriesSeed.sante.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1700, 'Loisirs, formation & lecture', NULL, 'expense', '#8b5cf6', 0, 8, 'categoriesSeed.loisirs.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1800, 'Boissons, tabac & cannabis', NULL, 'expense', '#7c3aed', 0, 9, 'categoriesSeed.consommation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1900, 'Finances & obligations', NULL, 'expense', '#6b7280', 0, 10, 'categoriesSeed.finances.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1950, 'Transferts & placements', NULL, 'transfer', '#0ea5e9', 0, 11, 'categoriesSeed.transferts.root');
|
||||
|
||||
-- 1000 — Revenus
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1010, 'Emploi', 1000, 'income', '#22c55e', 0, 1, 'categoriesSeed.revenus.emploi.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1011, 'Paie régulière', 1010, 'income', '#22c55e', 1, 1, 'categoriesSeed.revenus.emploi.paie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1012, 'Primes & bonus', 1010, 'income', '#4ade80', 1, 2, 'categoriesSeed.revenus.emploi.primes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1013, 'Travail autonome', 1010, 'income', '#86efac', 1, 3, 'categoriesSeed.revenus.emploi.autonome');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1020, 'Gouvernemental', 1000, 'income', '#16a34a', 0, 2, 'categoriesSeed.revenus.gouvernemental.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1021, 'Remboursement impôt', 1020, 'income', '#16a34a', 1, 1, 'categoriesSeed.revenus.gouvernemental.remboursementImpot');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1022, 'Allocations familiales', 1020, 'income', '#15803d', 1, 2, 'categoriesSeed.revenus.gouvernemental.allocations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1023, 'Crédits TPS/TVQ', 1020, 'income', '#166534', 1, 3, 'categoriesSeed.revenus.gouvernemental.credits');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1024, 'Assurance-emploi / RQAP', 1020, 'income', '#14532d', 1, 4, 'categoriesSeed.revenus.gouvernemental.assuranceEmploi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1030, 'Revenus de placement', 1000, 'income', '#10b981', 0, 3, 'categoriesSeed.revenus.placement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1031, 'Intérêts & dividendes', 1030, 'income', '#10b981', 1, 1, 'categoriesSeed.revenus.placement.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1032, 'Gains en capital', 1030, 'income', '#059669', 1, 2, 'categoriesSeed.revenus.placement.capital');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1033, 'Revenus locatifs', 1030, 'income', '#047857', 1, 3, 'categoriesSeed.revenus.placement.locatifs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1090, 'Autres revenus', 1000, 'income', '#84cc16', 1, 9, 'categoriesSeed.revenus.autres');
|
||||
|
||||
-- 1100 — Alimentation
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1110, 'Épicerie & marché', 1100, 'expense', '#ea580c', 0, 1, 'categoriesSeed.alimentation.epicerie.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1111, 'Épicerie régulière', 1110, 'expense', '#ea580c', 1, 1, 'categoriesSeed.alimentation.epicerie.reguliere');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1112, 'Boucherie & poissonnerie', 1110, 'expense', '#c2410c', 1, 2, 'categoriesSeed.alimentation.epicerie.boucherie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1113, 'Boulangerie & pâtisserie', 1110, 'expense', '#9a3412', 1, 3, 'categoriesSeed.alimentation.epicerie.boulangerie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1114, 'Dépanneur', 1110, 'expense', '#7c2d12', 1, 4, 'categoriesSeed.alimentation.epicerie.depanneur');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1115, 'Marché & produits spécialisés', 1110, 'expense', '#fb923c', 1, 5, 'categoriesSeed.alimentation.epicerie.marche');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1120, 'Restauration', 1100, 'expense', '#f97316', 0, 2, 'categoriesSeed.alimentation.restauration.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1121, 'Restaurant', 1120, 'expense', '#f97316', 1, 1, 'categoriesSeed.alimentation.restauration.restaurant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1122, 'Café & boulangerie rapide', 1120, 'expense', '#fb923c', 1, 2, 'categoriesSeed.alimentation.restauration.cafe');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1123, 'Restauration rapide', 1120, 'expense', '#fdba74', 1, 3, 'categoriesSeed.alimentation.restauration.fastfood');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1124, 'Livraison à domicile', 1120, 'expense', '#fed7aa', 1, 4, 'categoriesSeed.alimentation.restauration.livraison');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1125, 'Cantine & cafétéria', 1120, 'expense', '#ffedd5', 1, 5, 'categoriesSeed.alimentation.restauration.cantine');
|
||||
|
||||
-- 1200 — Logement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1210, 'Habitation principale', 1200, 'expense', '#dc2626', 0, 1, 'categoriesSeed.logement.habitation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1211, 'Loyer', 1210, 'expense', '#dc2626', 1, 1, 'categoriesSeed.logement.habitation.loyer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1212, 'Hypothèque', 1210, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.logement.habitation.hypotheque');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1213, 'Taxes municipales & scolaires', 1210, 'expense', '#991b1b', 1, 3, 'categoriesSeed.logement.habitation.taxes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1214, 'Charges de copropriété', 1210, 'expense', '#7f1d1d', 1, 4, 'categoriesSeed.logement.habitation.copropriete');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1220, 'Services publics', 1200, 'expense', '#ef4444', 0, 2, 'categoriesSeed.logement.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1221, 'Électricité', 1220, 'expense', '#ef4444', 1, 1, 'categoriesSeed.logement.services.electricite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1222, 'Gaz naturel', 1220, 'expense', '#f87171', 1, 2, 'categoriesSeed.logement.services.gaz');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1223, 'Chauffage (mazout, propane)', 1220, 'expense', '#fca5a5', 1, 3, 'categoriesSeed.logement.services.chauffage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1224, 'Eau & égouts', 1220, 'expense', '#fecaca', 1, 4, 'categoriesSeed.logement.services.eau');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1230, 'Communications', 1200, 'expense', '#6366f1', 0, 3, 'categoriesSeed.logement.communications.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1231, 'Internet résidentiel', 1230, 'expense', '#6366f1', 1, 1, 'categoriesSeed.logement.communications.internet');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1232, 'Téléphonie mobile', 1230, 'expense', '#818cf8', 1, 2, 'categoriesSeed.logement.communications.mobile');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1233, 'Téléphonie résidentielle', 1230, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.logement.communications.residentielle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1234, 'Câblodistribution & streaming TV', 1230, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.logement.communications.streamingTv');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1240, 'Entretien & réparations', 1200, 'expense', '#e11d48', 0, 4, 'categoriesSeed.logement.entretien.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1241, 'Entretien général', 1240, 'expense', '#e11d48', 1, 1, 'categoriesSeed.logement.entretien.general');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1242, 'Rénovations', 1240, 'expense', '#be123c', 1, 2, 'categoriesSeed.logement.entretien.renovations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1243, 'Matériaux & outils', 1240, 'expense', '#9f1239', 1, 3, 'categoriesSeed.logement.entretien.materiaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1244, 'Aménagement paysager', 1240, 'expense', '#881337', 1, 4, 'categoriesSeed.logement.entretien.paysager');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1250, 'Assurance habitation', 1200, 'expense', '#14b8a6', 1, 5, 'categoriesSeed.logement.assurance');
|
||||
|
||||
-- 1300 — Ménage & ameublement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1310, 'Ameublement', 1300, 'expense', '#ca8a04', 0, 1, 'categoriesSeed.menage.ameublement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1311, 'Meubles', 1310, 'expense', '#ca8a04', 1, 1, 'categoriesSeed.menage.ameublement.meubles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1312, 'Électroménagers', 1310, 'expense', '#a16207', 1, 2, 'categoriesSeed.menage.ameublement.electromenagers');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1313, 'Décoration', 1310, 'expense', '#854d0e', 1, 3, 'categoriesSeed.menage.ameublement.decoration');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1320, 'Fournitures ménagères', 1300, 'expense', '#eab308', 0, 2, 'categoriesSeed.menage.fournitures.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1321, 'Produits d''entretien', 1320, 'expense', '#eab308', 1, 1, 'categoriesSeed.menage.fournitures.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1322, 'Literie & linge de maison', 1320, 'expense', '#facc15', 1, 2, 'categoriesSeed.menage.fournitures.literie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1323, 'Vaisselle & ustensiles', 1320, 'expense', '#fde047', 1, 3, 'categoriesSeed.menage.fournitures.vaisselle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1330, 'Services domestiques', 1300, 'expense', '#fbbf24', 0, 3, 'categoriesSeed.menage.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1331, 'Ménage & nettoyage', 1330, 'expense', '#fbbf24', 1, 1, 'categoriesSeed.menage.services.nettoyage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1332, 'Buanderie & pressing', 1330, 'expense', '#fcd34d', 1, 2, 'categoriesSeed.menage.services.buanderie');
|
||||
|
||||
-- 1400 — Vêtements & chaussures
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1410, 'Vêtements adultes', 1400, 'expense', '#d946ef', 1, 1, 'categoriesSeed.vetements.adultes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1420, 'Vêtements enfants', 1400, 'expense', '#c026d3', 1, 2, 'categoriesSeed.vetements.enfants');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1430, 'Chaussures', 1400, 'expense', '#a21caf', 1, 3, 'categoriesSeed.vetements.chaussures');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1440, 'Accessoires & bijoux', 1400, 'expense', '#86198f', 1, 4, 'categoriesSeed.vetements.accessoires');
|
||||
|
||||
-- 1500 — Transport
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1510, 'Véhicule personnel', 1500, 'expense', '#2563eb', 0, 1, 'categoriesSeed.transport.vehicule.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1511, 'Achat / location véhicule', 1510, 'expense', '#2563eb', 1, 1, 'categoriesSeed.transport.vehicule.achat');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1512, 'Essence', 1510, 'expense', '#1d4ed8', 1, 2, 'categoriesSeed.transport.vehicule.essence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1513, 'Entretien & réparations auto', 1510, 'expense', '#1e40af', 1, 3, 'categoriesSeed.transport.vehicule.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1514, 'Immatriculation & permis', 1510, 'expense', '#1e3a8a', 1, 4, 'categoriesSeed.transport.vehicule.immatriculation');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1515, 'Stationnement & péages', 1510, 'expense', '#3b82f6', 1, 5, 'categoriesSeed.transport.vehicule.stationnement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1516, 'Assurance auto', 1510, 'expense', '#60a5fa', 1, 6, 'categoriesSeed.transport.vehicule.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1520, 'Transport public', 1500, 'expense', '#0ea5e9', 0, 2, 'categoriesSeed.transport.public.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1521, 'Autobus & métro', 1520, 'expense', '#0ea5e9', 1, 1, 'categoriesSeed.transport.public.autobus');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1522, 'Train de banlieue', 1520, 'expense', '#0284c7', 1, 2, 'categoriesSeed.transport.public.train');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1523, 'Taxi & covoiturage', 1520, 'expense', '#0369a1', 1, 3, 'categoriesSeed.transport.public.taxi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1530, 'Voyages longue distance', 1500, 'expense', '#38bdf8', 0, 3, 'categoriesSeed.transport.voyages.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1531, 'Avion', 1530, 'expense', '#38bdf8', 1, 1, 'categoriesSeed.transport.voyages.avion');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1532, 'Train & autocar', 1530, 'expense', '#7dd3fc', 1, 2, 'categoriesSeed.transport.voyages.trainAutocar');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1533, 'Hébergement', 1530, 'expense', '#bae6fd', 1, 3, 'categoriesSeed.transport.voyages.hebergement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1534, 'Location véhicule voyage', 1530, 'expense', '#e0f2fe', 1, 4, 'categoriesSeed.transport.voyages.location');
|
||||
|
||||
-- 1600 — Santé & soins personnels
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1610, 'Soins médicaux', 1600, 'expense', '#f43f5e', 0, 1, 'categoriesSeed.sante.medicaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1611, 'Pharmacie', 1610, 'expense', '#f43f5e', 1, 1, 'categoriesSeed.sante.medicaux.pharmacie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1612, 'Consultations médicales', 1610, 'expense', '#e11d48', 1, 2, 'categoriesSeed.sante.medicaux.consultations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1613, 'Dentiste & orthodontiste', 1610, 'expense', '#be123c', 1, 3, 'categoriesSeed.sante.medicaux.dentiste');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1614, 'Optométrie & lunettes', 1610, 'expense', '#9f1239', 1, 4, 'categoriesSeed.sante.medicaux.optometrie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1615, 'Thérapies (physio, psycho, etc.)', 1610, 'expense', '#881337', 1, 5, 'categoriesSeed.sante.medicaux.therapies');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1616, 'Assurance santé complémentaire', 1610, 'expense', '#fb7185', 1, 6, 'categoriesSeed.sante.medicaux.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1620, 'Soins personnels', 1600, 'expense', '#fb7185', 0, 2, 'categoriesSeed.sante.personnels.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1621, 'Coiffure & esthétique', 1620, 'expense', '#fb7185', 1, 1, 'categoriesSeed.sante.personnels.coiffure');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1622, 'Produits de soins corporels', 1620, 'expense', '#fda4af', 1, 2, 'categoriesSeed.sante.personnels.soins');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1630, 'Assurance vie & invalidité', 1600, 'expense', '#14b8a6', 1, 3, 'categoriesSeed.sante.assuranceVie');
|
||||
|
||||
-- 1700 — Loisirs, formation & lecture
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1710, 'Divertissement', 1700, 'expense', '#8b5cf6', 0, 1, 'categoriesSeed.loisirs.divertissement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1711, 'Cinéma & spectacles', 1710, 'expense', '#8b5cf6', 1, 1, 'categoriesSeed.loisirs.divertissement.cinema');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1712, 'Jeux vidéo & consoles', 1710, 'expense', '#a78bfa', 1, 2, 'categoriesSeed.loisirs.divertissement.jeux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1713, 'Streaming vidéo', 1710, 'expense', '#c4b5fd', 1, 3, 'categoriesSeed.loisirs.divertissement.streamingVideo');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1714, 'Streaming musique & audio', 1710, 'expense', '#ddd6fe', 1, 4, 'categoriesSeed.loisirs.divertissement.streamingMusique');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1715, 'Jouets & passe-temps', 1710, 'expense', '#ede9fe', 1, 5, 'categoriesSeed.loisirs.divertissement.jouets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1720, 'Sports & plein air', 1700, 'expense', '#22c55e', 0, 2, 'categoriesSeed.loisirs.sports.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1721, 'Abonnements sportifs', 1720, 'expense', '#22c55e', 1, 1, 'categoriesSeed.loisirs.sports.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1722, 'Équipement sportif', 1720, 'expense', '#4ade80', 1, 2, 'categoriesSeed.loisirs.sports.equipement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1723, 'Parcs & activités plein air', 1720, 'expense', '#86efac', 1, 3, 'categoriesSeed.loisirs.sports.parcs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1730, 'Formation & éducation', 1700, 'expense', '#6366f1', 0, 3, 'categoriesSeed.loisirs.formation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1731, 'Scolarité (frais)', 1730, 'expense', '#6366f1', 1, 1, 'categoriesSeed.loisirs.formation.scolarite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1732, 'Matériel scolaire', 1730, 'expense', '#818cf8', 1, 2, 'categoriesSeed.loisirs.formation.materiel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1733, 'Cours & certifications', 1730, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.loisirs.formation.cours');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1734, 'Abonnements professionnels', 1730, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.loisirs.formation.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1740, 'Lecture & médias', 1700, 'expense', '#ec4899', 0, 4, 'categoriesSeed.loisirs.lecture.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1741, 'Livres', 1740, 'expense', '#ec4899', 1, 1, 'categoriesSeed.loisirs.lecture.livres');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1742, 'Journaux & magazines', 1740, 'expense', '#f472b6', 1, 2, 'categoriesSeed.loisirs.lecture.journaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1750, 'Animaux de compagnie', 1700, 'expense', '#a855f7', 0, 5, 'categoriesSeed.loisirs.animaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1751, 'Nourriture & accessoires animaux', 1750, 'expense', '#a855f7', 1, 1, 'categoriesSeed.loisirs.animaux.nourriture');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1752, 'Vétérinaire', 1750, 'expense', '#c084fc', 1, 2, 'categoriesSeed.loisirs.animaux.veterinaire');
|
||||
|
||||
-- 1800 — Boissons, tabac & cannabis
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1810, 'Alcool (SAQ, microbrasseries)', 1800, 'expense', '#7c3aed', 1, 1, 'categoriesSeed.consommation.alcool');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1820, 'Cannabis (SQDC)', 1800, 'expense', '#6d28d9', 1, 2, 'categoriesSeed.consommation.cannabis');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1830, 'Tabac', 1800, 'expense', '#5b21b6', 1, 3, 'categoriesSeed.consommation.tabac');
|
||||
|
||||
-- 1900 — Finances & obligations
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1910, 'Frais bancaires', 1900, 'expense', '#6b7280', 0, 1, 'categoriesSeed.finances.fraisBancaires.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1911, 'Frais de compte', 1910, 'expense', '#6b7280', 1, 1, 'categoriesSeed.finances.fraisBancaires.compte');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1912, 'Intérêts & frais de crédit', 1910, 'expense', '#9ca3af', 1, 2, 'categoriesSeed.finances.fraisBancaires.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1913, 'Frais de change', 1910, 'expense', '#d1d5db', 1, 3, 'categoriesSeed.finances.fraisBancaires.change');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1920, 'Impôts & taxes', 1900, 'expense', '#dc2626', 0, 2, 'categoriesSeed.finances.impots.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1921, 'Impôt fédéral', 1920, 'expense', '#dc2626', 1, 1, 'categoriesSeed.finances.impots.federal');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1922, 'Impôt provincial', 1920, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.finances.impots.provincial');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1923, 'Acomptes provisionnels', 1920, 'expense', '#991b1b', 1, 3, 'categoriesSeed.finances.impots.acomptes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1930, 'Dons & cotisations', 1900, 'expense', '#ec4899', 0, 3, 'categoriesSeed.finances.dons.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1931, 'Dons de charité', 1930, 'expense', '#ec4899', 1, 1, 'categoriesSeed.finances.dons.charite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1932, 'Cotisations professionnelles', 1930, 'expense', '#f472b6', 1, 2, 'categoriesSeed.finances.dons.professionnelles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1933, 'Cotisations syndicales', 1930, 'expense', '#f9a8d4', 1, 3, 'categoriesSeed.finances.dons.syndicales');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1940, 'Cadeaux', 1900, 'expense', '#f43f5e', 1, 4, 'categoriesSeed.finances.cadeaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1945, 'Retrait cash', 1900, 'expense', '#57534e', 1, 5, 'categoriesSeed.finances.cash');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1946, 'Achats divers non catégorisés', 1900, 'expense', '#78716c', 1, 6, 'categoriesSeed.finances.divers');
|
||||
|
||||
-- 1950 — Transferts & placements
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1960, 'Épargne & placements', 1950, 'transfer', '#0ea5e9', 0, 1, 'categoriesSeed.transferts.epargne.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1961, 'REER / RRSP', 1960, 'transfer', '#0ea5e9', 1, 1, 'categoriesSeed.transferts.epargne.reer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1962, 'CELI / TFSA', 1960, 'transfer', '#0284c7', 1, 2, 'categoriesSeed.transferts.epargne.celi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1963, 'REEE / RESP', 1960, 'transfer', '#0369a1', 1, 3, 'categoriesSeed.transferts.epargne.reee');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1964, 'Compte non-enregistré', 1960, 'transfer', '#075985', 1, 4, 'categoriesSeed.transferts.epargne.nonEnregistre');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1965, 'Fonds d''urgence', 1960, 'transfer', '#0c4a6e', 1, 5, 'categoriesSeed.transferts.epargne.urgence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1970, 'Remboursement de dette', 1950, 'transfer', '#7c3aed', 0, 2, 'categoriesSeed.transferts.dette.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1971, 'Paiement carte crédit', 1970, 'transfer', '#7c3aed', 1, 1, 'categoriesSeed.transferts.dette.carteCredit');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1972, 'Remboursement prêt étudiant', 1970, 'transfer', '#8b5cf6', 1, 2, 'categoriesSeed.transferts.dette.etudiant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1973, 'Remboursement prêt perso', 1970, 'transfer', '#a78bfa', 1, 3, 'categoriesSeed.transferts.dette.personnel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1980, 'Transferts internes', 1950, 'transfer', '#64748b', 1, 3, 'categoriesSeed.transferts.internes');
|
||||
|
||||
-- ============================================================================
|
||||
-- Keywords — Canadian suppliers (150+ entries)
|
||||
-- ============================================================================
|
||||
|
||||
-- Alimentation > Épicerie régulière (1111)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('METRO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IGA', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MAXI', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUPER C', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LOBLAWS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROVIGO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ADONIS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WHOLE FOODS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AVRIL', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RACHELLE-BERY', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COSTCO', 1111, 50);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WALMART', 1111, 50);
|
||||
|
||||
-- Épicerie > Boucherie (1112)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCHERIE', 1112, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('POISSONNERIE', 1112, 0);
|
||||
|
||||
-- Épicerie > Boulangerie (1113)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOULANGERIE', 1113, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PATISSERIE', 1113, 0);
|
||||
|
||||
-- Épicerie > Dépanneur (1114)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPANNEUR', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('7-ELEVEN', 1114, 0);
|
||||
|
||||
-- Restauration > Restaurant (1121)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RESTAURANT', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRASSERIE', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BISTRO', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUSHI', 1121, 0);
|
||||
|
||||
-- Restauration > Café (1122)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STARBUCKS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIM HORTONS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SECOND CUP', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VAN HOUTTE', 1122, 0);
|
||||
|
||||
-- Restauration > Fast food (1123)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MCDONALD', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUBWAY', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('A&W', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BURGER KING', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KFC', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOMINOS', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PIZZA HUT', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELLE PROVINCE', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ST-HUBERT', 1123, 0);
|
||||
|
||||
-- Restauration > Livraison (1124)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DD/DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER EATS', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SKIPTHEDISHES', 1124, 0);
|
||||
|
||||
-- Logement > Hypothèque (1212)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MTG/HYP', 1212, 0);
|
||||
|
||||
-- Logement > Taxes municipales (1213)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('M-ST-HILAIRE TX', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXES MUNICIPALES', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CSS PATRIOT', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXE SCOLAIRE', 1213, 0);
|
||||
|
||||
-- Électricité (1221)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO-QUEBEC', 1221, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO QUEBEC', 1221, 0);
|
||||
|
||||
-- Gaz (1222)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ENERGIR', 1222, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAZ METRO', 1222, 0);
|
||||
|
||||
-- Internet (1231)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIDEOTRON', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL INTERNET', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORICOM', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COGECO', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EBOX', 1231, 0);
|
||||
|
||||
-- Mobile (1232)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIZZ', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KOODO', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PUBLIC MOBILE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIRGIN', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL MOBILITE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TELUS MOBILE', 1232, 0);
|
||||
|
||||
-- Entretien maison (1241)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IKEA', 1241, 0);
|
||||
|
||||
-- Matériaux & outils (1243)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANADIAN TIRE', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANAC', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RONA', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HOME DEPOT', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BMR', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRINCESS AUTO', 1243, 0);
|
||||
|
||||
-- Assurance habitation (1250)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELAIR', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRYSM', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INTACT ASSURANCE', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DESJARDINS ASSURANCE', 1250, 0);
|
||||
|
||||
-- Meubles (1311)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TANGUAY', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEON', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STRUCTUBE', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRICK', 1311, 0);
|
||||
|
||||
-- Électroménagers (1312)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BEST BUY', 1312, 0);
|
||||
|
||||
-- Décoration (1313)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCLAIR', 1313, 0);
|
||||
|
||||
-- Vêtements (1410)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIQLO', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WINNERS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SIMONS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARKS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('H&M', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OLD NAVY', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAP', 1410, 0);
|
||||
|
||||
-- Transport — Essence (1512)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SHELL', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ESSO', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ULTRAMAR', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO-CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CREVIER', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HARNOIS', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD ESSENCE', 1512, 10);
|
||||
|
||||
-- Permis / SAAQ (1514)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAAQ', 1514, 0);
|
||||
|
||||
-- Transport public — autobus/métro (1521)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STM', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RTC', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STL', 1521, 0);
|
||||
|
||||
-- Train de banlieue (1522)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE MONT-SAINT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE SAINT-HUBERT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE CENTRALE', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EXO', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REM', 1522, 0);
|
||||
|
||||
-- Taxi / Uber (1523)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LYFT', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXI', 1523, 0);
|
||||
|
||||
-- Avion (1531)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR CANADA', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WESTJET', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR TRANSAT', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PORTER', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AEROPORTS DE MONTREAL', 1531, 0);
|
||||
|
||||
-- Hébergement (1533)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIRBNB', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HILTON', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARRIOTT', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOOKING.COM', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NORWEGIAN CRUISE', 1533, 0);
|
||||
|
||||
-- Pharmacie (1611)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('JEAN COUTU', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FAMILIPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHARMAPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROXIM', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIPRIX', 1611, 0);
|
||||
|
||||
-- Thérapies (1615)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHYSIOACTIF', 1615, 0);
|
||||
|
||||
-- Cinéma & spectacles (1711)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEPLEX', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEMA DU PARC', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TICKETMASTER', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CLUB SODA', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEPOINTDEVENTE', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EVENBRITE', 1711, 0);
|
||||
|
||||
-- Jeux vidéo (1712)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STEAMGAMES', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PLAYSTATION', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NINTENDO', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('XBOX', 1712, 0);
|
||||
|
||||
-- Streaming vidéo (1713)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NETFLIX', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRIMEVIDEO', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DISNEY PLUS', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRAVE', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE TV', 1713, 0);
|
||||
|
||||
-- Streaming musique (1714)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPOTIFY', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('YOUTUBE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIDAL', 1714, 0);
|
||||
|
||||
-- Jouets & hobbies (1715)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEGO', 1715, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TOYS R US', 1715, 0);
|
||||
|
||||
-- Équipement sportif (1722)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MOUNTAIN EQUIPMENT', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LA CORDEE', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DECATHLON', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPORTS EXPERTS', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ATMOSPHERE', 1722, 0);
|
||||
|
||||
-- Parcs & activités (1723)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SEPAQ', 1723, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BLOC SHOP', 1723, 0);
|
||||
|
||||
-- Lecture (1741)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RENAUD-BRAY', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INDIGO', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARCHAMBAULT', 1741, 0);
|
||||
|
||||
-- Animaux — nourriture (1751)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MONDOU', 1751, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PET SMART', 1751, 0);
|
||||
|
||||
-- Alcool (1810)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAQ', 1810, 0);
|
||||
|
||||
-- Cannabis (1820)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SQDC', 1820, 0);
|
||||
|
||||
-- Frais bancaires (1911)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROGRAMME PERFORMANCE', 1911, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FRAIS MENSUELS', 1911, 0);
|
||||
|
||||
-- Impôts (1921, 1922)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GOUV. QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REVENU QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARC IMPOT', 1921, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRA TAX', 1921, 0);
|
||||
|
||||
-- Dons de charité (1931)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OXFAM', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CENTRAIDE', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FPA', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CROIX-ROUGE', 1931, 0);
|
||||
|
||||
-- Cotisations professionnelles (1932)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORDRE DES COMPTABL', 1932, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CPA CANADA', 1932, 0);
|
||||
|
||||
-- Cadeaux (1940)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DANS UN JARDIN', 1940, 0);
|
||||
|
||||
-- Divers (1946) — catch-all marketplace
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMAZON', 1946, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMZN', 1946, 0);
|
||||
|
||||
-- Placements (1964)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WS INVESTMENTS', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WEALTHSIMPLE', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PEAK INVESTMENT', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DYNAMIC FUND', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIDELITY', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AGF', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('QUESTRADE', 1964, 0);
|
||||
|
||||
-- Paie (1011)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAY/PAY', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPOT PAIE', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAYROLL', 1011, 0);
|
||||
184
src-tauri/src/database/fixtures/consolidated_v0.3.0.sql
Normal file
184
src-tauri/src/database/fixtures/consolidated_v0.3.0.sql
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
-- Consolidated schema for new profile databases
|
||||
-- This file bakes in the base schema + all migrations (v3-v6)
|
||||
-- Used ONLY for initializing new profile databases (not for the default profile)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS imported_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
file_hash TEXT NOT NULL,
|
||||
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
row_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'completed',
|
||||
notes TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
||||
UNIQUE(source_id, filename)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'expense',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_inputable INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
normalized_name TEXT NOT NULL,
|
||||
category_id INTEGER,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS keywords (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
keyword TEXT NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
UNIQUE(keyword, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
category_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
source_id INTEGER,
|
||||
file_id INTEGER,
|
||||
original_description TEXT,
|
||||
notes TEXT,
|
||||
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
||||
is_split INTEGER NOT NULL DEFAULT 0,
|
||||
parent_transaction_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
date DATE NOT NULL,
|
||||
is_recurring INTEGER NOT NULL DEFAULT 0,
|
||||
recurrence_rule TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
adjustment_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
description TEXT,
|
||||
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
month INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(category_id, year, month)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(template_id, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_config_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
date_format TEXT NOT NULL DEFAULT 'DD/MM/YYYY',
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
column_mapping TEXT NOT NULL,
|
||||
amount_mode TEXT NOT NULL DEFAULT 'single',
|
||||
sign_convention TEXT NOT NULL DEFAULT 'negative_expense',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
||||
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
||||
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
||||
|
||||
-- Default preferences
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|
||||
657
src-tauri/src/database/fixtures/consolidated_v0.8.4.sql
Normal file
657
src-tauri/src/database/fixtures/consolidated_v0.8.4.sql
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
-- Consolidated schema for new profile databases
|
||||
-- This file bakes in the base schema + all migrations (v3-v8) and pre-seeds
|
||||
-- the v1 IPC-aligned category taxonomy so that brand-new profiles immediately
|
||||
-- use the new standard. Existing profiles keep their v2 seed and are only
|
||||
-- tagged via the migration (categories_schema_version = 'v2').
|
||||
-- Used ONLY for initializing new profile databases (not for the default profile).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS imported_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
file_hash TEXT NOT NULL,
|
||||
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
row_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'completed',
|
||||
notes TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
||||
UNIQUE(source_id, filename)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'expense',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_inputable INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
i18n_key TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
normalized_name TEXT NOT NULL,
|
||||
category_id INTEGER,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS keywords (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
keyword TEXT NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
UNIQUE(keyword, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
category_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
source_id INTEGER,
|
||||
file_id INTEGER,
|
||||
original_description TEXT,
|
||||
notes TEXT,
|
||||
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
||||
is_split INTEGER NOT NULL DEFAULT 0,
|
||||
parent_transaction_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
date DATE NOT NULL,
|
||||
is_recurring INTEGER NOT NULL DEFAULT 0,
|
||||
recurrence_rule TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
adjustment_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
description TEXT,
|
||||
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
month INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(category_id, year, month)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(template_id, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_config_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
date_format TEXT NOT NULL DEFAULT 'DD/MM/YYYY',
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
column_mapping TEXT NOT NULL,
|
||||
amount_mode TEXT NOT NULL DEFAULT 'single',
|
||||
sign_convention TEXT NOT NULL DEFAULT 'negative_expense',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
||||
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
||||
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
||||
|
||||
-- Default preferences (new profiles ship with the v1 IPC taxonomy)
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|
||||
INSERT OR REPLACE INTO user_preferences (key, value) VALUES ('categories_schema_version', 'v1');
|
||||
|
||||
-- ============================================================================
|
||||
-- Seed v1 — IPC Statistique Canada-aligned, 3 levels, Canada/Québec
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Reset any pre-existing category data (possible when tauri-plugin-sql runs
|
||||
-- the historical v2 seed migration on this fresh DB before this script
|
||||
-- executes). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- (1000+ range) so existing references in migrations v3-v7 stay inert.
|
||||
-- ============================================================================
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- LEVEL 1 — Roots (9 IPC components + Revenus + Transferts)
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1000, 'Revenus', NULL, 'income', '#16a34a', 0, 1, 'categoriesSeed.revenus.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1100, 'Alimentation', NULL, 'expense', '#ea580c', 0, 2, 'categoriesSeed.alimentation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1200, 'Logement', NULL, 'expense', '#dc2626', 0, 3, 'categoriesSeed.logement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1300, 'Ménage & ameublement', NULL, 'expense', '#ca8a04', 0, 4, 'categoriesSeed.menage.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1400, 'Vêtements & chaussures', NULL, 'expense', '#d946ef', 0, 5, 'categoriesSeed.vetements.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1500, 'Transport', NULL, 'expense', '#2563eb', 0, 6, 'categoriesSeed.transport.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1600, 'Santé & soins personnels', NULL, 'expense', '#f43f5e', 0, 7, 'categoriesSeed.sante.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1700, 'Loisirs, formation & lecture', NULL, 'expense', '#8b5cf6', 0, 8, 'categoriesSeed.loisirs.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1800, 'Boissons, tabac & cannabis', NULL, 'expense', '#7c3aed', 0, 9, 'categoriesSeed.consommation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1900, 'Finances & obligations', NULL, 'expense', '#6b7280', 0, 10, 'categoriesSeed.finances.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1950, 'Transferts & placements', NULL, 'transfer', '#0ea5e9', 0, 11, 'categoriesSeed.transferts.root');
|
||||
|
||||
-- 1000 — Revenus
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1010, 'Emploi', 1000, 'income', '#22c55e', 0, 1, 'categoriesSeed.revenus.emploi.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1011, 'Paie régulière', 1010, 'income', '#22c55e', 1, 1, 'categoriesSeed.revenus.emploi.paie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1012, 'Primes & bonus', 1010, 'income', '#4ade80', 1, 2, 'categoriesSeed.revenus.emploi.primes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1013, 'Travail autonome', 1010, 'income', '#86efac', 1, 3, 'categoriesSeed.revenus.emploi.autonome');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1020, 'Gouvernemental', 1000, 'income', '#16a34a', 0, 2, 'categoriesSeed.revenus.gouvernemental.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1021, 'Remboursement impôt', 1020, 'income', '#16a34a', 1, 1, 'categoriesSeed.revenus.gouvernemental.remboursementImpot');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1022, 'Allocations familiales', 1020, 'income', '#15803d', 1, 2, 'categoriesSeed.revenus.gouvernemental.allocations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1023, 'Crédits TPS/TVQ', 1020, 'income', '#166534', 1, 3, 'categoriesSeed.revenus.gouvernemental.credits');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1024, 'Assurance-emploi / RQAP', 1020, 'income', '#14532d', 1, 4, 'categoriesSeed.revenus.gouvernemental.assuranceEmploi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1030, 'Revenus de placement', 1000, 'income', '#10b981', 0, 3, 'categoriesSeed.revenus.placement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1031, 'Intérêts & dividendes', 1030, 'income', '#10b981', 1, 1, 'categoriesSeed.revenus.placement.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1032, 'Gains en capital', 1030, 'income', '#059669', 1, 2, 'categoriesSeed.revenus.placement.capital');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1033, 'Revenus locatifs', 1030, 'income', '#047857', 1, 3, 'categoriesSeed.revenus.placement.locatifs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1090, 'Autres revenus', 1000, 'income', '#84cc16', 1, 9, 'categoriesSeed.revenus.autres');
|
||||
|
||||
-- 1100 — Alimentation
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1110, 'Épicerie & marché', 1100, 'expense', '#ea580c', 0, 1, 'categoriesSeed.alimentation.epicerie.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1111, 'Épicerie régulière', 1110, 'expense', '#ea580c', 1, 1, 'categoriesSeed.alimentation.epicerie.reguliere');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1112, 'Boucherie & poissonnerie', 1110, 'expense', '#c2410c', 1, 2, 'categoriesSeed.alimentation.epicerie.boucherie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1113, 'Boulangerie & pâtisserie', 1110, 'expense', '#9a3412', 1, 3, 'categoriesSeed.alimentation.epicerie.boulangerie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1114, 'Dépanneur', 1110, 'expense', '#7c2d12', 1, 4, 'categoriesSeed.alimentation.epicerie.depanneur');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1115, 'Marché & produits spécialisés', 1110, 'expense', '#fb923c', 1, 5, 'categoriesSeed.alimentation.epicerie.marche');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1120, 'Restauration', 1100, 'expense', '#f97316', 0, 2, 'categoriesSeed.alimentation.restauration.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1121, 'Restaurant', 1120, 'expense', '#f97316', 1, 1, 'categoriesSeed.alimentation.restauration.restaurant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1122, 'Café & boulangerie rapide', 1120, 'expense', '#fb923c', 1, 2, 'categoriesSeed.alimentation.restauration.cafe');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1123, 'Restauration rapide', 1120, 'expense', '#fdba74', 1, 3, 'categoriesSeed.alimentation.restauration.fastfood');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1124, 'Livraison à domicile', 1120, 'expense', '#fed7aa', 1, 4, 'categoriesSeed.alimentation.restauration.livraison');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1125, 'Cantine & cafétéria', 1120, 'expense', '#ffedd5', 1, 5, 'categoriesSeed.alimentation.restauration.cantine');
|
||||
|
||||
-- 1200 — Logement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1210, 'Habitation principale', 1200, 'expense', '#dc2626', 0, 1, 'categoriesSeed.logement.habitation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1211, 'Loyer', 1210, 'expense', '#dc2626', 1, 1, 'categoriesSeed.logement.habitation.loyer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1212, 'Hypothèque', 1210, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.logement.habitation.hypotheque');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1213, 'Taxes municipales & scolaires', 1210, 'expense', '#991b1b', 1, 3, 'categoriesSeed.logement.habitation.taxes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1214, 'Charges de copropriété', 1210, 'expense', '#7f1d1d', 1, 4, 'categoriesSeed.logement.habitation.copropriete');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1220, 'Services publics', 1200, 'expense', '#ef4444', 0, 2, 'categoriesSeed.logement.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1221, 'Électricité', 1220, 'expense', '#ef4444', 1, 1, 'categoriesSeed.logement.services.electricite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1222, 'Gaz naturel', 1220, 'expense', '#f87171', 1, 2, 'categoriesSeed.logement.services.gaz');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1223, 'Chauffage (mazout, propane)', 1220, 'expense', '#fca5a5', 1, 3, 'categoriesSeed.logement.services.chauffage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1224, 'Eau & égouts', 1220, 'expense', '#fecaca', 1, 4, 'categoriesSeed.logement.services.eau');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1230, 'Communications', 1200, 'expense', '#6366f1', 0, 3, 'categoriesSeed.logement.communications.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1231, 'Internet résidentiel', 1230, 'expense', '#6366f1', 1, 1, 'categoriesSeed.logement.communications.internet');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1232, 'Téléphonie mobile', 1230, 'expense', '#818cf8', 1, 2, 'categoriesSeed.logement.communications.mobile');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1233, 'Téléphonie résidentielle', 1230, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.logement.communications.residentielle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1234, 'Câblodistribution & streaming TV', 1230, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.logement.communications.streamingTv');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1240, 'Entretien & réparations', 1200, 'expense', '#e11d48', 0, 4, 'categoriesSeed.logement.entretien.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1241, 'Entretien général', 1240, 'expense', '#e11d48', 1, 1, 'categoriesSeed.logement.entretien.general');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1242, 'Rénovations', 1240, 'expense', '#be123c', 1, 2, 'categoriesSeed.logement.entretien.renovations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1243, 'Matériaux & outils', 1240, 'expense', '#9f1239', 1, 3, 'categoriesSeed.logement.entretien.materiaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1244, 'Aménagement paysager', 1240, 'expense', '#881337', 1, 4, 'categoriesSeed.logement.entretien.paysager');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1250, 'Assurance habitation', 1200, 'expense', '#14b8a6', 1, 5, 'categoriesSeed.logement.assurance');
|
||||
|
||||
-- 1300 — Ménage & ameublement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1310, 'Ameublement', 1300, 'expense', '#ca8a04', 0, 1, 'categoriesSeed.menage.ameublement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1311, 'Meubles', 1310, 'expense', '#ca8a04', 1, 1, 'categoriesSeed.menage.ameublement.meubles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1312, 'Électroménagers', 1310, 'expense', '#a16207', 1, 2, 'categoriesSeed.menage.ameublement.electromenagers');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1313, 'Décoration', 1310, 'expense', '#854d0e', 1, 3, 'categoriesSeed.menage.ameublement.decoration');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1320, 'Fournitures ménagères', 1300, 'expense', '#eab308', 0, 2, 'categoriesSeed.menage.fournitures.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1321, 'Produits d''entretien', 1320, 'expense', '#eab308', 1, 1, 'categoriesSeed.menage.fournitures.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1322, 'Literie & linge de maison', 1320, 'expense', '#facc15', 1, 2, 'categoriesSeed.menage.fournitures.literie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1323, 'Vaisselle & ustensiles', 1320, 'expense', '#fde047', 1, 3, 'categoriesSeed.menage.fournitures.vaisselle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1330, 'Services domestiques', 1300, 'expense', '#fbbf24', 0, 3, 'categoriesSeed.menage.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1331, 'Ménage & nettoyage', 1330, 'expense', '#fbbf24', 1, 1, 'categoriesSeed.menage.services.nettoyage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1332, 'Buanderie & pressing', 1330, 'expense', '#fcd34d', 1, 2, 'categoriesSeed.menage.services.buanderie');
|
||||
|
||||
-- 1400 — Vêtements & chaussures
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1410, 'Vêtements adultes', 1400, 'expense', '#d946ef', 1, 1, 'categoriesSeed.vetements.adultes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1420, 'Vêtements enfants', 1400, 'expense', '#c026d3', 1, 2, 'categoriesSeed.vetements.enfants');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1430, 'Chaussures', 1400, 'expense', '#a21caf', 1, 3, 'categoriesSeed.vetements.chaussures');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1440, 'Accessoires & bijoux', 1400, 'expense', '#86198f', 1, 4, 'categoriesSeed.vetements.accessoires');
|
||||
|
||||
-- 1500 — Transport
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1510, 'Véhicule personnel', 1500, 'expense', '#2563eb', 0, 1, 'categoriesSeed.transport.vehicule.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1511, 'Achat / location véhicule', 1510, 'expense', '#2563eb', 1, 1, 'categoriesSeed.transport.vehicule.achat');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1512, 'Essence', 1510, 'expense', '#1d4ed8', 1, 2, 'categoriesSeed.transport.vehicule.essence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1513, 'Entretien & réparations auto', 1510, 'expense', '#1e40af', 1, 3, 'categoriesSeed.transport.vehicule.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1514, 'Immatriculation & permis', 1510, 'expense', '#1e3a8a', 1, 4, 'categoriesSeed.transport.vehicule.immatriculation');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1515, 'Stationnement & péages', 1510, 'expense', '#3b82f6', 1, 5, 'categoriesSeed.transport.vehicule.stationnement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1516, 'Assurance auto', 1510, 'expense', '#60a5fa', 1, 6, 'categoriesSeed.transport.vehicule.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1520, 'Transport public', 1500, 'expense', '#0ea5e9', 0, 2, 'categoriesSeed.transport.public.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1521, 'Autobus & métro', 1520, 'expense', '#0ea5e9', 1, 1, 'categoriesSeed.transport.public.autobus');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1522, 'Train de banlieue', 1520, 'expense', '#0284c7', 1, 2, 'categoriesSeed.transport.public.train');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1523, 'Taxi & covoiturage', 1520, 'expense', '#0369a1', 1, 3, 'categoriesSeed.transport.public.taxi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1530, 'Voyages longue distance', 1500, 'expense', '#38bdf8', 0, 3, 'categoriesSeed.transport.voyages.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1531, 'Avion', 1530, 'expense', '#38bdf8', 1, 1, 'categoriesSeed.transport.voyages.avion');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1532, 'Train & autocar', 1530, 'expense', '#7dd3fc', 1, 2, 'categoriesSeed.transport.voyages.trainAutocar');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1533, 'Hébergement', 1530, 'expense', '#bae6fd', 1, 3, 'categoriesSeed.transport.voyages.hebergement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1534, 'Location véhicule voyage', 1530, 'expense', '#e0f2fe', 1, 4, 'categoriesSeed.transport.voyages.location');
|
||||
|
||||
-- 1600 — Santé & soins personnels
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1610, 'Soins médicaux', 1600, 'expense', '#f43f5e', 0, 1, 'categoriesSeed.sante.medicaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1611, 'Pharmacie', 1610, 'expense', '#f43f5e', 1, 1, 'categoriesSeed.sante.medicaux.pharmacie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1612, 'Consultations médicales', 1610, 'expense', '#e11d48', 1, 2, 'categoriesSeed.sante.medicaux.consultations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1613, 'Dentiste & orthodontiste', 1610, 'expense', '#be123c', 1, 3, 'categoriesSeed.sante.medicaux.dentiste');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1614, 'Optométrie & lunettes', 1610, 'expense', '#9f1239', 1, 4, 'categoriesSeed.sante.medicaux.optometrie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1615, 'Thérapies (physio, psycho, etc.)', 1610, 'expense', '#881337', 1, 5, 'categoriesSeed.sante.medicaux.therapies');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1616, 'Assurance santé complémentaire', 1610, 'expense', '#fb7185', 1, 6, 'categoriesSeed.sante.medicaux.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1620, 'Soins personnels', 1600, 'expense', '#fb7185', 0, 2, 'categoriesSeed.sante.personnels.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1621, 'Coiffure & esthétique', 1620, 'expense', '#fb7185', 1, 1, 'categoriesSeed.sante.personnels.coiffure');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1622, 'Produits de soins corporels', 1620, 'expense', '#fda4af', 1, 2, 'categoriesSeed.sante.personnels.soins');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1630, 'Assurance vie & invalidité', 1600, 'expense', '#14b8a6', 1, 3, 'categoriesSeed.sante.assuranceVie');
|
||||
|
||||
-- 1700 — Loisirs, formation & lecture
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1710, 'Divertissement', 1700, 'expense', '#8b5cf6', 0, 1, 'categoriesSeed.loisirs.divertissement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1711, 'Cinéma & spectacles', 1710, 'expense', '#8b5cf6', 1, 1, 'categoriesSeed.loisirs.divertissement.cinema');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1712, 'Jeux vidéo & consoles', 1710, 'expense', '#a78bfa', 1, 2, 'categoriesSeed.loisirs.divertissement.jeux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1713, 'Streaming vidéo', 1710, 'expense', '#c4b5fd', 1, 3, 'categoriesSeed.loisirs.divertissement.streamingVideo');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1714, 'Streaming musique & audio', 1710, 'expense', '#ddd6fe', 1, 4, 'categoriesSeed.loisirs.divertissement.streamingMusique');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1715, 'Jouets & passe-temps', 1710, 'expense', '#ede9fe', 1, 5, 'categoriesSeed.loisirs.divertissement.jouets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1720, 'Sports & plein air', 1700, 'expense', '#22c55e', 0, 2, 'categoriesSeed.loisirs.sports.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1721, 'Abonnements sportifs', 1720, 'expense', '#22c55e', 1, 1, 'categoriesSeed.loisirs.sports.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1722, 'Équipement sportif', 1720, 'expense', '#4ade80', 1, 2, 'categoriesSeed.loisirs.sports.equipement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1723, 'Parcs & activités plein air', 1720, 'expense', '#86efac', 1, 3, 'categoriesSeed.loisirs.sports.parcs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1730, 'Formation & éducation', 1700, 'expense', '#6366f1', 0, 3, 'categoriesSeed.loisirs.formation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1731, 'Scolarité (frais)', 1730, 'expense', '#6366f1', 1, 1, 'categoriesSeed.loisirs.formation.scolarite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1732, 'Matériel scolaire', 1730, 'expense', '#818cf8', 1, 2, 'categoriesSeed.loisirs.formation.materiel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1733, 'Cours & certifications', 1730, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.loisirs.formation.cours');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1734, 'Abonnements professionnels', 1730, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.loisirs.formation.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1740, 'Lecture & médias', 1700, 'expense', '#ec4899', 0, 4, 'categoriesSeed.loisirs.lecture.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1741, 'Livres', 1740, 'expense', '#ec4899', 1, 1, 'categoriesSeed.loisirs.lecture.livres');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1742, 'Journaux & magazines', 1740, 'expense', '#f472b6', 1, 2, 'categoriesSeed.loisirs.lecture.journaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1750, 'Animaux de compagnie', 1700, 'expense', '#a855f7', 0, 5, 'categoriesSeed.loisirs.animaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1751, 'Nourriture & accessoires animaux', 1750, 'expense', '#a855f7', 1, 1, 'categoriesSeed.loisirs.animaux.nourriture');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1752, 'Vétérinaire', 1750, 'expense', '#c084fc', 1, 2, 'categoriesSeed.loisirs.animaux.veterinaire');
|
||||
|
||||
-- 1800 — Boissons, tabac & cannabis
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1810, 'Alcool (SAQ, microbrasseries)', 1800, 'expense', '#7c3aed', 1, 1, 'categoriesSeed.consommation.alcool');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1820, 'Cannabis (SQDC)', 1800, 'expense', '#6d28d9', 1, 2, 'categoriesSeed.consommation.cannabis');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1830, 'Tabac', 1800, 'expense', '#5b21b6', 1, 3, 'categoriesSeed.consommation.tabac');
|
||||
|
||||
-- 1900 — Finances & obligations
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1910, 'Frais bancaires', 1900, 'expense', '#6b7280', 0, 1, 'categoriesSeed.finances.fraisBancaires.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1911, 'Frais de compte', 1910, 'expense', '#6b7280', 1, 1, 'categoriesSeed.finances.fraisBancaires.compte');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1912, 'Intérêts & frais de crédit', 1910, 'expense', '#9ca3af', 1, 2, 'categoriesSeed.finances.fraisBancaires.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1913, 'Frais de change', 1910, 'expense', '#d1d5db', 1, 3, 'categoriesSeed.finances.fraisBancaires.change');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1920, 'Impôts & taxes', 1900, 'expense', '#dc2626', 0, 2, 'categoriesSeed.finances.impots.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1921, 'Impôt fédéral', 1920, 'expense', '#dc2626', 1, 1, 'categoriesSeed.finances.impots.federal');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1922, 'Impôt provincial', 1920, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.finances.impots.provincial');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1923, 'Acomptes provisionnels', 1920, 'expense', '#991b1b', 1, 3, 'categoriesSeed.finances.impots.acomptes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1930, 'Dons & cotisations', 1900, 'expense', '#ec4899', 0, 3, 'categoriesSeed.finances.dons.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1931, 'Dons de charité', 1930, 'expense', '#ec4899', 1, 1, 'categoriesSeed.finances.dons.charite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1932, 'Cotisations professionnelles', 1930, 'expense', '#f472b6', 1, 2, 'categoriesSeed.finances.dons.professionnelles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1933, 'Cotisations syndicales', 1930, 'expense', '#f9a8d4', 1, 3, 'categoriesSeed.finances.dons.syndicales');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1940, 'Cadeaux', 1900, 'expense', '#f43f5e', 1, 4, 'categoriesSeed.finances.cadeaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1945, 'Retrait cash', 1900, 'expense', '#57534e', 1, 5, 'categoriesSeed.finances.cash');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1946, 'Achats divers non catégorisés', 1900, 'expense', '#78716c', 1, 6, 'categoriesSeed.finances.divers');
|
||||
|
||||
-- 1950 — Transferts & placements
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1960, 'Épargne & placements', 1950, 'transfer', '#0ea5e9', 0, 1, 'categoriesSeed.transferts.epargne.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1961, 'REER / RRSP', 1960, 'transfer', '#0ea5e9', 1, 1, 'categoriesSeed.transferts.epargne.reer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1962, 'CELI / TFSA', 1960, 'transfer', '#0284c7', 1, 2, 'categoriesSeed.transferts.epargne.celi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1963, 'REEE / RESP', 1960, 'transfer', '#0369a1', 1, 3, 'categoriesSeed.transferts.epargne.reee');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1964, 'Compte non-enregistré', 1960, 'transfer', '#075985', 1, 4, 'categoriesSeed.transferts.epargne.nonEnregistre');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1965, 'Fonds d''urgence', 1960, 'transfer', '#0c4a6e', 1, 5, 'categoriesSeed.transferts.epargne.urgence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1970, 'Remboursement de dette', 1950, 'transfer', '#7c3aed', 0, 2, 'categoriesSeed.transferts.dette.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1971, 'Paiement carte crédit', 1970, 'transfer', '#7c3aed', 1, 1, 'categoriesSeed.transferts.dette.carteCredit');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1972, 'Remboursement prêt étudiant', 1970, 'transfer', '#8b5cf6', 1, 2, 'categoriesSeed.transferts.dette.etudiant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1973, 'Remboursement prêt perso', 1970, 'transfer', '#a78bfa', 1, 3, 'categoriesSeed.transferts.dette.personnel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1980, 'Transferts internes', 1950, 'transfer', '#64748b', 1, 3, 'categoriesSeed.transferts.internes');
|
||||
|
||||
-- ============================================================================
|
||||
-- Keywords — Canadian suppliers (150+ entries)
|
||||
-- ============================================================================
|
||||
|
||||
-- Alimentation > Épicerie régulière (1111)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('METRO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IGA', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MAXI', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUPER C', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LOBLAWS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROVIGO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ADONIS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WHOLE FOODS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AVRIL', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RACHELLE-BERY', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COSTCO', 1111, 50);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WALMART', 1111, 50);
|
||||
|
||||
-- Épicerie > Boucherie (1112)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCHERIE', 1112, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('POISSONNERIE', 1112, 0);
|
||||
|
||||
-- Épicerie > Boulangerie (1113)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOULANGERIE', 1113, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PATISSERIE', 1113, 0);
|
||||
|
||||
-- Épicerie > Dépanneur (1114)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPANNEUR', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('7-ELEVEN', 1114, 0);
|
||||
|
||||
-- Restauration > Restaurant (1121)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RESTAURANT', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRASSERIE', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BISTRO', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUSHI', 1121, 0);
|
||||
|
||||
-- Restauration > Café (1122)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STARBUCKS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIM HORTONS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SECOND CUP', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VAN HOUTTE', 1122, 0);
|
||||
|
||||
-- Restauration > Fast food (1123)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MCDONALD', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUBWAY', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('A&W', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BURGER KING', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KFC', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOMINOS', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PIZZA HUT', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELLE PROVINCE', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ST-HUBERT', 1123, 0);
|
||||
|
||||
-- Restauration > Livraison (1124)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DD/DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER EATS', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SKIPTHEDISHES', 1124, 0);
|
||||
|
||||
-- Logement > Hypothèque (1212)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MTG/HYP', 1212, 0);
|
||||
|
||||
-- Logement > Taxes municipales (1213)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('M-ST-HILAIRE TX', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXES MUNICIPALES', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CSS PATRIOT', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXE SCOLAIRE', 1213, 0);
|
||||
|
||||
-- Électricité (1221)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO-QUEBEC', 1221, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO QUEBEC', 1221, 0);
|
||||
|
||||
-- Gaz (1222)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ENERGIR', 1222, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAZ METRO', 1222, 0);
|
||||
|
||||
-- Internet (1231)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIDEOTRON', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL INTERNET', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORICOM', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COGECO', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EBOX', 1231, 0);
|
||||
|
||||
-- Mobile (1232)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIZZ', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KOODO', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PUBLIC MOBILE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIRGIN', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL MOBILITE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TELUS MOBILE', 1232, 0);
|
||||
|
||||
-- Entretien maison (1241)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IKEA', 1241, 0);
|
||||
|
||||
-- Matériaux & outils (1243)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANADIAN TIRE', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANAC', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RONA', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HOME DEPOT', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BMR', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRINCESS AUTO', 1243, 0);
|
||||
|
||||
-- Assurance habitation (1250)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELAIR', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRYSM', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INTACT ASSURANCE', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DESJARDINS ASSURANCE', 1250, 0);
|
||||
|
||||
-- Meubles (1311)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TANGUAY', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEON', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STRUCTUBE', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRICK', 1311, 0);
|
||||
|
||||
-- Électroménagers (1312)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BEST BUY', 1312, 0);
|
||||
|
||||
-- Décoration (1313)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCLAIR', 1313, 0);
|
||||
|
||||
-- Vêtements (1410)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIQLO', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WINNERS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SIMONS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARKS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('H&M', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OLD NAVY', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAP', 1410, 0);
|
||||
|
||||
-- Transport — Essence (1512)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SHELL', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ESSO', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ULTRAMAR', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO-CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CREVIER', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HARNOIS', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD ESSENCE', 1512, 10);
|
||||
|
||||
-- Permis / SAAQ (1514)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAAQ', 1514, 0);
|
||||
|
||||
-- Transport public — autobus/métro (1521)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STM', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RTC', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STL', 1521, 0);
|
||||
|
||||
-- Train de banlieue (1522)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE MONT-SAINT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE SAINT-HUBERT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE CENTRALE', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EXO', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REM', 1522, 0);
|
||||
|
||||
-- Taxi / Uber (1523)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LYFT', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXI', 1523, 0);
|
||||
|
||||
-- Avion (1531)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR CANADA', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WESTJET', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR TRANSAT', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PORTER', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AEROPORTS DE MONTREAL', 1531, 0);
|
||||
|
||||
-- Hébergement (1533)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIRBNB', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HILTON', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARRIOTT', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOOKING.COM', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NORWEGIAN CRUISE', 1533, 0);
|
||||
|
||||
-- Pharmacie (1611)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('JEAN COUTU', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FAMILIPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHARMAPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROXIM', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIPRIX', 1611, 0);
|
||||
|
||||
-- Thérapies (1615)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHYSIOACTIF', 1615, 0);
|
||||
|
||||
-- Cinéma & spectacles (1711)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEPLEX', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEMA DU PARC', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TICKETMASTER', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CLUB SODA', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEPOINTDEVENTE', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EVENBRITE', 1711, 0);
|
||||
|
||||
-- Jeux vidéo (1712)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STEAMGAMES', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PLAYSTATION', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NINTENDO', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('XBOX', 1712, 0);
|
||||
|
||||
-- Streaming vidéo (1713)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NETFLIX', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRIMEVIDEO', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DISNEY PLUS', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRAVE', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE TV', 1713, 0);
|
||||
|
||||
-- Streaming musique (1714)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPOTIFY', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('YOUTUBE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIDAL', 1714, 0);
|
||||
|
||||
-- Jouets & hobbies (1715)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEGO', 1715, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TOYS R US', 1715, 0);
|
||||
|
||||
-- Équipement sportif (1722)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MOUNTAIN EQUIPMENT', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LA CORDEE', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DECATHLON', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPORTS EXPERTS', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ATMOSPHERE', 1722, 0);
|
||||
|
||||
-- Parcs & activités (1723)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SEPAQ', 1723, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BLOC SHOP', 1723, 0);
|
||||
|
||||
-- Lecture (1741)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RENAUD-BRAY', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INDIGO', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARCHAMBAULT', 1741, 0);
|
||||
|
||||
-- Animaux — nourriture (1751)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MONDOU', 1751, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PET SMART', 1751, 0);
|
||||
|
||||
-- Alcool (1810)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAQ', 1810, 0);
|
||||
|
||||
-- Cannabis (1820)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SQDC', 1820, 0);
|
||||
|
||||
-- Frais bancaires (1911)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROGRAMME PERFORMANCE', 1911, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FRAIS MENSUELS', 1911, 0);
|
||||
|
||||
-- Impôts (1921, 1922)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GOUV. QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REVENU QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARC IMPOT', 1921, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRA TAX', 1921, 0);
|
||||
|
||||
-- Dons de charité (1931)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OXFAM', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CENTRAIDE', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FPA', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CROIX-ROUGE', 1931, 0);
|
||||
|
||||
-- Cotisations professionnelles (1932)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORDRE DES COMPTABL', 1932, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CPA CANADA', 1932, 0);
|
||||
|
||||
-- Cadeaux (1940)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DANS UN JARDIN', 1940, 0);
|
||||
|
||||
-- Divers (1946) — catch-all marketplace
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMAZON', 1946, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMZN', 1946, 0);
|
||||
|
||||
-- Placements (1964)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WS INVESTMENTS', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WEALTHSIMPLE', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PEAK INVESTMENT', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DYNAMIC FUND', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIDELITY', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AGF', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('QUESTRADE', 1964, 0);
|
||||
|
||||
-- Paie (1011)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAY/PAY', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPOT PAIE', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAYROLL', 1011, 0);
|
||||
747
src-tauri/src/database/fixtures/consolidated_v0.9.0.sql
Normal file
747
src-tauri/src/database/fixtures/consolidated_v0.9.0.sql
Normal file
|
|
@ -0,0 +1,747 @@
|
|||
-- Consolidated schema for new profile databases
|
||||
-- This file bakes in the base schema + all migrations (v3-v8) and pre-seeds
|
||||
-- the v1 IPC-aligned category taxonomy so that brand-new profiles immediately
|
||||
-- use the new standard. Existing profiles keep their v2 seed and are only
|
||||
-- tagged via the migration (categories_schema_version = 'v2').
|
||||
-- Used ONLY for initializing new profile databases (not for the default profile).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS imported_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
file_hash TEXT NOT NULL,
|
||||
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
row_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'completed',
|
||||
notes TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
||||
UNIQUE(source_id, filename)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'expense',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_inputable INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
i18n_key TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
normalized_name TEXT NOT NULL,
|
||||
category_id INTEGER,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS keywords (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
keyword TEXT NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
UNIQUE(keyword, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
category_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
source_id INTEGER,
|
||||
file_id INTEGER,
|
||||
original_description TEXT,
|
||||
notes TEXT,
|
||||
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
||||
is_split INTEGER NOT NULL DEFAULT 0,
|
||||
parent_transaction_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
date DATE NOT NULL,
|
||||
is_recurring INTEGER NOT NULL DEFAULT 0,
|
||||
recurrence_rule TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
adjustment_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
description TEXT,
|
||||
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
month INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(category_id, year, month)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(template_id, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_config_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
date_format TEXT NOT NULL DEFAULT 'DD/MM/YYYY',
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
column_mapping TEXT NOT NULL,
|
||||
amount_mode TEXT NOT NULL DEFAULT 'single',
|
||||
sign_convention TEXT NOT NULL DEFAULT 'negative_expense',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
||||
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
||||
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- Balance sheet (Bilan) — Migration v9 mirror for new profiles
|
||||
-- ============================================================================
|
||||
-- 5 tables + 7 indexes + seeded categories. Kept in sync with
|
||||
-- `balance_schema.sql` (the source of truth applied by Migration v9 in lib.rs).
|
||||
-- New profiles created from this consolidated schema get the balance feature
|
||||
-- preinstalled without needing to replay v9 separately.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key TEXT NOT NULL UNIQUE,
|
||||
i18n_key TEXT NOT NULL,
|
||||
kind TEXT NOT NULL CHECK(kind IN ('simple','priced')),
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_seed INTEGER NOT NULL DEFAULT 0,
|
||||
asset_type TEXT CHECK(asset_type IS NULL OR asset_type IN ('stock','crypto'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
balance_category_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT,
|
||||
currency TEXT NOT NULL DEFAULT 'CAD' CHECK(currency = 'CAD'),
|
||||
notes TEXT,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
archived_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (balance_category_id) REFERENCES balance_categories(id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_date DATE NOT NULL UNIQUE,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshot_lines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_id INTEGER NOT NULL,
|
||||
account_id INTEGER NOT NULL,
|
||||
quantity REAL,
|
||||
unit_price REAL,
|
||||
value REAL NOT NULL,
|
||||
price_source TEXT,
|
||||
price_fetched_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (snapshot_id) REFERENCES balance_snapshots(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE RESTRICT,
|
||||
UNIQUE(snapshot_id, account_id),
|
||||
CHECK (
|
||||
(quantity IS NULL AND unit_price IS NULL)
|
||||
OR (quantity IS NOT NULL AND unit_price IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_account_transfers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL,
|
||||
transaction_id INTEGER NOT NULL,
|
||||
direction TEXT NOT NULL CHECK(direction IN ('in','out')),
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE RESTRICT,
|
||||
UNIQUE(transaction_id, account_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_category ON balance_accounts(balance_category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_active ON balance_accounts(is_active) WHERE is_active = 1;
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_snapshot ON balance_snapshot_lines(snapshot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_account ON balance_snapshot_lines(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_account ON balance_account_transfers(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_transaction ON balance_account_transfers(transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshots_date ON balance_snapshots(snapshot_date);
|
||||
|
||||
INSERT OR IGNORE INTO balance_categories (key, i18n_key, kind, sort_order, is_seed, asset_type) VALUES
|
||||
('cash', 'balance.category.cash', 'simple', 10, 1, NULL),
|
||||
('tfsa', 'balance.category.tfsa', 'simple', 20, 1, NULL),
|
||||
('rrsp', 'balance.category.rrsp', 'simple', 30, 1, NULL),
|
||||
('fund', 'balance.category.fund', 'simple', 40, 1, NULL),
|
||||
('other', 'balance.category.other', 'simple', 50, 1, NULL),
|
||||
('stock', 'balance.category.stock', 'priced', 60, 1, 'stock'),
|
||||
('crypto', 'balance.category.crypto', 'priced', 70, 1, 'crypto');
|
||||
|
||||
-- Default preferences (new profiles ship with the v1 IPC taxonomy)
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|
||||
INSERT OR REPLACE INTO user_preferences (key, value) VALUES ('categories_schema_version', 'v1');
|
||||
|
||||
-- ============================================================================
|
||||
-- Seed v1 — IPC Statistique Canada-aligned, 3 levels, Canada/Québec
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Reset any pre-existing category data (possible when tauri-plugin-sql runs
|
||||
-- the historical v2 seed migration on this fresh DB before this script
|
||||
-- executes). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- (1000+ range) so existing references in migrations v3-v7 stay inert.
|
||||
-- ============================================================================
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- LEVEL 1 — Roots (9 IPC components + Revenus + Transferts)
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1000, 'Revenus', NULL, 'income', '#16a34a', 0, 1, 'categoriesSeed.revenus.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1100, 'Alimentation', NULL, 'expense', '#ea580c', 0, 2, 'categoriesSeed.alimentation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1200, 'Logement', NULL, 'expense', '#dc2626', 0, 3, 'categoriesSeed.logement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1300, 'Ménage & ameublement', NULL, 'expense', '#ca8a04', 0, 4, 'categoriesSeed.menage.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1400, 'Vêtements & chaussures', NULL, 'expense', '#d946ef', 0, 5, 'categoriesSeed.vetements.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1500, 'Transport', NULL, 'expense', '#2563eb', 0, 6, 'categoriesSeed.transport.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1600, 'Santé & soins personnels', NULL, 'expense', '#f43f5e', 0, 7, 'categoriesSeed.sante.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1700, 'Loisirs, formation & lecture', NULL, 'expense', '#8b5cf6', 0, 8, 'categoriesSeed.loisirs.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1800, 'Boissons, tabac & cannabis', NULL, 'expense', '#7c3aed', 0, 9, 'categoriesSeed.consommation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1900, 'Finances & obligations', NULL, 'expense', '#6b7280', 0, 10, 'categoriesSeed.finances.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1950, 'Transferts & placements', NULL, 'transfer', '#0ea5e9', 0, 11, 'categoriesSeed.transferts.root');
|
||||
|
||||
-- 1000 — Revenus
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1010, 'Emploi', 1000, 'income', '#22c55e', 0, 1, 'categoriesSeed.revenus.emploi.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1011, 'Paie régulière', 1010, 'income', '#22c55e', 1, 1, 'categoriesSeed.revenus.emploi.paie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1012, 'Primes & bonus', 1010, 'income', '#4ade80', 1, 2, 'categoriesSeed.revenus.emploi.primes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1013, 'Travail autonome', 1010, 'income', '#86efac', 1, 3, 'categoriesSeed.revenus.emploi.autonome');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1020, 'Gouvernemental', 1000, 'income', '#16a34a', 0, 2, 'categoriesSeed.revenus.gouvernemental.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1021, 'Remboursement impôt', 1020, 'income', '#16a34a', 1, 1, 'categoriesSeed.revenus.gouvernemental.remboursementImpot');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1022, 'Allocations familiales', 1020, 'income', '#15803d', 1, 2, 'categoriesSeed.revenus.gouvernemental.allocations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1023, 'Crédits TPS/TVQ', 1020, 'income', '#166534', 1, 3, 'categoriesSeed.revenus.gouvernemental.credits');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1024, 'Assurance-emploi / RQAP', 1020, 'income', '#14532d', 1, 4, 'categoriesSeed.revenus.gouvernemental.assuranceEmploi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1030, 'Revenus de placement', 1000, 'income', '#10b981', 0, 3, 'categoriesSeed.revenus.placement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1031, 'Intérêts & dividendes', 1030, 'income', '#10b981', 1, 1, 'categoriesSeed.revenus.placement.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1032, 'Gains en capital', 1030, 'income', '#059669', 1, 2, 'categoriesSeed.revenus.placement.capital');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1033, 'Revenus locatifs', 1030, 'income', '#047857', 1, 3, 'categoriesSeed.revenus.placement.locatifs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1090, 'Autres revenus', 1000, 'income', '#84cc16', 1, 9, 'categoriesSeed.revenus.autres');
|
||||
|
||||
-- 1100 — Alimentation
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1110, 'Épicerie & marché', 1100, 'expense', '#ea580c', 0, 1, 'categoriesSeed.alimentation.epicerie.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1111, 'Épicerie régulière', 1110, 'expense', '#ea580c', 1, 1, 'categoriesSeed.alimentation.epicerie.reguliere');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1112, 'Boucherie & poissonnerie', 1110, 'expense', '#c2410c', 1, 2, 'categoriesSeed.alimentation.epicerie.boucherie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1113, 'Boulangerie & pâtisserie', 1110, 'expense', '#9a3412', 1, 3, 'categoriesSeed.alimentation.epicerie.boulangerie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1114, 'Dépanneur', 1110, 'expense', '#7c2d12', 1, 4, 'categoriesSeed.alimentation.epicerie.depanneur');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1115, 'Marché & produits spécialisés', 1110, 'expense', '#fb923c', 1, 5, 'categoriesSeed.alimentation.epicerie.marche');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1120, 'Restauration', 1100, 'expense', '#f97316', 0, 2, 'categoriesSeed.alimentation.restauration.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1121, 'Restaurant', 1120, 'expense', '#f97316', 1, 1, 'categoriesSeed.alimentation.restauration.restaurant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1122, 'Café & boulangerie rapide', 1120, 'expense', '#fb923c', 1, 2, 'categoriesSeed.alimentation.restauration.cafe');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1123, 'Restauration rapide', 1120, 'expense', '#fdba74', 1, 3, 'categoriesSeed.alimentation.restauration.fastfood');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1124, 'Livraison à domicile', 1120, 'expense', '#fed7aa', 1, 4, 'categoriesSeed.alimentation.restauration.livraison');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1125, 'Cantine & cafétéria', 1120, 'expense', '#ffedd5', 1, 5, 'categoriesSeed.alimentation.restauration.cantine');
|
||||
|
||||
-- 1200 — Logement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1210, 'Habitation principale', 1200, 'expense', '#dc2626', 0, 1, 'categoriesSeed.logement.habitation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1211, 'Loyer', 1210, 'expense', '#dc2626', 1, 1, 'categoriesSeed.logement.habitation.loyer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1212, 'Hypothèque', 1210, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.logement.habitation.hypotheque');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1213, 'Taxes municipales & scolaires', 1210, 'expense', '#991b1b', 1, 3, 'categoriesSeed.logement.habitation.taxes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1214, 'Charges de copropriété', 1210, 'expense', '#7f1d1d', 1, 4, 'categoriesSeed.logement.habitation.copropriete');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1220, 'Services publics', 1200, 'expense', '#ef4444', 0, 2, 'categoriesSeed.logement.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1221, 'Électricité', 1220, 'expense', '#ef4444', 1, 1, 'categoriesSeed.logement.services.electricite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1222, 'Gaz naturel', 1220, 'expense', '#f87171', 1, 2, 'categoriesSeed.logement.services.gaz');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1223, 'Chauffage (mazout, propane)', 1220, 'expense', '#fca5a5', 1, 3, 'categoriesSeed.logement.services.chauffage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1224, 'Eau & égouts', 1220, 'expense', '#fecaca', 1, 4, 'categoriesSeed.logement.services.eau');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1230, 'Communications', 1200, 'expense', '#6366f1', 0, 3, 'categoriesSeed.logement.communications.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1231, 'Internet résidentiel', 1230, 'expense', '#6366f1', 1, 1, 'categoriesSeed.logement.communications.internet');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1232, 'Téléphonie mobile', 1230, 'expense', '#818cf8', 1, 2, 'categoriesSeed.logement.communications.mobile');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1233, 'Téléphonie résidentielle', 1230, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.logement.communications.residentielle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1234, 'Câblodistribution & streaming TV', 1230, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.logement.communications.streamingTv');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1240, 'Entretien & réparations', 1200, 'expense', '#e11d48', 0, 4, 'categoriesSeed.logement.entretien.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1241, 'Entretien général', 1240, 'expense', '#e11d48', 1, 1, 'categoriesSeed.logement.entretien.general');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1242, 'Rénovations', 1240, 'expense', '#be123c', 1, 2, 'categoriesSeed.logement.entretien.renovations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1243, 'Matériaux & outils', 1240, 'expense', '#9f1239', 1, 3, 'categoriesSeed.logement.entretien.materiaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1244, 'Aménagement paysager', 1240, 'expense', '#881337', 1, 4, 'categoriesSeed.logement.entretien.paysager');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1250, 'Assurance habitation', 1200, 'expense', '#14b8a6', 1, 5, 'categoriesSeed.logement.assurance');
|
||||
|
||||
-- 1300 — Ménage & ameublement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1310, 'Ameublement', 1300, 'expense', '#ca8a04', 0, 1, 'categoriesSeed.menage.ameublement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1311, 'Meubles', 1310, 'expense', '#ca8a04', 1, 1, 'categoriesSeed.menage.ameublement.meubles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1312, 'Électroménagers', 1310, 'expense', '#a16207', 1, 2, 'categoriesSeed.menage.ameublement.electromenagers');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1313, 'Décoration', 1310, 'expense', '#854d0e', 1, 3, 'categoriesSeed.menage.ameublement.decoration');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1320, 'Fournitures ménagères', 1300, 'expense', '#eab308', 0, 2, 'categoriesSeed.menage.fournitures.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1321, 'Produits d''entretien', 1320, 'expense', '#eab308', 1, 1, 'categoriesSeed.menage.fournitures.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1322, 'Literie & linge de maison', 1320, 'expense', '#facc15', 1, 2, 'categoriesSeed.menage.fournitures.literie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1323, 'Vaisselle & ustensiles', 1320, 'expense', '#fde047', 1, 3, 'categoriesSeed.menage.fournitures.vaisselle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1330, 'Services domestiques', 1300, 'expense', '#fbbf24', 0, 3, 'categoriesSeed.menage.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1331, 'Ménage & nettoyage', 1330, 'expense', '#fbbf24', 1, 1, 'categoriesSeed.menage.services.nettoyage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1332, 'Buanderie & pressing', 1330, 'expense', '#fcd34d', 1, 2, 'categoriesSeed.menage.services.buanderie');
|
||||
|
||||
-- 1400 — Vêtements & chaussures
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1410, 'Vêtements adultes', 1400, 'expense', '#d946ef', 1, 1, 'categoriesSeed.vetements.adultes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1420, 'Vêtements enfants', 1400, 'expense', '#c026d3', 1, 2, 'categoriesSeed.vetements.enfants');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1430, 'Chaussures', 1400, 'expense', '#a21caf', 1, 3, 'categoriesSeed.vetements.chaussures');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1440, 'Accessoires & bijoux', 1400, 'expense', '#86198f', 1, 4, 'categoriesSeed.vetements.accessoires');
|
||||
|
||||
-- 1500 — Transport
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1510, 'Véhicule personnel', 1500, 'expense', '#2563eb', 0, 1, 'categoriesSeed.transport.vehicule.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1511, 'Achat / location véhicule', 1510, 'expense', '#2563eb', 1, 1, 'categoriesSeed.transport.vehicule.achat');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1512, 'Essence', 1510, 'expense', '#1d4ed8', 1, 2, 'categoriesSeed.transport.vehicule.essence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1513, 'Entretien & réparations auto', 1510, 'expense', '#1e40af', 1, 3, 'categoriesSeed.transport.vehicule.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1514, 'Immatriculation & permis', 1510, 'expense', '#1e3a8a', 1, 4, 'categoriesSeed.transport.vehicule.immatriculation');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1515, 'Stationnement & péages', 1510, 'expense', '#3b82f6', 1, 5, 'categoriesSeed.transport.vehicule.stationnement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1516, 'Assurance auto', 1510, 'expense', '#60a5fa', 1, 6, 'categoriesSeed.transport.vehicule.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1520, 'Transport public', 1500, 'expense', '#0ea5e9', 0, 2, 'categoriesSeed.transport.public.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1521, 'Autobus & métro', 1520, 'expense', '#0ea5e9', 1, 1, 'categoriesSeed.transport.public.autobus');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1522, 'Train de banlieue', 1520, 'expense', '#0284c7', 1, 2, 'categoriesSeed.transport.public.train');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1523, 'Taxi & covoiturage', 1520, 'expense', '#0369a1', 1, 3, 'categoriesSeed.transport.public.taxi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1530, 'Voyages longue distance', 1500, 'expense', '#38bdf8', 0, 3, 'categoriesSeed.transport.voyages.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1531, 'Avion', 1530, 'expense', '#38bdf8', 1, 1, 'categoriesSeed.transport.voyages.avion');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1532, 'Train & autocar', 1530, 'expense', '#7dd3fc', 1, 2, 'categoriesSeed.transport.voyages.trainAutocar');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1533, 'Hébergement', 1530, 'expense', '#bae6fd', 1, 3, 'categoriesSeed.transport.voyages.hebergement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1534, 'Location véhicule voyage', 1530, 'expense', '#e0f2fe', 1, 4, 'categoriesSeed.transport.voyages.location');
|
||||
|
||||
-- 1600 — Santé & soins personnels
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1610, 'Soins médicaux', 1600, 'expense', '#f43f5e', 0, 1, 'categoriesSeed.sante.medicaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1611, 'Pharmacie', 1610, 'expense', '#f43f5e', 1, 1, 'categoriesSeed.sante.medicaux.pharmacie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1612, 'Consultations médicales', 1610, 'expense', '#e11d48', 1, 2, 'categoriesSeed.sante.medicaux.consultations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1613, 'Dentiste & orthodontiste', 1610, 'expense', '#be123c', 1, 3, 'categoriesSeed.sante.medicaux.dentiste');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1614, 'Optométrie & lunettes', 1610, 'expense', '#9f1239', 1, 4, 'categoriesSeed.sante.medicaux.optometrie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1615, 'Thérapies (physio, psycho, etc.)', 1610, 'expense', '#881337', 1, 5, 'categoriesSeed.sante.medicaux.therapies');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1616, 'Assurance santé complémentaire', 1610, 'expense', '#fb7185', 1, 6, 'categoriesSeed.sante.medicaux.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1620, 'Soins personnels', 1600, 'expense', '#fb7185', 0, 2, 'categoriesSeed.sante.personnels.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1621, 'Coiffure & esthétique', 1620, 'expense', '#fb7185', 1, 1, 'categoriesSeed.sante.personnels.coiffure');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1622, 'Produits de soins corporels', 1620, 'expense', '#fda4af', 1, 2, 'categoriesSeed.sante.personnels.soins');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1630, 'Assurance vie & invalidité', 1600, 'expense', '#14b8a6', 1, 3, 'categoriesSeed.sante.assuranceVie');
|
||||
|
||||
-- 1700 — Loisirs, formation & lecture
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1710, 'Divertissement', 1700, 'expense', '#8b5cf6', 0, 1, 'categoriesSeed.loisirs.divertissement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1711, 'Cinéma & spectacles', 1710, 'expense', '#8b5cf6', 1, 1, 'categoriesSeed.loisirs.divertissement.cinema');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1712, 'Jeux vidéo & consoles', 1710, 'expense', '#a78bfa', 1, 2, 'categoriesSeed.loisirs.divertissement.jeux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1713, 'Streaming vidéo', 1710, 'expense', '#c4b5fd', 1, 3, 'categoriesSeed.loisirs.divertissement.streamingVideo');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1714, 'Streaming musique & audio', 1710, 'expense', '#ddd6fe', 1, 4, 'categoriesSeed.loisirs.divertissement.streamingMusique');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1715, 'Jouets & passe-temps', 1710, 'expense', '#ede9fe', 1, 5, 'categoriesSeed.loisirs.divertissement.jouets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1720, 'Sports & plein air', 1700, 'expense', '#22c55e', 0, 2, 'categoriesSeed.loisirs.sports.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1721, 'Abonnements sportifs', 1720, 'expense', '#22c55e', 1, 1, 'categoriesSeed.loisirs.sports.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1722, 'Équipement sportif', 1720, 'expense', '#4ade80', 1, 2, 'categoriesSeed.loisirs.sports.equipement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1723, 'Parcs & activités plein air', 1720, 'expense', '#86efac', 1, 3, 'categoriesSeed.loisirs.sports.parcs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1730, 'Formation & éducation', 1700, 'expense', '#6366f1', 0, 3, 'categoriesSeed.loisirs.formation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1731, 'Scolarité (frais)', 1730, 'expense', '#6366f1', 1, 1, 'categoriesSeed.loisirs.formation.scolarite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1732, 'Matériel scolaire', 1730, 'expense', '#818cf8', 1, 2, 'categoriesSeed.loisirs.formation.materiel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1733, 'Cours & certifications', 1730, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.loisirs.formation.cours');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1734, 'Abonnements professionnels', 1730, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.loisirs.formation.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1740, 'Lecture & médias', 1700, 'expense', '#ec4899', 0, 4, 'categoriesSeed.loisirs.lecture.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1741, 'Livres', 1740, 'expense', '#ec4899', 1, 1, 'categoriesSeed.loisirs.lecture.livres');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1742, 'Journaux & magazines', 1740, 'expense', '#f472b6', 1, 2, 'categoriesSeed.loisirs.lecture.journaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1750, 'Animaux de compagnie', 1700, 'expense', '#a855f7', 0, 5, 'categoriesSeed.loisirs.animaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1751, 'Nourriture & accessoires animaux', 1750, 'expense', '#a855f7', 1, 1, 'categoriesSeed.loisirs.animaux.nourriture');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1752, 'Vétérinaire', 1750, 'expense', '#c084fc', 1, 2, 'categoriesSeed.loisirs.animaux.veterinaire');
|
||||
|
||||
-- 1800 — Boissons, tabac & cannabis
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1810, 'Alcool (SAQ, microbrasseries)', 1800, 'expense', '#7c3aed', 1, 1, 'categoriesSeed.consommation.alcool');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1820, 'Cannabis (SQDC)', 1800, 'expense', '#6d28d9', 1, 2, 'categoriesSeed.consommation.cannabis');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1830, 'Tabac', 1800, 'expense', '#5b21b6', 1, 3, 'categoriesSeed.consommation.tabac');
|
||||
|
||||
-- 1900 — Finances & obligations
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1910, 'Frais bancaires', 1900, 'expense', '#6b7280', 0, 1, 'categoriesSeed.finances.fraisBancaires.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1911, 'Frais de compte', 1910, 'expense', '#6b7280', 1, 1, 'categoriesSeed.finances.fraisBancaires.compte');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1912, 'Intérêts & frais de crédit', 1910, 'expense', '#9ca3af', 1, 2, 'categoriesSeed.finances.fraisBancaires.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1913, 'Frais de change', 1910, 'expense', '#d1d5db', 1, 3, 'categoriesSeed.finances.fraisBancaires.change');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1920, 'Impôts & taxes', 1900, 'expense', '#dc2626', 0, 2, 'categoriesSeed.finances.impots.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1921, 'Impôt fédéral', 1920, 'expense', '#dc2626', 1, 1, 'categoriesSeed.finances.impots.federal');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1922, 'Impôt provincial', 1920, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.finances.impots.provincial');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1923, 'Acomptes provisionnels', 1920, 'expense', '#991b1b', 1, 3, 'categoriesSeed.finances.impots.acomptes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1930, 'Dons & cotisations', 1900, 'expense', '#ec4899', 0, 3, 'categoriesSeed.finances.dons.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1931, 'Dons de charité', 1930, 'expense', '#ec4899', 1, 1, 'categoriesSeed.finances.dons.charite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1932, 'Cotisations professionnelles', 1930, 'expense', '#f472b6', 1, 2, 'categoriesSeed.finances.dons.professionnelles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1933, 'Cotisations syndicales', 1930, 'expense', '#f9a8d4', 1, 3, 'categoriesSeed.finances.dons.syndicales');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1940, 'Cadeaux', 1900, 'expense', '#f43f5e', 1, 4, 'categoriesSeed.finances.cadeaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1945, 'Retrait cash', 1900, 'expense', '#57534e', 1, 5, 'categoriesSeed.finances.cash');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1946, 'Achats divers non catégorisés', 1900, 'expense', '#78716c', 1, 6, 'categoriesSeed.finances.divers');
|
||||
|
||||
-- 1950 — Transferts & placements
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1960, 'Épargne & placements', 1950, 'transfer', '#0ea5e9', 0, 1, 'categoriesSeed.transferts.epargne.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1961, 'REER / RRSP', 1960, 'transfer', '#0ea5e9', 1, 1, 'categoriesSeed.transferts.epargne.reer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1962, 'CELI / TFSA', 1960, 'transfer', '#0284c7', 1, 2, 'categoriesSeed.transferts.epargne.celi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1963, 'REEE / RESP', 1960, 'transfer', '#0369a1', 1, 3, 'categoriesSeed.transferts.epargne.reee');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1964, 'Compte non-enregistré', 1960, 'transfer', '#075985', 1, 4, 'categoriesSeed.transferts.epargne.nonEnregistre');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1965, 'Fonds d''urgence', 1960, 'transfer', '#0c4a6e', 1, 5, 'categoriesSeed.transferts.epargne.urgence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1970, 'Remboursement de dette', 1950, 'transfer', '#7c3aed', 0, 2, 'categoriesSeed.transferts.dette.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1971, 'Paiement carte crédit', 1970, 'transfer', '#7c3aed', 1, 1, 'categoriesSeed.transferts.dette.carteCredit');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1972, 'Remboursement prêt étudiant', 1970, 'transfer', '#8b5cf6', 1, 2, 'categoriesSeed.transferts.dette.etudiant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1973, 'Remboursement prêt perso', 1970, 'transfer', '#a78bfa', 1, 3, 'categoriesSeed.transferts.dette.personnel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1980, 'Transferts internes', 1950, 'transfer', '#64748b', 1, 3, 'categoriesSeed.transferts.internes');
|
||||
|
||||
-- ============================================================================
|
||||
-- Keywords — Canadian suppliers (150+ entries)
|
||||
-- ============================================================================
|
||||
|
||||
-- Alimentation > Épicerie régulière (1111)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('METRO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IGA', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MAXI', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUPER C', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LOBLAWS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROVIGO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ADONIS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WHOLE FOODS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AVRIL', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RACHELLE-BERY', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COSTCO', 1111, 50);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WALMART', 1111, 50);
|
||||
|
||||
-- Épicerie > Boucherie (1112)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCHERIE', 1112, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('POISSONNERIE', 1112, 0);
|
||||
|
||||
-- Épicerie > Boulangerie (1113)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOULANGERIE', 1113, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PATISSERIE', 1113, 0);
|
||||
|
||||
-- Épicerie > Dépanneur (1114)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPANNEUR', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('7-ELEVEN', 1114, 0);
|
||||
|
||||
-- Restauration > Restaurant (1121)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RESTAURANT', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRASSERIE', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BISTRO', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUSHI', 1121, 0);
|
||||
|
||||
-- Restauration > Café (1122)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STARBUCKS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIM HORTONS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SECOND CUP', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VAN HOUTTE', 1122, 0);
|
||||
|
||||
-- Restauration > Fast food (1123)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MCDONALD', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUBWAY', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('A&W', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BURGER KING', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KFC', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOMINOS', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PIZZA HUT', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELLE PROVINCE', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ST-HUBERT', 1123, 0);
|
||||
|
||||
-- Restauration > Livraison (1124)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DD/DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER EATS', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SKIPTHEDISHES', 1124, 0);
|
||||
|
||||
-- Logement > Hypothèque (1212)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MTG/HYP', 1212, 0);
|
||||
|
||||
-- Logement > Taxes municipales (1213)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('M-ST-HILAIRE TX', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXES MUNICIPALES', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CSS PATRIOT', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXE SCOLAIRE', 1213, 0);
|
||||
|
||||
-- Électricité (1221)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO-QUEBEC', 1221, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO QUEBEC', 1221, 0);
|
||||
|
||||
-- Gaz (1222)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ENERGIR', 1222, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAZ METRO', 1222, 0);
|
||||
|
||||
-- Internet (1231)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIDEOTRON', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL INTERNET', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORICOM', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COGECO', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EBOX', 1231, 0);
|
||||
|
||||
-- Mobile (1232)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIZZ', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KOODO', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PUBLIC MOBILE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIRGIN', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL MOBILITE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TELUS MOBILE', 1232, 0);
|
||||
|
||||
-- Entretien maison (1241)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IKEA', 1241, 0);
|
||||
|
||||
-- Matériaux & outils (1243)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANADIAN TIRE', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANAC', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RONA', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HOME DEPOT', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BMR', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRINCESS AUTO', 1243, 0);
|
||||
|
||||
-- Assurance habitation (1250)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELAIR', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRYSM', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INTACT ASSURANCE', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DESJARDINS ASSURANCE', 1250, 0);
|
||||
|
||||
-- Meubles (1311)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TANGUAY', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEON', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STRUCTUBE', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRICK', 1311, 0);
|
||||
|
||||
-- Électroménagers (1312)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BEST BUY', 1312, 0);
|
||||
|
||||
-- Décoration (1313)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCLAIR', 1313, 0);
|
||||
|
||||
-- Vêtements (1410)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIQLO', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WINNERS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SIMONS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARKS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('H&M', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OLD NAVY', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAP', 1410, 0);
|
||||
|
||||
-- Transport — Essence (1512)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SHELL', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ESSO', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ULTRAMAR', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO-CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CREVIER', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HARNOIS', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD ESSENCE', 1512, 10);
|
||||
|
||||
-- Permis / SAAQ (1514)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAAQ', 1514, 0);
|
||||
|
||||
-- Transport public — autobus/métro (1521)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STM', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RTC', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STL', 1521, 0);
|
||||
|
||||
-- Train de banlieue (1522)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE MONT-SAINT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE SAINT-HUBERT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE CENTRALE', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EXO', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REM', 1522, 0);
|
||||
|
||||
-- Taxi / Uber (1523)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LYFT', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXI', 1523, 0);
|
||||
|
||||
-- Avion (1531)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR CANADA', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WESTJET', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR TRANSAT', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PORTER', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AEROPORTS DE MONTREAL', 1531, 0);
|
||||
|
||||
-- Hébergement (1533)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIRBNB', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HILTON', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARRIOTT', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOOKING.COM', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NORWEGIAN CRUISE', 1533, 0);
|
||||
|
||||
-- Pharmacie (1611)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('JEAN COUTU', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FAMILIPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHARMAPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROXIM', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIPRIX', 1611, 0);
|
||||
|
||||
-- Thérapies (1615)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHYSIOACTIF', 1615, 0);
|
||||
|
||||
-- Cinéma & spectacles (1711)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEPLEX', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEMA DU PARC', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TICKETMASTER', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CLUB SODA', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEPOINTDEVENTE', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EVENBRITE', 1711, 0);
|
||||
|
||||
-- Jeux vidéo (1712)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STEAMGAMES', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PLAYSTATION', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NINTENDO', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('XBOX', 1712, 0);
|
||||
|
||||
-- Streaming vidéo (1713)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NETFLIX', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRIMEVIDEO', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DISNEY PLUS', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRAVE', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE TV', 1713, 0);
|
||||
|
||||
-- Streaming musique (1714)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPOTIFY', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('YOUTUBE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIDAL', 1714, 0);
|
||||
|
||||
-- Jouets & hobbies (1715)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEGO', 1715, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TOYS R US', 1715, 0);
|
||||
|
||||
-- Équipement sportif (1722)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MOUNTAIN EQUIPMENT', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LA CORDEE', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DECATHLON', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPORTS EXPERTS', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ATMOSPHERE', 1722, 0);
|
||||
|
||||
-- Parcs & activités (1723)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SEPAQ', 1723, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BLOC SHOP', 1723, 0);
|
||||
|
||||
-- Lecture (1741)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RENAUD-BRAY', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INDIGO', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARCHAMBAULT', 1741, 0);
|
||||
|
||||
-- Animaux — nourriture (1751)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MONDOU', 1751, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PET SMART', 1751, 0);
|
||||
|
||||
-- Alcool (1810)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAQ', 1810, 0);
|
||||
|
||||
-- Cannabis (1820)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SQDC', 1820, 0);
|
||||
|
||||
-- Frais bancaires (1911)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROGRAMME PERFORMANCE', 1911, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FRAIS MENSUELS', 1911, 0);
|
||||
|
||||
-- Impôts (1921, 1922)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GOUV. QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REVENU QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARC IMPOT', 1921, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRA TAX', 1921, 0);
|
||||
|
||||
-- Dons de charité (1931)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OXFAM', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CENTRAIDE', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FPA', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CROIX-ROUGE', 1931, 0);
|
||||
|
||||
-- Cotisations professionnelles (1932)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORDRE DES COMPTABL', 1932, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CPA CANADA', 1932, 0);
|
||||
|
||||
-- Cadeaux (1940)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DANS UN JARDIN', 1940, 0);
|
||||
|
||||
-- Divers (1946) — catch-all marketplace
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMAZON', 1946, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMZN', 1946, 0);
|
||||
|
||||
-- Placements (1964)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WS INVESTMENTS', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WEALTHSIMPLE', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PEAK INVESTMENT', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DYNAMIC FUND', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIDELITY', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AGF', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('QUESTRADE', 1964, 0);
|
||||
|
||||
-- Paie (1011)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAY/PAY', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPOT PAIE', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAYROLL', 1011, 0);
|
||||
764
src-tauri/src/database/fixtures/consolidated_v0.9.1.sql
Normal file
764
src-tauri/src/database/fixtures/consolidated_v0.9.1.sql
Normal file
|
|
@ -0,0 +1,764 @@
|
|||
-- Consolidated schema for new profile databases
|
||||
-- This file bakes in the base schema + all migrations (v3-v8) and pre-seeds
|
||||
-- the v1 IPC-aligned category taxonomy so that brand-new profiles immediately
|
||||
-- use the new standard. Existing profiles keep their v2 seed and are only
|
||||
-- tagged via the migration (categories_schema_version = 'v2').
|
||||
-- Used ONLY for initializing new profile databases (not for the default profile).
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_sources (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
column_mapping TEXT NOT NULL,
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS imported_files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
file_hash TEXT NOT NULL,
|
||||
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
row_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'completed',
|
||||
notes TEXT,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
||||
UNIQUE(source_id, filename)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT,
|
||||
icon TEXT,
|
||||
type TEXT NOT NULL DEFAULT 'expense',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_inputable INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
i18n_key TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
normalized_name TEXT NOT NULL,
|
||||
category_id INTEGER,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS keywords (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
keyword TEXT NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
UNIQUE(keyword, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS transactions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
category_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
source_id INTEGER,
|
||||
file_id INTEGER,
|
||||
original_description TEXT,
|
||||
notes TEXT,
|
||||
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
||||
is_split INTEGER NOT NULL DEFAULT 0,
|
||||
parent_transaction_id INTEGER,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
date DATE NOT NULL,
|
||||
is_recurring INTEGER NOT NULL DEFAULT 0,
|
||||
recurrence_rule TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
adjustment_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
description TEXT,
|
||||
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL,
|
||||
year INTEGER NOT NULL,
|
||||
month INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(category_id, year, month)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
template_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
amount REAL NOT NULL,
|
||||
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
||||
UNIQUE(template_id, category_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS import_config_templates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
delimiter TEXT NOT NULL DEFAULT ';',
|
||||
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
||||
date_format TEXT NOT NULL DEFAULT 'DD/MM/YYYY',
|
||||
skip_lines INTEGER NOT NULL DEFAULT 0,
|
||||
has_header INTEGER NOT NULL DEFAULT 1,
|
||||
column_mapping TEXT NOT NULL,
|
||||
amount_mode TEXT NOT NULL DEFAULT 'single',
|
||||
sign_convention TEXT NOT NULL DEFAULT 'negative_expense',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_preferences (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
||||
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
||||
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- Balance sheet (Bilan) — Migration v9 mirror for new profiles
|
||||
-- ============================================================================
|
||||
-- 5 tables + 7 indexes + seeded categories. Kept in sync with
|
||||
-- `balance_schema.sql` (the source of truth applied by Migration v9 in lib.rs).
|
||||
-- New profiles created from this consolidated schema get the balance feature
|
||||
-- preinstalled without needing to replay v9 separately.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key TEXT NOT NULL UNIQUE,
|
||||
i18n_key TEXT NOT NULL,
|
||||
kind TEXT NOT NULL CHECK(kind IN ('simple','priced')),
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_seed INTEGER NOT NULL DEFAULT 0,
|
||||
asset_type TEXT CHECK(asset_type IS NULL OR asset_type IN ('stock','crypto'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
balance_category_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT,
|
||||
currency TEXT NOT NULL DEFAULT 'CAD' CHECK(currency = 'CAD'),
|
||||
notes TEXT,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
archived_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (balance_category_id) REFERENCES balance_categories(id) ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshots (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_date DATE NOT NULL UNIQUE,
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_snapshot_lines (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
snapshot_id INTEGER NOT NULL,
|
||||
account_id INTEGER NOT NULL,
|
||||
quantity REAL,
|
||||
unit_price REAL,
|
||||
value REAL NOT NULL,
|
||||
price_source TEXT,
|
||||
price_fetched_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (snapshot_id) REFERENCES balance_snapshots(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE RESTRICT,
|
||||
UNIQUE(snapshot_id, account_id),
|
||||
CHECK (
|
||||
(quantity IS NULL AND unit_price IS NULL)
|
||||
OR (quantity IS NOT NULL AND unit_price IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS balance_account_transfers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL,
|
||||
transaction_id INTEGER NOT NULL,
|
||||
direction TEXT NOT NULL CHECK(direction IN ('in','out')),
|
||||
notes TEXT,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (account_id) REFERENCES balance_accounts(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (transaction_id) REFERENCES transactions(id) ON DELETE RESTRICT,
|
||||
UNIQUE(transaction_id, account_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_category ON balance_accounts(balance_category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_accounts_active ON balance_accounts(is_active) WHERE is_active = 1;
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_snapshot ON balance_snapshot_lines(snapshot_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshot_lines_account ON balance_snapshot_lines(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_account ON balance_account_transfers(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_account_transfers_transaction ON balance_account_transfers(transaction_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_balance_snapshots_date ON balance_snapshots(snapshot_date);
|
||||
|
||||
INSERT OR IGNORE INTO balance_categories (key, i18n_key, kind, sort_order, is_seed, asset_type) VALUES
|
||||
('cash', 'balance.category.cash', 'simple', 10, 1, NULL),
|
||||
('tfsa', 'balance.category.tfsa', 'simple', 20, 1, NULL),
|
||||
('rrsp', 'balance.category.rrsp', 'simple', 30, 1, NULL),
|
||||
('fund', 'balance.category.fund', 'simple', 40, 1, NULL),
|
||||
('other', 'balance.category.other', 'simple', 50, 1, NULL),
|
||||
('stock', 'balance.category.stock', 'priced', 60, 1, 'stock'),
|
||||
('crypto', 'balance.category.crypto', 'priced', 70, 1, 'crypto');
|
||||
|
||||
-- Starter accounts (Issue #179): 4 plain accounts seeded for new profiles so
|
||||
-- /balance lands non-empty. They are NOT marked as seed (no is_seed column on
|
||||
-- balance_accounts) — once created they are indistinguishable from
|
||||
-- user-created accounts and can be renamed/archived freely. Existing profiles
|
||||
-- get the same 4 proposed via StarterAccountsModal on first /balance visit.
|
||||
INSERT INTO balance_accounts (balance_category_id, name, currency, is_active) VALUES
|
||||
((SELECT id FROM balance_categories WHERE key = 'cash'), 'Compte chèque', 'CAD', 1),
|
||||
((SELECT id FROM balance_categories WHERE key = 'tfsa'), 'CELI', 'CAD', 1),
|
||||
((SELECT id FROM balance_categories WHERE key = 'rrsp'), 'REER', 'CAD', 1),
|
||||
((SELECT id FROM balance_categories WHERE key = 'other'), 'Compte non-enregistré', 'CAD', 1);
|
||||
|
||||
-- Default preferences (new profiles ship with the v1 IPC taxonomy)
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|
||||
INSERT OR REPLACE INTO user_preferences (key, value) VALUES ('categories_schema_version', 'v1');
|
||||
-- Suppress StarterAccountsModal on first /balance visit for new profiles
|
||||
-- (Issue #179). The 4 starter accounts are already seeded above, so the
|
||||
-- modal would only show 4 collision rows with no actionable choice. Pre-
|
||||
-- writing the pref skips that briefly-empty UX entirely. Suggestion S1
|
||||
-- from PR #185 review (#187).
|
||||
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('balance_starter_proposed', '{"shown_at":"seed","accepted":[]}');
|
||||
|
||||
-- ============================================================================
|
||||
-- Seed v1 — IPC Statistique Canada-aligned, 3 levels, Canada/Québec
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Reset any pre-existing category data (possible when tauri-plugin-sql runs
|
||||
-- the historical v2 seed migration on this fresh DB before this script
|
||||
-- executes). Keywords/categories are wiped and re-inserted with the v1 IDs
|
||||
-- (1000+ range) so existing references in migrations v3-v7 stay inert.
|
||||
-- ============================================================================
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- LEVEL 1 — Roots (9 IPC components + Revenus + Transferts)
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1000, 'Revenus', NULL, 'income', '#16a34a', 0, 1, 'categoriesSeed.revenus.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1100, 'Alimentation', NULL, 'expense', '#ea580c', 0, 2, 'categoriesSeed.alimentation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1200, 'Logement', NULL, 'expense', '#dc2626', 0, 3, 'categoriesSeed.logement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1300, 'Ménage & ameublement', NULL, 'expense', '#ca8a04', 0, 4, 'categoriesSeed.menage.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1400, 'Vêtements & chaussures', NULL, 'expense', '#d946ef', 0, 5, 'categoriesSeed.vetements.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1500, 'Transport', NULL, 'expense', '#2563eb', 0, 6, 'categoriesSeed.transport.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1600, 'Santé & soins personnels', NULL, 'expense', '#f43f5e', 0, 7, 'categoriesSeed.sante.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1700, 'Loisirs, formation & lecture', NULL, 'expense', '#8b5cf6', 0, 8, 'categoriesSeed.loisirs.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1800, 'Boissons, tabac & cannabis', NULL, 'expense', '#7c3aed', 0, 9, 'categoriesSeed.consommation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1900, 'Finances & obligations', NULL, 'expense', '#6b7280', 0, 10, 'categoriesSeed.finances.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1950, 'Transferts & placements', NULL, 'transfer', '#0ea5e9', 0, 11, 'categoriesSeed.transferts.root');
|
||||
|
||||
-- 1000 — Revenus
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1010, 'Emploi', 1000, 'income', '#22c55e', 0, 1, 'categoriesSeed.revenus.emploi.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1011, 'Paie régulière', 1010, 'income', '#22c55e', 1, 1, 'categoriesSeed.revenus.emploi.paie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1012, 'Primes & bonus', 1010, 'income', '#4ade80', 1, 2, 'categoriesSeed.revenus.emploi.primes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1013, 'Travail autonome', 1010, 'income', '#86efac', 1, 3, 'categoriesSeed.revenus.emploi.autonome');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1020, 'Gouvernemental', 1000, 'income', '#16a34a', 0, 2, 'categoriesSeed.revenus.gouvernemental.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1021, 'Remboursement impôt', 1020, 'income', '#16a34a', 1, 1, 'categoriesSeed.revenus.gouvernemental.remboursementImpot');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1022, 'Allocations familiales', 1020, 'income', '#15803d', 1, 2, 'categoriesSeed.revenus.gouvernemental.allocations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1023, 'Crédits TPS/TVQ', 1020, 'income', '#166534', 1, 3, 'categoriesSeed.revenus.gouvernemental.credits');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1024, 'Assurance-emploi / RQAP', 1020, 'income', '#14532d', 1, 4, 'categoriesSeed.revenus.gouvernemental.assuranceEmploi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1030, 'Revenus de placement', 1000, 'income', '#10b981', 0, 3, 'categoriesSeed.revenus.placement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1031, 'Intérêts & dividendes', 1030, 'income', '#10b981', 1, 1, 'categoriesSeed.revenus.placement.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1032, 'Gains en capital', 1030, 'income', '#059669', 1, 2, 'categoriesSeed.revenus.placement.capital');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1033, 'Revenus locatifs', 1030, 'income', '#047857', 1, 3, 'categoriesSeed.revenus.placement.locatifs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1090, 'Autres revenus', 1000, 'income', '#84cc16', 1, 9, 'categoriesSeed.revenus.autres');
|
||||
|
||||
-- 1100 — Alimentation
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1110, 'Épicerie & marché', 1100, 'expense', '#ea580c', 0, 1, 'categoriesSeed.alimentation.epicerie.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1111, 'Épicerie régulière', 1110, 'expense', '#ea580c', 1, 1, 'categoriesSeed.alimentation.epicerie.reguliere');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1112, 'Boucherie & poissonnerie', 1110, 'expense', '#c2410c', 1, 2, 'categoriesSeed.alimentation.epicerie.boucherie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1113, 'Boulangerie & pâtisserie', 1110, 'expense', '#9a3412', 1, 3, 'categoriesSeed.alimentation.epicerie.boulangerie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1114, 'Dépanneur', 1110, 'expense', '#7c2d12', 1, 4, 'categoriesSeed.alimentation.epicerie.depanneur');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1115, 'Marché & produits spécialisés', 1110, 'expense', '#fb923c', 1, 5, 'categoriesSeed.alimentation.epicerie.marche');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1120, 'Restauration', 1100, 'expense', '#f97316', 0, 2, 'categoriesSeed.alimentation.restauration.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1121, 'Restaurant', 1120, 'expense', '#f97316', 1, 1, 'categoriesSeed.alimentation.restauration.restaurant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1122, 'Café & boulangerie rapide', 1120, 'expense', '#fb923c', 1, 2, 'categoriesSeed.alimentation.restauration.cafe');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1123, 'Restauration rapide', 1120, 'expense', '#fdba74', 1, 3, 'categoriesSeed.alimentation.restauration.fastfood');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1124, 'Livraison à domicile', 1120, 'expense', '#fed7aa', 1, 4, 'categoriesSeed.alimentation.restauration.livraison');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1125, 'Cantine & cafétéria', 1120, 'expense', '#ffedd5', 1, 5, 'categoriesSeed.alimentation.restauration.cantine');
|
||||
|
||||
-- 1200 — Logement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1210, 'Habitation principale', 1200, 'expense', '#dc2626', 0, 1, 'categoriesSeed.logement.habitation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1211, 'Loyer', 1210, 'expense', '#dc2626', 1, 1, 'categoriesSeed.logement.habitation.loyer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1212, 'Hypothèque', 1210, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.logement.habitation.hypotheque');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1213, 'Taxes municipales & scolaires', 1210, 'expense', '#991b1b', 1, 3, 'categoriesSeed.logement.habitation.taxes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1214, 'Charges de copropriété', 1210, 'expense', '#7f1d1d', 1, 4, 'categoriesSeed.logement.habitation.copropriete');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1220, 'Services publics', 1200, 'expense', '#ef4444', 0, 2, 'categoriesSeed.logement.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1221, 'Électricité', 1220, 'expense', '#ef4444', 1, 1, 'categoriesSeed.logement.services.electricite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1222, 'Gaz naturel', 1220, 'expense', '#f87171', 1, 2, 'categoriesSeed.logement.services.gaz');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1223, 'Chauffage (mazout, propane)', 1220, 'expense', '#fca5a5', 1, 3, 'categoriesSeed.logement.services.chauffage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1224, 'Eau & égouts', 1220, 'expense', '#fecaca', 1, 4, 'categoriesSeed.logement.services.eau');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1230, 'Communications', 1200, 'expense', '#6366f1', 0, 3, 'categoriesSeed.logement.communications.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1231, 'Internet résidentiel', 1230, 'expense', '#6366f1', 1, 1, 'categoriesSeed.logement.communications.internet');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1232, 'Téléphonie mobile', 1230, 'expense', '#818cf8', 1, 2, 'categoriesSeed.logement.communications.mobile');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1233, 'Téléphonie résidentielle', 1230, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.logement.communications.residentielle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1234, 'Câblodistribution & streaming TV', 1230, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.logement.communications.streamingTv');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1240, 'Entretien & réparations', 1200, 'expense', '#e11d48', 0, 4, 'categoriesSeed.logement.entretien.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1241, 'Entretien général', 1240, 'expense', '#e11d48', 1, 1, 'categoriesSeed.logement.entretien.general');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1242, 'Rénovations', 1240, 'expense', '#be123c', 1, 2, 'categoriesSeed.logement.entretien.renovations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1243, 'Matériaux & outils', 1240, 'expense', '#9f1239', 1, 3, 'categoriesSeed.logement.entretien.materiaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1244, 'Aménagement paysager', 1240, 'expense', '#881337', 1, 4, 'categoriesSeed.logement.entretien.paysager');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1250, 'Assurance habitation', 1200, 'expense', '#14b8a6', 1, 5, 'categoriesSeed.logement.assurance');
|
||||
|
||||
-- 1300 — Ménage & ameublement
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1310, 'Ameublement', 1300, 'expense', '#ca8a04', 0, 1, 'categoriesSeed.menage.ameublement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1311, 'Meubles', 1310, 'expense', '#ca8a04', 1, 1, 'categoriesSeed.menage.ameublement.meubles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1312, 'Électroménagers', 1310, 'expense', '#a16207', 1, 2, 'categoriesSeed.menage.ameublement.electromenagers');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1313, 'Décoration', 1310, 'expense', '#854d0e', 1, 3, 'categoriesSeed.menage.ameublement.decoration');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1320, 'Fournitures ménagères', 1300, 'expense', '#eab308', 0, 2, 'categoriesSeed.menage.fournitures.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1321, 'Produits d''entretien', 1320, 'expense', '#eab308', 1, 1, 'categoriesSeed.menage.fournitures.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1322, 'Literie & linge de maison', 1320, 'expense', '#facc15', 1, 2, 'categoriesSeed.menage.fournitures.literie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1323, 'Vaisselle & ustensiles', 1320, 'expense', '#fde047', 1, 3, 'categoriesSeed.menage.fournitures.vaisselle');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1330, 'Services domestiques', 1300, 'expense', '#fbbf24', 0, 3, 'categoriesSeed.menage.services.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1331, 'Ménage & nettoyage', 1330, 'expense', '#fbbf24', 1, 1, 'categoriesSeed.menage.services.nettoyage');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1332, 'Buanderie & pressing', 1330, 'expense', '#fcd34d', 1, 2, 'categoriesSeed.menage.services.buanderie');
|
||||
|
||||
-- 1400 — Vêtements & chaussures
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1410, 'Vêtements adultes', 1400, 'expense', '#d946ef', 1, 1, 'categoriesSeed.vetements.adultes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1420, 'Vêtements enfants', 1400, 'expense', '#c026d3', 1, 2, 'categoriesSeed.vetements.enfants');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1430, 'Chaussures', 1400, 'expense', '#a21caf', 1, 3, 'categoriesSeed.vetements.chaussures');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1440, 'Accessoires & bijoux', 1400, 'expense', '#86198f', 1, 4, 'categoriesSeed.vetements.accessoires');
|
||||
|
||||
-- 1500 — Transport
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1510, 'Véhicule personnel', 1500, 'expense', '#2563eb', 0, 1, 'categoriesSeed.transport.vehicule.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1511, 'Achat / location véhicule', 1510, 'expense', '#2563eb', 1, 1, 'categoriesSeed.transport.vehicule.achat');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1512, 'Essence', 1510, 'expense', '#1d4ed8', 1, 2, 'categoriesSeed.transport.vehicule.essence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1513, 'Entretien & réparations auto', 1510, 'expense', '#1e40af', 1, 3, 'categoriesSeed.transport.vehicule.entretien');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1514, 'Immatriculation & permis', 1510, 'expense', '#1e3a8a', 1, 4, 'categoriesSeed.transport.vehicule.immatriculation');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1515, 'Stationnement & péages', 1510, 'expense', '#3b82f6', 1, 5, 'categoriesSeed.transport.vehicule.stationnement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1516, 'Assurance auto', 1510, 'expense', '#60a5fa', 1, 6, 'categoriesSeed.transport.vehicule.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1520, 'Transport public', 1500, 'expense', '#0ea5e9', 0, 2, 'categoriesSeed.transport.public.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1521, 'Autobus & métro', 1520, 'expense', '#0ea5e9', 1, 1, 'categoriesSeed.transport.public.autobus');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1522, 'Train de banlieue', 1520, 'expense', '#0284c7', 1, 2, 'categoriesSeed.transport.public.train');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1523, 'Taxi & covoiturage', 1520, 'expense', '#0369a1', 1, 3, 'categoriesSeed.transport.public.taxi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1530, 'Voyages longue distance', 1500, 'expense', '#38bdf8', 0, 3, 'categoriesSeed.transport.voyages.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1531, 'Avion', 1530, 'expense', '#38bdf8', 1, 1, 'categoriesSeed.transport.voyages.avion');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1532, 'Train & autocar', 1530, 'expense', '#7dd3fc', 1, 2, 'categoriesSeed.transport.voyages.trainAutocar');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1533, 'Hébergement', 1530, 'expense', '#bae6fd', 1, 3, 'categoriesSeed.transport.voyages.hebergement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1534, 'Location véhicule voyage', 1530, 'expense', '#e0f2fe', 1, 4, 'categoriesSeed.transport.voyages.location');
|
||||
|
||||
-- 1600 — Santé & soins personnels
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1610, 'Soins médicaux', 1600, 'expense', '#f43f5e', 0, 1, 'categoriesSeed.sante.medicaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1611, 'Pharmacie', 1610, 'expense', '#f43f5e', 1, 1, 'categoriesSeed.sante.medicaux.pharmacie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1612, 'Consultations médicales', 1610, 'expense', '#e11d48', 1, 2, 'categoriesSeed.sante.medicaux.consultations');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1613, 'Dentiste & orthodontiste', 1610, 'expense', '#be123c', 1, 3, 'categoriesSeed.sante.medicaux.dentiste');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1614, 'Optométrie & lunettes', 1610, 'expense', '#9f1239', 1, 4, 'categoriesSeed.sante.medicaux.optometrie');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1615, 'Thérapies (physio, psycho, etc.)', 1610, 'expense', '#881337', 1, 5, 'categoriesSeed.sante.medicaux.therapies');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1616, 'Assurance santé complémentaire', 1610, 'expense', '#fb7185', 1, 6, 'categoriesSeed.sante.medicaux.assurance');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1620, 'Soins personnels', 1600, 'expense', '#fb7185', 0, 2, 'categoriesSeed.sante.personnels.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1621, 'Coiffure & esthétique', 1620, 'expense', '#fb7185', 1, 1, 'categoriesSeed.sante.personnels.coiffure');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1622, 'Produits de soins corporels', 1620, 'expense', '#fda4af', 1, 2, 'categoriesSeed.sante.personnels.soins');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1630, 'Assurance vie & invalidité', 1600, 'expense', '#14b8a6', 1, 3, 'categoriesSeed.sante.assuranceVie');
|
||||
|
||||
-- 1700 — Loisirs, formation & lecture
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1710, 'Divertissement', 1700, 'expense', '#8b5cf6', 0, 1, 'categoriesSeed.loisirs.divertissement.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1711, 'Cinéma & spectacles', 1710, 'expense', '#8b5cf6', 1, 1, 'categoriesSeed.loisirs.divertissement.cinema');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1712, 'Jeux vidéo & consoles', 1710, 'expense', '#a78bfa', 1, 2, 'categoriesSeed.loisirs.divertissement.jeux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1713, 'Streaming vidéo', 1710, 'expense', '#c4b5fd', 1, 3, 'categoriesSeed.loisirs.divertissement.streamingVideo');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1714, 'Streaming musique & audio', 1710, 'expense', '#ddd6fe', 1, 4, 'categoriesSeed.loisirs.divertissement.streamingMusique');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1715, 'Jouets & passe-temps', 1710, 'expense', '#ede9fe', 1, 5, 'categoriesSeed.loisirs.divertissement.jouets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1720, 'Sports & plein air', 1700, 'expense', '#22c55e', 0, 2, 'categoriesSeed.loisirs.sports.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1721, 'Abonnements sportifs', 1720, 'expense', '#22c55e', 1, 1, 'categoriesSeed.loisirs.sports.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1722, 'Équipement sportif', 1720, 'expense', '#4ade80', 1, 2, 'categoriesSeed.loisirs.sports.equipement');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1723, 'Parcs & activités plein air', 1720, 'expense', '#86efac', 1, 3, 'categoriesSeed.loisirs.sports.parcs');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1730, 'Formation & éducation', 1700, 'expense', '#6366f1', 0, 3, 'categoriesSeed.loisirs.formation.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1731, 'Scolarité (frais)', 1730, 'expense', '#6366f1', 1, 1, 'categoriesSeed.loisirs.formation.scolarite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1732, 'Matériel scolaire', 1730, 'expense', '#818cf8', 1, 2, 'categoriesSeed.loisirs.formation.materiel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1733, 'Cours & certifications', 1730, 'expense', '#a5b4fc', 1, 3, 'categoriesSeed.loisirs.formation.cours');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1734, 'Abonnements professionnels', 1730, 'expense', '#c7d2fe', 1, 4, 'categoriesSeed.loisirs.formation.abonnements');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1740, 'Lecture & médias', 1700, 'expense', '#ec4899', 0, 4, 'categoriesSeed.loisirs.lecture.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1741, 'Livres', 1740, 'expense', '#ec4899', 1, 1, 'categoriesSeed.loisirs.lecture.livres');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1742, 'Journaux & magazines', 1740, 'expense', '#f472b6', 1, 2, 'categoriesSeed.loisirs.lecture.journaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1750, 'Animaux de compagnie', 1700, 'expense', '#a855f7', 0, 5, 'categoriesSeed.loisirs.animaux.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1751, 'Nourriture & accessoires animaux', 1750, 'expense', '#a855f7', 1, 1, 'categoriesSeed.loisirs.animaux.nourriture');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1752, 'Vétérinaire', 1750, 'expense', '#c084fc', 1, 2, 'categoriesSeed.loisirs.animaux.veterinaire');
|
||||
|
||||
-- 1800 — Boissons, tabac & cannabis
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1810, 'Alcool (SAQ, microbrasseries)', 1800, 'expense', '#7c3aed', 1, 1, 'categoriesSeed.consommation.alcool');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1820, 'Cannabis (SQDC)', 1800, 'expense', '#6d28d9', 1, 2, 'categoriesSeed.consommation.cannabis');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1830, 'Tabac', 1800, 'expense', '#5b21b6', 1, 3, 'categoriesSeed.consommation.tabac');
|
||||
|
||||
-- 1900 — Finances & obligations
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1910, 'Frais bancaires', 1900, 'expense', '#6b7280', 0, 1, 'categoriesSeed.finances.fraisBancaires.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1911, 'Frais de compte', 1910, 'expense', '#6b7280', 1, 1, 'categoriesSeed.finances.fraisBancaires.compte');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1912, 'Intérêts & frais de crédit', 1910, 'expense', '#9ca3af', 1, 2, 'categoriesSeed.finances.fraisBancaires.interets');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1913, 'Frais de change', 1910, 'expense', '#d1d5db', 1, 3, 'categoriesSeed.finances.fraisBancaires.change');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1920, 'Impôts & taxes', 1900, 'expense', '#dc2626', 0, 2, 'categoriesSeed.finances.impots.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1921, 'Impôt fédéral', 1920, 'expense', '#dc2626', 1, 1, 'categoriesSeed.finances.impots.federal');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1922, 'Impôt provincial', 1920, 'expense', '#b91c1c', 1, 2, 'categoriesSeed.finances.impots.provincial');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1923, 'Acomptes provisionnels', 1920, 'expense', '#991b1b', 1, 3, 'categoriesSeed.finances.impots.acomptes');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1930, 'Dons & cotisations', 1900, 'expense', '#ec4899', 0, 3, 'categoriesSeed.finances.dons.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1931, 'Dons de charité', 1930, 'expense', '#ec4899', 1, 1, 'categoriesSeed.finances.dons.charite');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1932, 'Cotisations professionnelles', 1930, 'expense', '#f472b6', 1, 2, 'categoriesSeed.finances.dons.professionnelles');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1933, 'Cotisations syndicales', 1930, 'expense', '#f9a8d4', 1, 3, 'categoriesSeed.finances.dons.syndicales');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1940, 'Cadeaux', 1900, 'expense', '#f43f5e', 1, 4, 'categoriesSeed.finances.cadeaux');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1945, 'Retrait cash', 1900, 'expense', '#57534e', 1, 5, 'categoriesSeed.finances.cash');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1946, 'Achats divers non catégorisés', 1900, 'expense', '#78716c', 1, 6, 'categoriesSeed.finances.divers');
|
||||
|
||||
-- 1950 — Transferts & placements
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1960, 'Épargne & placements', 1950, 'transfer', '#0ea5e9', 0, 1, 'categoriesSeed.transferts.epargne.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1961, 'REER / RRSP', 1960, 'transfer', '#0ea5e9', 1, 1, 'categoriesSeed.transferts.epargne.reer');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1962, 'CELI / TFSA', 1960, 'transfer', '#0284c7', 1, 2, 'categoriesSeed.transferts.epargne.celi');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1963, 'REEE / RESP', 1960, 'transfer', '#0369a1', 1, 3, 'categoriesSeed.transferts.epargne.reee');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1964, 'Compte non-enregistré', 1960, 'transfer', '#075985', 1, 4, 'categoriesSeed.transferts.epargne.nonEnregistre');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1965, 'Fonds d''urgence', 1960, 'transfer', '#0c4a6e', 1, 5, 'categoriesSeed.transferts.epargne.urgence');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1970, 'Remboursement de dette', 1950, 'transfer', '#7c3aed', 0, 2, 'categoriesSeed.transferts.dette.root');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1971, 'Paiement carte crédit', 1970, 'transfer', '#7c3aed', 1, 1, 'categoriesSeed.transferts.dette.carteCredit');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1972, 'Remboursement prêt étudiant', 1970, 'transfer', '#8b5cf6', 1, 2, 'categoriesSeed.transferts.dette.etudiant');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1973, 'Remboursement prêt perso', 1970, 'transfer', '#a78bfa', 1, 3, 'categoriesSeed.transferts.dette.personnel');
|
||||
INSERT INTO categories (id, name, parent_id, type, color, is_inputable, sort_order, i18n_key) VALUES (1980, 'Transferts internes', 1950, 'transfer', '#64748b', 1, 3, 'categoriesSeed.transferts.internes');
|
||||
|
||||
-- ============================================================================
|
||||
-- Keywords — Canadian suppliers (150+ entries)
|
||||
-- ============================================================================
|
||||
|
||||
-- Alimentation > Épicerie régulière (1111)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('METRO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IGA', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MAXI', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUPER C', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LOBLAWS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROVIGO', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ADONIS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WHOLE FOODS', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AVRIL', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RACHELLE-BERY', 1111, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COSTCO', 1111, 50);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WALMART', 1111, 50);
|
||||
|
||||
-- Épicerie > Boucherie (1112)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCHERIE', 1112, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('POISSONNERIE', 1112, 0);
|
||||
|
||||
-- Épicerie > Boulangerie (1113)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOULANGERIE', 1113, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PATISSERIE', 1113, 0);
|
||||
|
||||
-- Épicerie > Dépanneur (1114)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPANNEUR', 1114, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('7-ELEVEN', 1114, 0);
|
||||
|
||||
-- Restauration > Restaurant (1121)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RESTAURANT', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRASSERIE', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BISTRO', 1121, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUSHI', 1121, 0);
|
||||
|
||||
-- Restauration > Café (1122)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STARBUCKS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIM HORTONS', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SECOND CUP', 1122, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VAN HOUTTE', 1122, 0);
|
||||
|
||||
-- Restauration > Fast food (1123)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MCDONALD', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SUBWAY', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('A&W', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BURGER KING', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KFC', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOMINOS', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PIZZA HUT', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELLE PROVINCE', 1123, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ST-HUBERT', 1123, 0);
|
||||
|
||||
-- Restauration > Livraison (1124)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DD/DOORDASH', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER EATS', 1124, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SKIPTHEDISHES', 1124, 0);
|
||||
|
||||
-- Logement > Hypothèque (1212)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MTG/HYP', 1212, 0);
|
||||
|
||||
-- Logement > Taxes municipales (1213)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('M-ST-HILAIRE TX', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXES MUNICIPALES', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CSS PATRIOT', 1213, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXE SCOLAIRE', 1213, 0);
|
||||
|
||||
-- Électricité (1221)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO-QUEBEC', 1221, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HYDRO QUEBEC', 1221, 0);
|
||||
|
||||
-- Gaz (1222)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ENERGIR', 1222, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAZ METRO', 1222, 0);
|
||||
|
||||
-- Internet (1231)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIDEOTRON', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL INTERNET', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORICOM', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COGECO', 1231, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EBOX', 1231, 0);
|
||||
|
||||
-- Mobile (1232)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIZZ', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('KOODO', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PUBLIC MOBILE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('VIRGIN', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELL MOBILITE', 1232, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TELUS MOBILE', 1232, 0);
|
||||
|
||||
-- Entretien maison (1241)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('IKEA', 1241, 0);
|
||||
|
||||
-- Matériaux & outils (1243)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANADIAN TIRE', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CANAC', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RONA', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HOME DEPOT', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BMR', 1243, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRINCESS AUTO', 1243, 0);
|
||||
|
||||
-- Assurance habitation (1250)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BELAIR', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRYSM', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INTACT ASSURANCE', 1250, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DESJARDINS ASSURANCE', 1250, 0);
|
||||
|
||||
-- Meubles (1311)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TANGUAY', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEON', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STRUCTUBE', 1311, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BRICK', 1311, 0);
|
||||
|
||||
-- Électroménagers (1312)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BEST BUY', 1312, 0);
|
||||
|
||||
-- Décoration (1313)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOUCLAIR', 1313, 0);
|
||||
|
||||
-- Vêtements (1410)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIQLO', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WINNERS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SIMONS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARKS', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('H&M', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OLD NAVY', 1410, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GAP', 1410, 0);
|
||||
|
||||
-- Transport — Essence (1512)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SHELL', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ESSO', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ULTRAMAR', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO-CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PETRO CANADA', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CREVIER', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HARNOIS', 1512, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('COUCHE-TARD ESSENCE', 1512, 10);
|
||||
|
||||
-- Permis / SAAQ (1514)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAAQ', 1514, 0);
|
||||
|
||||
-- Transport public — autobus/métro (1521)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STM', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RTC', 1521, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STL', 1521, 0);
|
||||
|
||||
-- Train de banlieue (1522)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE MONT-SAINT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE SAINT-HUBERT', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GARE CENTRALE', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EXO', 1522, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REM', 1522, 0);
|
||||
|
||||
-- Taxi / Uber (1523)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UBER', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LYFT', 1523, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TAXI', 1523, 0);
|
||||
|
||||
-- Avion (1531)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR CANADA', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WESTJET', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIR TRANSAT', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PORTER', 1531, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AEROPORTS DE MONTREAL', 1531, 0);
|
||||
|
||||
-- Hébergement (1533)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AIRBNB', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('HILTON', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MARRIOTT', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BOOKING.COM', 1533, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NORWEGIAN CRUISE', 1533, 0);
|
||||
|
||||
-- Pharmacie (1611)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('JEAN COUTU', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FAMILIPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHARMAPRIX', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROXIM', 1611, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('UNIPRIX', 1611, 0);
|
||||
|
||||
-- Thérapies (1615)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PHYSIOACTIF', 1615, 0);
|
||||
|
||||
-- Cinéma & spectacles (1711)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEPLEX', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CINEMA DU PARC', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TICKETMASTER', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CLUB SODA', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEPOINTDEVENTE', 1711, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('EVENBRITE', 1711, 0);
|
||||
|
||||
-- Jeux vidéo (1712)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('STEAMGAMES', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PLAYSTATION', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NINTENDO', 1712, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('XBOX', 1712, 0);
|
||||
|
||||
-- Streaming vidéo (1713)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('NETFLIX', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PRIMEVIDEO', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DISNEY PLUS', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRAVE', 1713, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE TV', 1713, 0);
|
||||
|
||||
-- Streaming musique (1714)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPOTIFY', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('APPLE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('YOUTUBE MUSIC', 1714, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TIDAL', 1714, 0);
|
||||
|
||||
-- Jouets & hobbies (1715)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LEGO', 1715, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('TOYS R US', 1715, 0);
|
||||
|
||||
-- Équipement sportif (1722)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MOUNTAIN EQUIPMENT', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('LA CORDEE', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DECATHLON', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SPORTS EXPERTS', 1722, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ATMOSPHERE', 1722, 0);
|
||||
|
||||
-- Parcs & activités (1723)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SEPAQ', 1723, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('BLOC SHOP', 1723, 0);
|
||||
|
||||
-- Lecture (1741)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('RENAUD-BRAY', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('INDIGO', 1741, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARCHAMBAULT', 1741, 0);
|
||||
|
||||
-- Animaux — nourriture (1751)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('MONDOU', 1751, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PET SMART', 1751, 0);
|
||||
|
||||
-- Alcool (1810)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SAQ', 1810, 0);
|
||||
|
||||
-- Cannabis (1820)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('SQDC', 1820, 0);
|
||||
|
||||
-- Frais bancaires (1911)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PROGRAMME PERFORMANCE', 1911, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FRAIS MENSUELS', 1911, 0);
|
||||
|
||||
-- Impôts (1921, 1922)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('GOUV. QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('REVENU QUEBEC', 1922, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ARC IMPOT', 1921, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CRA TAX', 1921, 0);
|
||||
|
||||
-- Dons de charité (1931)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('OXFAM', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CENTRAIDE', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FPA', 1931, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CROIX-ROUGE', 1931, 0);
|
||||
|
||||
-- Cotisations professionnelles (1932)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('ORDRE DES COMPTABL', 1932, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('CPA CANADA', 1932, 0);
|
||||
|
||||
-- Cadeaux (1940)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DANS UN JARDIN', 1940, 0);
|
||||
|
||||
-- Divers (1946) — catch-all marketplace
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMAZON', 1946, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AMZN', 1946, 0);
|
||||
|
||||
-- Placements (1964)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WS INVESTMENTS', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('WEALTHSIMPLE', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PEAK INVESTMENT', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DYNAMIC FUND', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('FIDELITY', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('AGF', 1964, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('QUESTRADE', 1964, 0);
|
||||
|
||||
-- Paie (1011)
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAY/PAY', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('DEPOT PAIE', 1011, 0);
|
||||
INSERT INTO keywords (keyword, category_id, priority) VALUES ('PAYROLL', 1011, 0);
|
||||
232
src-tauri/src/database/fixtures/seed_v0.3.0.sql
Normal file
232
src-tauri/src/database/fixtures/seed_v0.3.0.sql
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
-- Migration v2: Seed categories and keywords from SommaireDepense.csv
|
||||
|
||||
-- Clear existing data (FK order: keywords -> categories)
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- ==========================================
|
||||
-- Parent categories (Regroupement level)
|
||||
-- ==========================================
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (1, 'Revenus', 'income', 1);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (2, 'Dépenses récurrentes', 'expense', 2);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (3, 'Dépenses ponctuelles', 'expense', 3);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (4, 'Maison', 'expense', 4);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (5, 'Placements', 'transfer', 5);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (6, 'Autres', 'expense', 6);
|
||||
|
||||
-- ==========================================
|
||||
-- Child categories
|
||||
-- ==========================================
|
||||
|
||||
-- Revenus children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (10, 'Paie', 1, 'income', '#22c55e', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (11, 'Autres revenus', 1, 'income', '#4ade80', 2);
|
||||
|
||||
-- Dépenses récurrentes children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (20, 'Loyer', 2, 'expense', '#ef4444', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (21, 'Électricité', 2, 'expense', '#f59e0b', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (22, 'Épicerie', 2, 'expense', '#10b981', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (23, 'Dons', 2, 'expense', '#ec4899', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (24, 'Restaurant', 2, 'expense', '#f97316', 5);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (25, 'Frais bancaires', 2, 'expense', '#6b7280', 6);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (26, 'Jeux, Films & Livres', 2, 'expense', '#8b5cf6', 7);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (27, 'Abonnements Musique', 2, 'expense', '#06b6d4', 8);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (28, 'Transport en commun', 2, 'expense', '#3b82f6', 9);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (29, 'Internet & Télécom', 2, 'expense', '#6366f1', 10);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (30, 'Animaux', 2, 'expense', '#a855f7', 11);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (31, 'Assurances', 2, 'expense', '#14b8a6', 12);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (32, 'Pharmacie', 2, 'expense', '#f43f5e', 13);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (33, 'Taxes municipales', 2, 'expense', '#78716c', 14);
|
||||
|
||||
-- Dépenses ponctuelles children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (40, 'Voiture', 3, 'expense', '#64748b', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (41, 'Amazon', 3, 'expense', '#f59e0b', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (42, 'Électroniques', 3, 'expense', '#3b82f6', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (43, 'Alcool', 3, 'expense', '#7c3aed', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (44, 'Cadeaux', 3, 'expense', '#ec4899', 5);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (45, 'Vêtements', 3, 'expense', '#d946ef', 6);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (46, 'CPA', 3, 'expense', '#0ea5e9', 7);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (47, 'Voyage', 3, 'expense', '#f97316', 8);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (48, 'Sports & Plein air', 3, 'expense', '#22c55e', 9);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (49, 'Spectacles & sorties', 3, 'expense', '#e11d48', 10);
|
||||
|
||||
-- Maison children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (50, 'Hypothèque', 4, 'expense', '#dc2626', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (51, 'Achats maison', 4, 'expense', '#ea580c', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (52, 'Entretien maison', 4, 'expense', '#ca8a04', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (53, 'Électroménagers & Meubles', 4, 'expense', '#0d9488', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (54, 'Outils', 4, 'expense', '#b45309', 5);
|
||||
|
||||
-- Placements children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (60, 'Placements', 5, 'transfer', '#2563eb', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (61, 'Transferts', 5, 'transfer', '#7c3aed', 2);
|
||||
|
||||
-- Autres children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (70, 'Impôts', 6, 'expense', '#dc2626', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (71, 'Paiement CC', 6, 'transfer', '#6b7280', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (72, 'Retrait cash', 6, 'expense', '#57534e', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (73, 'Projets', 6, 'expense', '#0ea5e9', 4);
|
||||
|
||||
-- ==========================================
|
||||
-- Keywords
|
||||
-- ==========================================
|
||||
|
||||
-- Paie (10)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PAY/PAY', 10);
|
||||
|
||||
-- Électricité (21)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HYDRO-QUEBEC', 21);
|
||||
|
||||
-- Épicerie (22)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('METRO', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('IGA', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MAXI', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUPER C', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOUCHERIE LAFLECHE', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOULANGERIE JARRY', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOLLARAMA', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WALMART', 22);
|
||||
|
||||
-- Dons (23)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('OXFAM', 23);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CENTRAIDE', 23);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FPA', 23);
|
||||
|
||||
-- Restaurant (24)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUBWAY', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MCDONALD', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('A&W', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DD/DOORDASH', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOORDASH', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUSHI', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOMINOS', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BELLE PROVINCE', 24);
|
||||
|
||||
-- Frais bancaires (25)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PROGRAMME PERFORMANCE', 25);
|
||||
|
||||
-- Jeux, Films & Livres (26)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('STEAMGAMES', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PLAYSTATION', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRIMEVIDEO', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NINTENDO', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('RENAUD-BRAY', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CINEMA DU PARC', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LEGO', 26);
|
||||
|
||||
-- Abonnements Musique (27)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SPOTIFY', 27);
|
||||
|
||||
-- Transport en commun (28)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('STM', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE MONT-SAINT', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE SAINT-HUBERT', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE CENTRALE', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('REM', 28);
|
||||
|
||||
-- Internet & Télécom (29)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('VIDEOTRON', 29);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ORICOM', 29);
|
||||
|
||||
-- Animaux (30)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MONDOU', 30);
|
||||
|
||||
-- Assurances (31)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BELAIR', 31);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRYSM', 31);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('INS/ASS', 31);
|
||||
|
||||
-- Pharmacie (32)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('JEAN COUTU', 32);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FAMILIPRIX', 32);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PHARMAPRIX', 32);
|
||||
|
||||
-- Taxes municipales (33)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('M-ST-HILAIRE TX', 33);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CSS PATRIOT', 33);
|
||||
|
||||
-- Voiture (40)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SHELL', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ESSO', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ULTRAMAR', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PETRO-CANADA', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SAAQ', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CREVIER', 40);
|
||||
|
||||
-- Amazon (41)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AMAZON', 41);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AMZN', 41);
|
||||
|
||||
-- Électroniques (42)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MICROSOFT', 42);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ADDISON ELECTRONIQUE', 42);
|
||||
|
||||
-- Alcool (43)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SAQ', 43);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SQDC', 43);
|
||||
|
||||
-- Cadeaux (44)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DANS UN JARDIN', 44);
|
||||
|
||||
-- Vêtements (45)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('UNIQLO', 45);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WINNERS', 45);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SIMONS', 45);
|
||||
|
||||
-- CPA (46)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ORDRE DES COMPTABL', 46);
|
||||
|
||||
-- Voyage (47)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NORWEGIAN CRUISE', 47);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AEROPORTS DE MONTREAL', 47);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HILTON', 47);
|
||||
|
||||
-- Sports & Plein air (48)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BLOC SHOP', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SEPAQ', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LA CORDEE', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MOUNTAIN EQUIPMENT', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PHYSIOACTIF', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DECATHLON', 48);
|
||||
|
||||
-- Spectacles & sorties (49)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('TICKETMASTER', 49);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CLUB SODA', 49);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LEPOINTDEVENTE', 49);
|
||||
|
||||
-- Hypothèque (50)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MTG/HYP', 50);
|
||||
|
||||
-- Achats maison (51)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CANADIAN TIRE', 51);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CANAC', 51);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('RONA', 51);
|
||||
|
||||
-- Entretien maison (52)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('IKEA', 52);
|
||||
|
||||
-- Électroménagers & Meubles (53)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('TANGUAY', 53);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOUCLAIR', 53);
|
||||
|
||||
-- Outils (54)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BMR', 54);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HOME DEPOT', 54);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRINCESS AUTO', 54);
|
||||
|
||||
-- Placements (60)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DYNAMIC FUND', 60);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FIDELITY', 60);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AGF', 60);
|
||||
|
||||
-- Transferts (61)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WS INVESTMENTS', 61);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PEAK INVESTMENT', 61);
|
||||
|
||||
-- Impôts (70)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GOUV. QUEBEC', 70);
|
||||
|
||||
-- Projets (73)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CLAUDE.AI', 73);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NAME-CHEAP', 73);
|
||||
241
src-tauri/src/database/fixtures/seed_v0.4.0.sql
Normal file
241
src-tauri/src/database/fixtures/seed_v0.4.0.sql
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
-- Migration v2: Seed categories and keywords from SommaireDepense.csv
|
||||
|
||||
-- Clear existing data (FK order: keywords -> categories)
|
||||
DELETE FROM keywords;
|
||||
UPDATE transactions SET category_id = NULL;
|
||||
DELETE FROM categories;
|
||||
|
||||
-- ==========================================
|
||||
-- Parent categories (Regroupement level)
|
||||
-- ==========================================
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (1, 'Revenus', 'income', 1);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (2, 'Dépenses récurrentes', 'expense', 2);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (3, 'Dépenses ponctuelles', 'expense', 3);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (4, 'Maison', 'expense', 4);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (5, 'Placements', 'transfer', 5);
|
||||
INSERT INTO categories (id, name, type, sort_order) VALUES (6, 'Autres', 'expense', 6);
|
||||
|
||||
-- ==========================================
|
||||
-- Child categories
|
||||
-- ==========================================
|
||||
|
||||
-- Revenus children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (10, 'Paie', 1, 'income', '#22c55e', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (11, 'Autres revenus', 1, 'income', '#4ade80', 2);
|
||||
|
||||
-- Dépenses récurrentes children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (20, 'Loyer', 2, 'expense', '#ef4444', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (21, 'Électricité', 2, 'expense', '#f59e0b', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (22, 'Épicerie', 2, 'expense', '#10b981', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (23, 'Dons', 2, 'expense', '#ec4899', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (24, 'Restaurant', 2, 'expense', '#f97316', 5);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (25, 'Frais bancaires', 2, 'expense', '#6b7280', 6);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (26, 'Jeux, Films & Livres', 2, 'expense', '#8b5cf6', 7);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (27, 'Abonnements Musique', 2, 'expense', '#06b6d4', 8);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (28, 'Transport en commun', 2, 'expense', '#3b82f6', 9);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (29, 'Internet & Télécom', 2, 'expense', '#6366f1', 10);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (30, 'Animaux', 2, 'expense', '#a855f7', 11);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order, is_inputable) VALUES (31, 'Assurances', 2, 'expense', '#14b8a6', 12, 0);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (32, 'Pharmacie', 2, 'expense', '#f43f5e', 13);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (33, 'Taxes municipales', 2, 'expense', '#78716c', 14);
|
||||
|
||||
-- Dépenses ponctuelles children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (40, 'Voiture', 3, 'expense', '#64748b', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (41, 'Amazon', 3, 'expense', '#f59e0b', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (42, 'Électroniques', 3, 'expense', '#3b82f6', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (43, 'Alcool', 3, 'expense', '#7c3aed', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (44, 'Cadeaux', 3, 'expense', '#ec4899', 5);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (45, 'Vêtements', 3, 'expense', '#d946ef', 6);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (46, 'CPA', 3, 'expense', '#0ea5e9', 7);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (47, 'Voyage', 3, 'expense', '#f97316', 8);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (48, 'Sports & Plein air', 3, 'expense', '#22c55e', 9);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (49, 'Spectacles & sorties', 3, 'expense', '#e11d48', 10);
|
||||
|
||||
-- Maison children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (50, 'Hypothèque', 4, 'expense', '#dc2626', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (51, 'Achats maison', 4, 'expense', '#ea580c', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (52, 'Entretien maison', 4, 'expense', '#ca8a04', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (53, 'Électroménagers & Meubles', 4, 'expense', '#0d9488', 4);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (54, 'Outils', 4, 'expense', '#b45309', 5);
|
||||
|
||||
-- Placements children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (60, 'Placements', 5, 'transfer', '#2563eb', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (61, 'Transferts', 5, 'transfer', '#7c3aed', 2);
|
||||
|
||||
-- Autres children
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (70, 'Impôts', 6, 'expense', '#dc2626', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (71, 'Paiement CC', 6, 'transfer', '#6b7280', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (72, 'Retrait cash', 6, 'expense', '#57534e', 3);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (73, 'Projets', 6, 'expense', '#0ea5e9', 4);
|
||||
|
||||
-- ==========================================
|
||||
-- Grandchild categories (Level 3 — under Assurances)
|
||||
-- ==========================================
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (310, 'Assurance-auto', 31, 'expense', '#14b8a6', 1);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (311, 'Assurance-habitation', 31, 'expense', '#0d9488', 2);
|
||||
INSERT INTO categories (id, name, parent_id, type, color, sort_order) VALUES (312, 'Assurance-vie', 31, 'expense', '#0f766e', 3);
|
||||
|
||||
-- ==========================================
|
||||
-- Keywords
|
||||
-- ==========================================
|
||||
|
||||
-- Paie (10)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PAY/PAY', 10);
|
||||
|
||||
-- Électricité (21)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HYDRO-QUEBEC', 21);
|
||||
|
||||
-- Épicerie (22)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('METRO', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('IGA', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MAXI', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUPER C', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOUCHERIE LAFLECHE', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOULANGERIE JARRY', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOLLARAMA', 22);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WALMART', 22);
|
||||
|
||||
-- Dons (23)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('OXFAM', 23);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CENTRAIDE', 23);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FPA', 23);
|
||||
|
||||
-- Restaurant (24)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUBWAY', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MCDONALD', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('A&W', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DD/DOORDASH', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOORDASH', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SUSHI', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DOMINOS', 24);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BELLE PROVINCE', 24);
|
||||
|
||||
-- Frais bancaires (25)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PROGRAMME PERFORMANCE', 25);
|
||||
|
||||
-- Jeux, Films & Livres (26)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('STEAMGAMES', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PLAYSTATION', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRIMEVIDEO', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NINTENDO', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('RENAUD-BRAY', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CINEMA DU PARC', 26);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LEGO', 26);
|
||||
|
||||
-- Abonnements Musique (27)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SPOTIFY', 27);
|
||||
|
||||
-- Transport en commun (28)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('STM', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE MONT-SAINT', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE SAINT-HUBERT', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GARE CENTRALE', 28);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('REM', 28);
|
||||
|
||||
-- Internet & Télécom (29)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('VIDEOTRON', 29);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ORICOM', 29);
|
||||
|
||||
-- Animaux (30)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MONDOU', 30);
|
||||
|
||||
-- Assurance-auto (310)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BELAIR', 310);
|
||||
-- Assurance-habitation (311)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRYSM', 311);
|
||||
-- Assurance-vie (312)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('INS/ASS', 312);
|
||||
|
||||
-- Pharmacie (32)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('JEAN COUTU', 32);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FAMILIPRIX', 32);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PHARMAPRIX', 32);
|
||||
|
||||
-- Taxes municipales (33)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('M-ST-HILAIRE TX', 33);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CSS PATRIOT', 33);
|
||||
|
||||
-- Voiture (40)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SHELL', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ESSO', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ULTRAMAR', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PETRO-CANADA', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SAAQ', 40);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CREVIER', 40);
|
||||
|
||||
-- Amazon (41)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AMAZON', 41);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AMZN', 41);
|
||||
|
||||
-- Électroniques (42)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MICROSOFT', 42);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ADDISON ELECTRONIQUE', 42);
|
||||
|
||||
-- Alcool (43)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SAQ', 43);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SQDC', 43);
|
||||
|
||||
-- Cadeaux (44)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DANS UN JARDIN', 44);
|
||||
|
||||
-- Vêtements (45)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('UNIQLO', 45);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WINNERS', 45);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SIMONS', 45);
|
||||
|
||||
-- CPA (46)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('ORDRE DES COMPTABL', 46);
|
||||
|
||||
-- Voyage (47)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NORWEGIAN CRUISE', 47);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AEROPORTS DE MONTREAL', 47);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HILTON', 47);
|
||||
|
||||
-- Sports & Plein air (48)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BLOC SHOP', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('SEPAQ', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LA CORDEE', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MOUNTAIN EQUIPMENT', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PHYSIOACTIF', 48);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DECATHLON', 48);
|
||||
|
||||
-- Spectacles & sorties (49)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('TICKETMASTER', 49);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CLUB SODA', 49);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('LEPOINTDEVENTE', 49);
|
||||
|
||||
-- Hypothèque (50)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('MTG/HYP', 50);
|
||||
|
||||
-- Achats maison (51)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CANADIAN TIRE', 51);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CANAC', 51);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('RONA', 51);
|
||||
|
||||
-- Entretien maison (52)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('IKEA', 52);
|
||||
|
||||
-- Électroménagers & Meubles (53)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('TANGUAY', 53);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BOUCLAIR', 53);
|
||||
|
||||
-- Outils (54)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('BMR', 54);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('HOME DEPOT', 54);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PRINCESS AUTO', 54);
|
||||
|
||||
-- Placements (60)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('DYNAMIC FUND', 60);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('FIDELITY', 60);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('AGF', 60);
|
||||
|
||||
-- Transferts (61)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('WS INVESTMENTS', 61);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('PEAK INVESTMENT', 61);
|
||||
|
||||
-- Impôts (70)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('GOUV. QUEBEC', 70);
|
||||
|
||||
-- Projets (73)
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('CLAUDE.AI', 73);
|
||||
INSERT INTO keywords (keyword, category_id) VALUES ('NAME-CHEAP', 73);
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
pub mod profile_db;
|
||||
|
||||
pub const SCHEMA: &str = include_str!("schema.sql");
|
||||
pub const SEED_CATEGORIES: &str = include_str!("seed_categories.sql");
|
||||
pub const CONSOLIDATED_SCHEMA: &str = include_str!("consolidated_schema.sql");
|
||||
pub const BALANCE_SCHEMA: &str = include_str!("balance_schema.sql");
|
||||
pub const BALANCE_HOLDINGS_SCHEMA: &str = include_str!("balance_holdings_schema.sql");
|
||||
|
||||
/// File name of the default profile's database: the only one tauri-plugin-sql
|
||||
/// migrates itself (`add_migrations` in lib.rs).
|
||||
pub const DEFAULT_PROFILE_DB: &str = "simpl_resultat.db";
|
||||
|
|
|
|||
1479
src-tauri/src/database/profile_db.rs
Normal file
1479
src-tauri/src/database/profile_db.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,9 +6,12 @@ use tauri::{Emitter, Manager};
|
|||
use tauri_plugin_deep_link::DeepLinkExt;
|
||||
use tauri_plugin_sql::{Migration, MigrationKind};
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let migrations = vec![
|
||||
/// Every migration, in order. tauri-plugin-sql applies them to the default
|
||||
/// profile on load; `database::profile_db` catches the secondary profiles up
|
||||
/// with the same list (#390). The SQL bytes are checksummed by sqlx and pinned
|
||||
/// by a test: never edit an existing entry, append a new version.
|
||||
pub(crate) fn migrations() -> Vec<Migration> {
|
||||
vec![
|
||||
Migration {
|
||||
version: 1,
|
||||
description: "create initial schema",
|
||||
|
|
@ -365,7 +368,12 @@ pub fn run() {
|
|||
WHERE column_mapping LIKE '%debitAmount%';",
|
||||
kind: MigrationKind::Up,
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let migrations = migrations();
|
||||
|
||||
tauri::Builder::default()
|
||||
// Single-instance plugin MUST be registered first. With the `deep-link`
|
||||
|
|
@ -429,7 +437,7 @@ pub fn run() {
|
|||
})
|
||||
.plugin(
|
||||
tauri_plugin_sql::Builder::default()
|
||||
.add_migrations("sqlite:simpl_resultat.db", migrations)
|
||||
.add_migrations(&format!("sqlite:{}", database::DEFAULT_PROFILE_DB), migrations)
|
||||
.build(),
|
||||
)
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
|
|
@ -452,6 +460,7 @@ pub fn run() {
|
|||
commands::hash_pin,
|
||||
commands::verify_pin,
|
||||
commands::repair_migrations,
|
||||
commands::prepare_profile_db,
|
||||
commands::validate_license_key,
|
||||
commands::store_license,
|
||||
commands::remove_license,
|
||||
|
|
@ -3867,12 +3876,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn consolidated_schema_matches_v17_chain_on_import_sources_at_parity() {
|
||||
// The consolidated schema is the tested reference definition for new
|
||||
// profiles. Without this test the DEFAULT or the CHECK of the four v17
|
||||
// columns could drift between the two definitions unnoticed — the
|
||||
// columns are inert on the production path (this script runs after every
|
||||
// migration and only uses CREATE TABLE IF NOT EXISTS), so nothing else
|
||||
// would surface the divergence.
|
||||
// The consolidated schema is the definition a secondary profile is
|
||||
// created with: tauri-plugin-sql runs no migration on its database
|
||||
// (#390). Without this test the DEFAULT or the CHECK of the four v17
|
||||
// columns could drift between the two definitions unnoticed.
|
||||
let chain = db_pre_v17();
|
||||
chain.execute_batch(V17_SQL).expect("apply v17");
|
||||
let consolidated = consolidated_db();
|
||||
|
|
|
|||
|
|
@ -874,7 +874,9 @@
|
|||
"tips": [
|
||||
"A default profile is automatically created on first launch",
|
||||
"The PIN is requested each time you access a protected profile",
|
||||
"Deleting a profile permanently removes all its data — this action cannot be undone"
|
||||
"Deleting a profile permanently removes all its data — this action cannot be undone",
|
||||
"When you open a profile created by an earlier version, the app updates its database after keeping a copy in the migration-backups folder, next to the databases (on Linux ~/.config/com.simpl.resultat/, on Windows %APPDATA%\\com.simpl.resultat\\). The copy is deleted with the profile",
|
||||
"On Linux, versions up to 0.17.0 left a deleted profile's database on disk (~/.config/com.simpl.resultat/profile_….db); you can delete that file by hand"
|
||||
]
|
||||
},
|
||||
"dashboard": {
|
||||
|
|
|
|||
|
|
@ -874,7 +874,9 @@
|
|||
"tips": [
|
||||
"Un profil par défaut est créé automatiquement au premier lancement",
|
||||
"Le NIP est demandé à chaque fois que vous accédez à un profil protégé",
|
||||
"La suppression d'un profil supprime définitivement toutes ses données — cette action est irréversible"
|
||||
"La suppression d'un profil supprime définitivement toutes ses données — cette action est irréversible",
|
||||
"À l'ouverture d'un profil créé par une version antérieure, l'application met sa base à jour après en avoir gardé une copie dans le dossier migration-backups, à côté des bases (sous Linux ~/.config/com.simpl.resultat/, sous Windows %APPDATA%\\com.simpl.resultat\\). La copie est supprimée avec le profil",
|
||||
"Sous Linux, les versions jusqu'à la 0.17.0 laissaient sur le disque la base d'un profil supprimé (~/.config/com.simpl.resultat/profile_….db) ; vous pouvez supprimer ce fichier à la main"
|
||||
]
|
||||
},
|
||||
"dashboard": {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import {
|
|||
importCategoriesOnly,
|
||||
importTransactionsOnly,
|
||||
importTransactionsWithCategories,
|
||||
parseImportedCsv,
|
||||
parseImportedJson,
|
||||
serializeToJson,
|
||||
validateImportedFormatRows,
|
||||
|
|
@ -728,3 +729,36 @@ describe("the refusal messages are translated (#331)", () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 5. The manual-categorization flag (#390)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("a restore writes the manual flag as an integer (#390)", () => {
|
||||
// A backup exported while the Transactions page bound the JS boolean carries
|
||||
// the text "true"; written back as is, the checklist's `= 1` misses it.
|
||||
const fromTheBug = { ...transactionFixture(1), is_manually_categorized: "true" as unknown as number };
|
||||
|
||||
it("restores the 'true' of an older JSON backup as 1", async () => {
|
||||
await importTransactionsWithCategories(
|
||||
envelopeData({ transactions: [fromTheBug, transactionFixture(2)] }),
|
||||
"backup.json"
|
||||
);
|
||||
expect(db.tables.transactions.map((t) => t.is_manually_categorized)).toEqual([1, 0]);
|
||||
});
|
||||
|
||||
it("does the same in transactions_only mode", async () => {
|
||||
await importTransactionsOnly(envelopeData({ transactions: [fromTheBug] }), "backup.json");
|
||||
expect(db.tables.transactions[0].is_manually_categorized).toBe(1);
|
||||
});
|
||||
|
||||
it("reads the flag of a CSV export, 'true' included", () => {
|
||||
const csv =
|
||||
"date,description,amount,is_manually_categorized,is_split\n" +
|
||||
"2026-01-01,a,-1,true,0\n" +
|
||||
"2026-01-02,b,-2,1,0\n" +
|
||||
"2026-01-03,c,-3,0,0\n";
|
||||
const { transactions } = parseImportedCsv(csv);
|
||||
expect(transactions.map((t) => t.is_manually_categorized)).toEqual([1, 1, 0]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type Database from "@tauri-apps/plugin-sql";
|
||||
import { getDb, withTransaction } from "./db";
|
||||
import Papa from "papaparse";
|
||||
import { toSqlFlag } from "../utils/sqlFlag";
|
||||
import type {
|
||||
Category,
|
||||
ImportConfigTemplate,
|
||||
|
|
@ -360,7 +361,8 @@ export function parseImportedCsv(content: string): {
|
|||
category_name: row.category_name || null,
|
||||
original_description: row.original_description || null,
|
||||
notes: row.notes || null,
|
||||
is_manually_categorized: parseInt(row.is_manually_categorized) || 0,
|
||||
// An export from the time of #390 carries "true" in this column.
|
||||
is_manually_categorized: toSqlFlag(row.is_manually_categorized),
|
||||
is_split: parseInt(row.is_split) || 0,
|
||||
parent_transaction_id: row.parent_transaction_id
|
||||
? parseInt(row.parent_transaction_id)
|
||||
|
|
@ -638,7 +640,8 @@ async function attachTransactions(
|
|||
tx.category_id,
|
||||
tx.original_description,
|
||||
tx.notes,
|
||||
tx.is_manually_categorized,
|
||||
// A JSON backup from the time of #390 carries the text "true".
|
||||
toSqlFlag(tx.is_manually_categorized),
|
||||
tx.is_split,
|
||||
tx.parent_transaction_id,
|
||||
sourceId,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
|||
// Ordered log of every fake-db operation's start/end, shared with the fake db.
|
||||
const events: string[] = [];
|
||||
// Hoisted handle so the (hoisted) vi.mock factory can reach the per-test db.
|
||||
const h = vi.hoisted(() => ({ fakeDb: null as unknown as FakeDb }));
|
||||
const h = vi.hoisted(() => ({
|
||||
fakeDb: null as unknown as FakeDb,
|
||||
// What `prepare_profile_db` answers (#390); a test may make it throw.
|
||||
prepare: async (): Promise<unknown> => null,
|
||||
}));
|
||||
|
||||
interface FakeDb {
|
||||
execute: (q: string, p?: unknown[]) => Promise<{ rowsAffected: number }>;
|
||||
|
|
@ -23,9 +27,21 @@ interface FakeDb {
|
|||
vi.mock("@tauri-apps/plugin-sql", () => ({
|
||||
default: { load: vi.fn(async () => h.fakeDb) },
|
||||
}));
|
||||
vi.mock("@tauri-apps/api/core", () => ({ invoke: vi.fn(async () => false) }));
|
||||
vi.mock("@tauri-apps/api/core", () => ({
|
||||
invoke: vi.fn(async (command: string) => (command === "prepare_profile_db" ? h.prepare() : false)),
|
||||
}));
|
||||
vi.mock("./logService", () => ({ logInfo: vi.fn(), logError: vi.fn() }));
|
||||
|
||||
import { connectToProfile, getDb, withTransaction } from "./db";
|
||||
import Database from "@tauri-apps/plugin-sql";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { logError, logInfo } from "./logService";
|
||||
import {
|
||||
connectToProfile,
|
||||
describePreparation,
|
||||
getDb,
|
||||
withTransaction,
|
||||
type ProfilePreparation,
|
||||
} from "./db";
|
||||
|
||||
// Each op records start, yields a real macrotask (a window for interleaving if
|
||||
// the lock were broken), then records end. The lock must keep them ordered.
|
||||
|
|
@ -50,6 +66,7 @@ function makeFakeDb(): FakeDb {
|
|||
beforeEach(async () => {
|
||||
events.length = 0;
|
||||
h.fakeDb = makeFakeDb();
|
||||
h.prepare = async () => null;
|
||||
await connectToProfile("test.db");
|
||||
});
|
||||
|
||||
|
|
@ -121,3 +138,123 @@ describe("db serialization (database-locked fix)", () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Profile preparation (#390)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function report(overrides: Partial<ProfilePreparation> = {}): ProfilePreparation {
|
||||
return { catch_up: null, catch_up_error: null, repaired_flags: 0, elapsed_ms: 12, ...overrides };
|
||||
}
|
||||
|
||||
function catchUp(overrides: Partial<NonNullable<ProfilePreparation["catch_up"]>> = {}) {
|
||||
return {
|
||||
floor: 6,
|
||||
recorded: [],
|
||||
applied: [],
|
||||
fk_repaired: [],
|
||||
fk_violations: [],
|
||||
backup_file: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("a profile is prepared before the plugin opens it (#390)", () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(invoke).mockClear();
|
||||
vi.mocked(Database.load).mockClear();
|
||||
vi.mocked(logInfo).mockClear();
|
||||
vi.mocked(logError).mockClear();
|
||||
});
|
||||
|
||||
it("prepares after the checksum repair and before Database.load", async () => {
|
||||
await connectToProfile("profile_0a1b2c3d.db");
|
||||
|
||||
const invoked = vi.mocked(invoke).mock;
|
||||
expect(invoked.calls.map((call) => call[0])).toEqual(["repair_migrations", "prepare_profile_db"]);
|
||||
expect(invoked.calls[1][1]).toEqual({ dbFilename: "profile_0a1b2c3d.db" });
|
||||
expect(invoked.invocationCallOrder[1]).toBeLessThan(
|
||||
vi.mocked(Database.load).mock.invocationCallOrder[0]
|
||||
);
|
||||
});
|
||||
|
||||
it("opens the database only once the preparation has finished", async () => {
|
||||
// In production the command runs on the main thread while Database.load
|
||||
// is asynchronous: started early, the two would overlap on the same file.
|
||||
let finish: (report: ProfilePreparation | null) => void = () => {};
|
||||
h.prepare = () =>
|
||||
new Promise((resolve) => {
|
||||
finish = resolve;
|
||||
});
|
||||
|
||||
const connecting = connectToProfile("profile_0a1b2c3d.db");
|
||||
await vi.waitFor(() =>
|
||||
expect(invoke).toHaveBeenCalledWith("prepare_profile_db", { dbFilename: "profile_0a1b2c3d.db" })
|
||||
);
|
||||
// Give a load started too early every chance to show up.
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
expect(Database.load).not.toHaveBeenCalled();
|
||||
|
||||
finish(null);
|
||||
await connecting;
|
||||
expect(Database.load).toHaveBeenCalledWith("sqlite:profile_0a1b2c3d.db");
|
||||
});
|
||||
|
||||
it("still opens the profile when the preparation fails, and says so in the Journal", async () => {
|
||||
h.prepare = async () => {
|
||||
throw "invalid_profile_db_filename";
|
||||
};
|
||||
|
||||
await connectToProfile("profile_0a1b2c3d.db");
|
||||
|
||||
expect(Database.load).toHaveBeenCalledWith("sqlite:profile_0a1b2c3d.db");
|
||||
expect(logError).toHaveBeenCalledWith(
|
||||
"Profile profile_0a1b2c3d.db: database preparation failed: invalid_profile_db_filename"
|
||||
);
|
||||
});
|
||||
|
||||
it("writes what changed to the Journal", async () => {
|
||||
h.prepare = async () =>
|
||||
report({
|
||||
catch_up: catchUp({ applied: [7, 8, 17], backup_file: "profile_0a1b2c3d-before-v7.db" }),
|
||||
repaired_flags: 2,
|
||||
});
|
||||
|
||||
await connectToProfile("profile_0a1b2c3d.db");
|
||||
|
||||
expect(vi.mocked(logInfo).mock.calls.map((call) => call[0])).toEqual([
|
||||
"Profile profile_0a1b2c3d.db: database updated with versions 7 to 17 in 12 ms, copy of the previous state kept as profile_0a1b2c3d-before-v7.db",
|
||||
"Profile profile_0a1b2c3d.db: 2 manual categorization flag(s) repaired",
|
||||
]);
|
||||
expect(logError).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("describePreparation (#390)", () => {
|
||||
it("says nothing when nothing changed", () => {
|
||||
expect(describePreparation("x.db", report({ catch_up: catchUp() }))).toEqual({ info: [], errors: [] });
|
||||
});
|
||||
|
||||
it("tolerates a missing report", () => {
|
||||
expect(describePreparation("x.db", null)).toEqual({ info: [], errors: [] });
|
||||
expect(describePreparation("x.db", false as never)).toEqual({ info: [], errors: [] });
|
||||
});
|
||||
|
||||
it("notes a history written without any update", () => {
|
||||
const lines = describePreparation("x.db", report({ catch_up: catchUp({ recorded: [1, 2, 17] }) }));
|
||||
expect(lines.info).toEqual(["Profile x.db: migration history recorded up to version 17"]);
|
||||
});
|
||||
|
||||
it("names the rows a version detached from a missing parent", () => {
|
||||
const lines = describePreparation(
|
||||
"x.db",
|
||||
report({ catch_up: catchUp({ applied: [7], fk_repaired: [["categories", 3]] }) })
|
||||
);
|
||||
expect(lines.info).toContain("Profile x.db: 3 row(s) of categories detached from a missing parent");
|
||||
});
|
||||
|
||||
it("reports a stopped catch-up as an error", () => {
|
||||
const lines = describePreparation("x.db", report({ catch_up_error: "migration_failed:v12: boom" }));
|
||||
expect(lines.errors).toEqual(["Profile x.db: database update stopped: migration_failed:v12: boom"]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import Database from "@tauri-apps/plugin-sql";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { logError, logInfo } from "./logService";
|
||||
|
||||
let rawInstance: Database | null = null;
|
||||
let serializedInstance: Database | null = null;
|
||||
|
|
@ -103,6 +104,61 @@ export async function withTransaction<T>(
|
|||
});
|
||||
}
|
||||
|
||||
/** What `prepare_profile_db` did to one profile database (#390). */
|
||||
export interface ProfilePreparation {
|
||||
catch_up: {
|
||||
floor: number | null;
|
||||
recorded: number[];
|
||||
applied: number[];
|
||||
fk_repaired: Array<[string, number]>;
|
||||
fk_violations: Array<[string, number]>;
|
||||
backup_file: string | null;
|
||||
} | null;
|
||||
catch_up_error: string | null;
|
||||
repaired_flags: number;
|
||||
elapsed_ms: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Journal lines for one preparation: only what changed. Names files, never
|
||||
* folders: an error line can be attached to a feedback report, and the
|
||||
* folder holds the OS user name.
|
||||
*/
|
||||
export function describePreparation(
|
||||
dbFilename: string,
|
||||
report: ProfilePreparation | null | undefined
|
||||
): { info: string[]; errors: string[] } {
|
||||
const info: string[] = [];
|
||||
const errors: string[] = [];
|
||||
if (!report || typeof report !== "object") return { info, errors };
|
||||
const catchUp = report.catch_up;
|
||||
if (catchUp && catchUp.applied.length > 0) {
|
||||
const first = catchUp.applied[0];
|
||||
const last = catchUp.applied[catchUp.applied.length - 1];
|
||||
info.push(
|
||||
`Profile ${dbFilename}: database updated with versions ${first} to ${last} in ${report.elapsed_ms} ms` +
|
||||
(catchUp.backup_file ? `, copy of the previous state kept as ${catchUp.backup_file}` : "")
|
||||
);
|
||||
} else if (catchUp && catchUp.recorded.length > 0) {
|
||||
info.push(
|
||||
`Profile ${dbFilename}: migration history recorded up to version ${catchUp.recorded[catchUp.recorded.length - 1]}`
|
||||
);
|
||||
}
|
||||
for (const [table, rows] of catchUp?.fk_repaired ?? []) {
|
||||
info.push(`Profile ${dbFilename}: ${rows} row(s) of ${table} detached from a missing parent`);
|
||||
}
|
||||
for (const [table, rows] of catchUp?.fk_violations ?? []) {
|
||||
info.push(`Profile ${dbFilename}: ${rows} row(s) of ${table} point to a missing row`);
|
||||
}
|
||||
if (report.catch_up_error) {
|
||||
errors.push(`Profile ${dbFilename}: database update stopped: ${report.catch_up_error}`);
|
||||
}
|
||||
if (report.repaired_flags > 0) {
|
||||
info.push(`Profile ${dbFilename}: ${report.repaired_flags} manual categorization flag(s) repaired`);
|
||||
}
|
||||
return { info, errors };
|
||||
}
|
||||
|
||||
export async function connectToProfile(dbFilename: string): Promise<void> {
|
||||
if (rawInstance) {
|
||||
await rawInstance.close();
|
||||
|
|
@ -118,6 +174,19 @@ export async function connectToProfile(dbFilename: string): Promise<void> {
|
|||
} catch (e) {
|
||||
console.error("Migration repair failed:", e);
|
||||
}
|
||||
// Catch a secondary profile up on the migrations tauri-plugin-sql never
|
||||
// runs for it, and repair legacy values in every profile (#390). Fails
|
||||
// open, like the repair above: the profile still opens.
|
||||
try {
|
||||
const report = await invoke<ProfilePreparation>("prepare_profile_db", { dbFilename });
|
||||
const lines = describePreparation(dbFilename, report);
|
||||
lines.info.forEach((line) => logInfo(line));
|
||||
lines.errors.forEach((line) => logError(line));
|
||||
} catch (e) {
|
||||
logError(
|
||||
`Profile ${dbFilename}: database preparation failed: ${e instanceof Error ? e.message : String(e)}`
|
||||
);
|
||||
}
|
||||
rawInstance = await Database.load(`sqlite:${dbFilename}`);
|
||||
serializedInstance = serialize(rawInstance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ vi.mock("./db", () => {
|
|||
});
|
||||
|
||||
import { getDb } from "./db";
|
||||
import { getTransactionCount } from "./transactionService";
|
||||
import { getTransactionCount, updateTransactionCategory } from "./transactionService";
|
||||
|
||||
const mockSelect = vi.fn();
|
||||
const mockExecute = vi.fn();
|
||||
|
|
@ -41,3 +41,22 @@ describe("getTransactionCount (#351)", () => {
|
|||
await expect(getTransactionCount()).resolves.toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("updateTransactionCategory (#390)", () => {
|
||||
// tauri-plugin-sql stores a bound JS boolean as the TEXT 'true', which the
|
||||
// getting-started checklist's `is_manually_categorized = 1` never matches.
|
||||
it("binds the manual flag as the integer 1, never as a boolean", async () => {
|
||||
mockExecute.mockResolvedValueOnce({ rowsAffected: 1 });
|
||||
await updateTransactionCategory(5, 12, true);
|
||||
expect(mockExecute).toHaveBeenCalledTimes(1);
|
||||
const params = mockExecute.mock.calls[0][1] as unknown[];
|
||||
expect(params).toEqual([12, 1, 5]);
|
||||
expect(typeof params[1]).toBe("number");
|
||||
});
|
||||
|
||||
it("binds 0 when the category is not set by hand", async () => {
|
||||
mockExecute.mockResolvedValueOnce({ rowsAffected: 1 });
|
||||
await updateTransactionCategory(5, null, false);
|
||||
expect(mockExecute.mock.calls[0][1]).toEqual([null, 0, 5]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
isLinkedTransactionFkError,
|
||||
type LinkedTransferTooltipRow,
|
||||
} from "./balance.service";
|
||||
import { toSqlFlag } from "../utils/sqlFlag";
|
||||
import type {
|
||||
Transaction,
|
||||
TransactionRow,
|
||||
|
|
@ -299,9 +300,11 @@ export async function updateTransactionCategory(
|
|||
isManual: boolean
|
||||
): Promise<void> {
|
||||
const db = await getDb();
|
||||
// Never bind the boolean itself: tauri-plugin-sql would store the TEXT
|
||||
// 'true', which `is_manually_categorized = 1` never matches (#390).
|
||||
await db.execute(
|
||||
`UPDATE transactions SET category_id = $1, is_manually_categorized = $2, updated_at = CURRENT_TIMESTAMP WHERE id = $3`,
|
||||
[categoryId, isManual, txId]
|
||||
[categoryId, toSqlFlag(isManual), txId]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
49
src/utils/sqlFlag.test.ts
Normal file
49
src/utils/sqlFlag.test.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { describe, it, expect } from "vitest";
|
||||
import { toSqlFlag } from "./sqlFlag";
|
||||
|
||||
describe("toSqlFlag (#390)", () => {
|
||||
it("maps the UI boolean to an integer, never to the boolean itself", () => {
|
||||
expect(toSqlFlag(true)).toBe(1);
|
||||
expect(toSqlFlag(false)).toBe(0);
|
||||
});
|
||||
|
||||
it("keeps database integers", () => {
|
||||
expect(toSqlFlag(1)).toBe(1);
|
||||
expect(toSqlFlag(0)).toBe(0);
|
||||
});
|
||||
|
||||
it("treats any finite non-zero number as set, like SQLite", () => {
|
||||
expect(toSqlFlag(2)).toBe(1);
|
||||
expect(toSqlFlag(-1)).toBe(1);
|
||||
});
|
||||
|
||||
it("maps NaN and infinities to 0", () => {
|
||||
expect(toSqlFlag(Number.NaN)).toBe(0);
|
||||
expect(toSqlFlag(Number.POSITIVE_INFINITY)).toBe(0);
|
||||
});
|
||||
|
||||
it("reads the 'true' a backup carries from the time of the bug", () => {
|
||||
expect(toSqlFlag("true")).toBe(1);
|
||||
expect(toSqlFlag("TRUE")).toBe(1);
|
||||
expect(toSqlFlag(" true ")).toBe(1);
|
||||
});
|
||||
|
||||
it("reads a CSV cell", () => {
|
||||
expect(toSqlFlag("1")).toBe(1);
|
||||
expect(toSqlFlag(" 1 ")).toBe(1);
|
||||
expect(toSqlFlag("0")).toBe(0);
|
||||
expect(toSqlFlag("")).toBe(0);
|
||||
});
|
||||
|
||||
it("maps every other string to 0", () => {
|
||||
expect(toSqlFlag("false")).toBe(0);
|
||||
expect(toSqlFlag("yes")).toBe(0);
|
||||
expect(toSqlFlag("01")).toBe(0);
|
||||
});
|
||||
|
||||
it("maps absent values to 0", () => {
|
||||
expect(toSqlFlag(null)).toBe(0);
|
||||
expect(toSqlFlag(undefined)).toBe(0);
|
||||
expect(toSqlFlag({})).toBe(0);
|
||||
});
|
||||
});
|
||||
22
src/utils/sqlFlag.ts
Normal file
22
src/utils/sqlFlag.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Turn any truthy-looking value into the integer SQLite expects for a 0/1
|
||||
* flag column (#390).
|
||||
*
|
||||
* Never bind a JS boolean through tauri-plugin-sql: the plugin only special-
|
||||
* cases null, strings and numbers, so `true` reaches sqlx as a JSON value and
|
||||
* is stored as the TEXT `'true'`. An INTEGER column keeps that text (it is not
|
||||
* a number), and `WHERE flag = 1` never matches it.
|
||||
*
|
||||
* Accepts what a flag can look like on the way in: a boolean from the UI, a
|
||||
* number from the database, or a string from a backup (`"1"`, or `"true"` in a
|
||||
* backup exported while the bug stood).
|
||||
*/
|
||||
export function toSqlFlag(value: unknown): 0 | 1 {
|
||||
if (value === true) return 1;
|
||||
if (typeof value === "number") return Number.isFinite(value) && value !== 0 ? 1 : 0;
|
||||
if (typeof value === "string") {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
return normalized === "1" || normalized === "true" ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue