feat(balance): SnapshotEditPage + simple-kind editor (#146) #148
4 changed files with 78 additions and 4 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
## [Non publié]
|
## [Non publié]
|
||||||
|
|
||||||
### Ajouté
|
### Ajouté
|
||||||
|
- **Bilan — éditeur de snapshot (type simple)** (route `/balance/snapshot`) : deuxième tranche de la feature *Bilan*. La nouvelle page permet de créer ou modifier un snapshot daté de votre patrimoine : choisissez une date (par défaut aujourd'hui), saisissez la valeur de chaque compte actif groupé par catégorie, puis enregistrez. Le mode est piloté par le paramètre `?date=` de l'URL — si un snapshot existe déjà à cette date, la page bascule automatiquement en mode édition (la contrainte UNIQUE sur `balance_snapshots.snapshot_date` garantit un snapshot par jour). La date d'un snapshot existant est immuable : pour la changer, supprimez puis recréez. Un bouton *Pré-remplir depuis le précédent* copie les valeurs du snapshot antérieur le plus récent (comptes simples uniquement — les comptes cotés seront pris en charge quand l'éditeur coté arrivera). Un bouton *Supprimer* affiche une modal de double confirmation qui exige de retaper la date du snapshot avant d'activer l'action destructive. Seules les valeurs de type simple sont acceptées à ce stade (`quantity` et `unit_price` sont laissés `NULL`) ; l'éditeur coté (quantité × prix unitaire + récupération de prix) arrivera dans une prochaine version. Nouveau hook `useSnapshotEditor` (`useReducer` couvrant tout le cycle de vie) et deux nouveaux composants `SnapshotEditor` + `SnapshotLineRow`. i18n FR/EN sous `balance.snapshot.*` (#146)
|
||||||
- **Bilan — fondations du schéma et page Comptes** (route `/balance/accounts`) : première tranche de la nouvelle feature *Bilan*. La migration SQL v9 introduit 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) avec 7 index et seede 7 catégories standard — Encaisse, CELI, REER, Fonds commun, Autre (type simple) + Action et Cryptomonnaie (type coté). La colonne `currency` est verrouillée à `CAD` via une contrainte CHECK au MVP — le support multi-devises arrivera plus tard. La nouvelle page expose deux onglets : *Comptes* (CRUD complet sur les comptes de l'utilisateur, archivage soft plutôt que suppression dure pour préserver les snapshots historiques) et *Catégories* (renommer une catégorie, créer des catégories de type simple, supprimer celles créées par l'utilisateur — les catégories standard sont protégées). Couverture i18n FR/EN complète sous `balance.*`. Snapshots, transferts, rendements et price-fetching premium arriveront dans les prochaines issues ; pour l'instant la route est accessible directement par URL (pas encore d'entrée sidebar) (#138)
|
- **Bilan — fondations du schéma et page Comptes** (route `/balance/accounts`) : première tranche de la nouvelle feature *Bilan*. La migration SQL v9 introduit 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) avec 7 index et seede 7 catégories standard — Encaisse, CELI, REER, Fonds commun, Autre (type simple) + Action et Cryptomonnaie (type coté). La colonne `currency` est verrouillée à `CAD` via une contrainte CHECK au MVP — le support multi-devises arrivera plus tard. La nouvelle page expose deux onglets : *Comptes* (CRUD complet sur les comptes de l'utilisateur, archivage soft plutôt que suppression dure pour préserver les snapshots historiques) et *Catégories* (renommer une catégorie, créer des catégories de type simple, supprimer celles créées par l'utilisateur — les catégories standard sont protégées). Couverture i18n FR/EN complète sous `balance.*`. Snapshots, transferts, rendements et price-fetching premium arriveront dans les prochaines issues ; pour l'instant la route est accessible directement par URL (pas encore d'entrée sidebar) (#138)
|
||||||
|
|
||||||
### Corrigé
|
### Corrigé
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- **Balance sheet — snapshot editor (simple kind)** (route `/balance/snapshot`): second slice of the *Bilan* feature. The new page lets you create or edit a dated snapshot of your balance: pick a date (defaulting to today), enter the value of each active account grouped by category, and save. The mode is driven by the `?date=` query parameter — when a snapshot already exists at that date the page automatically flips into edit mode (the underlying `balance_snapshots.snapshot_date` UNIQUE constraint guarantees one snapshot per day). The date of an existing snapshot is immutable: to change it, delete the snapshot and create a new one. A *Prefill from previous snapshot* button copies values from the most recent earlier snapshot (simple-kind accounts only — priced accounts will be handled when the priced editor lands in a later release). A *Delete* button surfaces a double-confirmation modal that requires retyping the snapshot date before the destructive action is enabled. Only simple-kind values are accepted at this stage (`quantity` and `unit_price` are kept `NULL`); the priced editor (quantity × unit price + price fetch) ships in a later release. New `useSnapshotEditor` hook (scoped `useReducer` covering the full lifecycle) and two new components `SnapshotEditor` + `SnapshotLineRow`. FR/EN i18n under `balance.snapshot.*` (#146)
|
||||||
- **Balance sheet — schema foundation and accounts page** (route `/balance/accounts`): first slice of the upcoming *Bilan* feature. New SQL migration v9 introduces 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) with 7 indexes and seeds 7 standard categories — Cash, TFSA, RRSP, Mutual Fund, Other (simple kind) plus Stock and Crypto (priced kind). The `currency` column is hardcoded to `CAD` via a CHECK constraint at the MVP — multi-currency support will come in a later release. The new accounts page exposes two tabs: *Accounts* (full CRUD over the user's holdings, soft-archive instead of hard delete to preserve historic snapshots) and *Categories* (rename any category, create simple-kind ones, delete user-created ones — seeded categories are protected). The full FR/EN i18n coverage uses keys under `balance.*`. Snapshots, transfers, returns and the price-fetching premium remain to ship in upcoming issues; for now the route is reachable directly via URL (no sidebar entry yet) (#138)
|
- **Balance sheet — schema foundation and accounts page** (route `/balance/accounts`): first slice of the upcoming *Bilan* feature. New SQL migration v9 introduces 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) with 7 indexes and seeds 7 standard categories — Cash, TFSA, RRSP, Mutual Fund, Other (simple kind) plus Stock and Crypto (priced kind). The `currency` column is hardcoded to `CAD` via a CHECK constraint at the MVP — multi-currency support will come in a later release. The new accounts page exposes two tabs: *Accounts* (full CRUD over the user's holdings, soft-archive instead of hard delete to preserve historic snapshots) and *Categories* (rename any category, create simple-kind ones, delete user-created ones — seeded categories are protected). The full FR/EN i18n coverage uses keys under `balance.*`. Snapshots, transfers, returns and the price-fetching premium remain to ship in upcoming issues; for now the route is reachable directly via URL (no sidebar entry yet) (#138)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
|
|
@ -981,7 +981,8 @@
|
||||||
"darkMode": "Dark mode",
|
"darkMode": "Dark mode",
|
||||||
"lightMode": "Light mode",
|
"lightMode": "Light mode",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"underConstruction": "Under construction"
|
"underConstruction": "Under construction",
|
||||||
|
"back": "Back"
|
||||||
},
|
},
|
||||||
"license": {
|
"license": {
|
||||||
"title": "License",
|
"title": "License",
|
||||||
|
|
@ -1535,6 +1536,36 @@
|
||||||
"stock": "Stock",
|
"stock": "Stock",
|
||||||
"crypto": "Crypto"
|
"crypto": "Crypto"
|
||||||
},
|
},
|
||||||
|
"snapshot": {
|
||||||
|
"page": {
|
||||||
|
"newTitle": "New snapshot",
|
||||||
|
"editTitle": "Edit snapshot",
|
||||||
|
"dateLabel": "Snapshot date",
|
||||||
|
"dateImmutable": "An existing snapshot date cannot be changed. To change the date, delete this snapshot and create a new one.",
|
||||||
|
"total": "Entered total",
|
||||||
|
"noAccounts": "You need to create at least one balance account first.",
|
||||||
|
"goToAccounts": "Go to accounts",
|
||||||
|
"prefill": "Prefill from previous",
|
||||||
|
"prefillTooltip": "Copy values from the snapshot dated {{date}}",
|
||||||
|
"prefillNoPrevious": "No earlier snapshot available.",
|
||||||
|
"save": "Save",
|
||||||
|
"create": "Create snapshot",
|
||||||
|
"delete": "Delete this snapshot"
|
||||||
|
},
|
||||||
|
"editor": {
|
||||||
|
"empty": "No active accounts. Create an account before entering a snapshot."
|
||||||
|
},
|
||||||
|
"line": {
|
||||||
|
"valuePlaceholder": "0.00",
|
||||||
|
"valueLabel": "Value for {{account}}"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"title": "Delete this snapshot?",
|
||||||
|
"body": "This permanently deletes the snapshot dated {{date}} and all its lines. To confirm, retype the date below.",
|
||||||
|
"confirmLabel": "Retype the date {{date}} to confirm",
|
||||||
|
"confirm": "Delete permanently"
|
||||||
|
}
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"currency_unsupported": "Only CAD is supported at the MVP.",
|
"currency_unsupported": "Only CAD is supported at the MVP.",
|
||||||
"category_seed_protected": "Standard categories cannot be deleted.",
|
"category_seed_protected": "Standard categories cannot be deleted.",
|
||||||
|
|
@ -1542,7 +1573,12 @@
|
||||||
"category_not_found": "Category not found.",
|
"category_not_found": "Category not found.",
|
||||||
"account_not_found": "Account not found.",
|
"account_not_found": "Account not found.",
|
||||||
"name_required": "Name is required.",
|
"name_required": "Name is required.",
|
||||||
"kind_invalid": "Invalid category kind."
|
"kind_invalid": "Invalid category kind.",
|
||||||
|
"snapshot_date_required": "A date in YYYY-MM-DD format is required.",
|
||||||
|
"snapshot_date_taken": "A snapshot already exists at that date — edit it instead of creating a new one.",
|
||||||
|
"snapshot_not_found": "Snapshot not found.",
|
||||||
|
"snapshot_value_invalid": "An entered value is not a valid number.",
|
||||||
|
"snapshot_priced_unsupported": "Priced accounts (stocks/crypto) will be supported in a future release."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -981,7 +981,8 @@
|
||||||
"darkMode": "Mode sombre",
|
"darkMode": "Mode sombre",
|
||||||
"lightMode": "Mode clair",
|
"lightMode": "Mode clair",
|
||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
"underConstruction": "En construction"
|
"underConstruction": "En construction",
|
||||||
|
"back": "Retour"
|
||||||
},
|
},
|
||||||
"license": {
|
"license": {
|
||||||
"title": "Licence",
|
"title": "Licence",
|
||||||
|
|
@ -1535,6 +1536,36 @@
|
||||||
"stock": "Action",
|
"stock": "Action",
|
||||||
"crypto": "Cryptomonnaie"
|
"crypto": "Cryptomonnaie"
|
||||||
},
|
},
|
||||||
|
"snapshot": {
|
||||||
|
"page": {
|
||||||
|
"newTitle": "Nouveau snapshot",
|
||||||
|
"editTitle": "Modifier le snapshot",
|
||||||
|
"dateLabel": "Date du snapshot",
|
||||||
|
"dateImmutable": "La date d'un snapshot existant ne peut pas être modifiée. Pour changer la date, supprimez ce snapshot et créez-en un nouveau.",
|
||||||
|
"total": "Total saisi",
|
||||||
|
"noAccounts": "Vous devez d'abord créer au moins un compte de bilan.",
|
||||||
|
"goToAccounts": "Aller aux comptes",
|
||||||
|
"prefill": "Pré-remplir depuis le précédent",
|
||||||
|
"prefillTooltip": "Copier les valeurs du snapshot du {{date}}",
|
||||||
|
"prefillNoPrevious": "Aucun snapshot antérieur disponible.",
|
||||||
|
"save": "Enregistrer",
|
||||||
|
"create": "Créer le snapshot",
|
||||||
|
"delete": "Supprimer ce snapshot"
|
||||||
|
},
|
||||||
|
"editor": {
|
||||||
|
"empty": "Aucun compte actif. Créez un compte avant de saisir un snapshot."
|
||||||
|
},
|
||||||
|
"line": {
|
||||||
|
"valuePlaceholder": "0,00",
|
||||||
|
"valueLabel": "Valeur pour {{account}}"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"title": "Supprimer ce snapshot ?",
|
||||||
|
"body": "Cette action supprime définitivement le snapshot du {{date}} et toutes ses lignes. Pour confirmer, retapez la date ci-dessous.",
|
||||||
|
"confirmLabel": "Retapez la date {{date}} pour confirmer",
|
||||||
|
"confirm": "Supprimer définitivement"
|
||||||
|
}
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"currency_unsupported": "Seul le CAD est supporté au MVP.",
|
"currency_unsupported": "Seul le CAD est supporté au MVP.",
|
||||||
"category_seed_protected": "Les catégories standard ne peuvent pas être supprimées.",
|
"category_seed_protected": "Les catégories standard ne peuvent pas être supprimées.",
|
||||||
|
|
@ -1542,7 +1573,12 @@
|
||||||
"category_not_found": "Catégorie introuvable.",
|
"category_not_found": "Catégorie introuvable.",
|
||||||
"account_not_found": "Compte introuvable.",
|
"account_not_found": "Compte introuvable.",
|
||||||
"name_required": "Le nom est obligatoire.",
|
"name_required": "Le nom est obligatoire.",
|
||||||
"kind_invalid": "Type de catégorie invalide."
|
"kind_invalid": "Type de catégorie invalide.",
|
||||||
|
"snapshot_date_required": "Une date au format AAAA-MM-JJ est obligatoire.",
|
||||||
|
"snapshot_date_taken": "Un snapshot existe déjà à cette date — modifiez-le au lieu d'en créer un nouveau.",
|
||||||
|
"snapshot_not_found": "Snapshot introuvable.",
|
||||||
|
"snapshot_value_invalid": "Une valeur saisie n'est pas un nombre valide.",
|
||||||
|
"snapshot_priced_unsupported": "Les comptes cotés (actions/crypto) seront supportés dans une prochaine version."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue