Bilan #4 — Ciblage transferts + rendement Modified Dietz #142

Closed
opened 2026-04-25 16:08:40 +00:00 by maximus · 1 comment
Owner

Refs: spec-decisions-bilan.md + spec-plan-bilan.md (v2)

Depends on #141

Plan v2 : Modified Dietz dans src-tauri/src/commands/return_calculator.rs (co-localisé), tests TDD co-localisés via #[cfg(test)] mod tests, FK RESTRICT sur transferts.

Tâches

Setup

  • Ajouter chrono = "0.4" à src-tauri/Cargo.toml (arithmétique de dates en jours pour pondération Modified Dietz). reqwest = "0.12" déjà présent.

Module Modified Dietz (Rust)

  • Créer src-tauri/src/commands/return_calculator.rs (module privé)
    • Type AccountReturn { value_start, value_end, net_contributions, return_pct, annualized_pct, is_partial, has_no_transfers_warning }
    • Fonction pub(crate) fn modified_dietz(value_start, value_end, cash_flows: &[(NaiveDate, f64)], period_start, period_end) -> AccountReturn
    • Gestion cas limites (voir tests)
  • Tests Rust co-localisés dans le même fichier (#[cfg(test)] mod tests) :
    • Cas nominal (snapshot début + fin + 2 apports répartis)
    • Pas de snapshot avant période → value_start: None
    • Snapshot manquant après → is_partial: true
    • Compte créé en cours (V_début = 0)
    • Compte vidé puis rechargé → warning
    • Aucun transfert lié → has_no_transfers_warning: true
    • Annualisation correcte (1+R)^(365/days)-1
  • Déclarer mod return_calculator; dans src-tauri/src/commands/mod.rs

Commande Tauri

  • Créer src-tauri/src/commands/balance_commands.rs avec UNIQUEMENT compute_account_return(account_id, period_start, period_end) :
    • Lit snapshots + transfers via tauri_plugin_sql côté Rust
    • Appelle return_calculator::modified_dietz, retourne AccountReturn
  • Enregistrer la commande dans lib.rs

Frontend

  • Étendre balance.service.ts avec section returns :
    • computeAccountReturn (via invoke)
    • linkTransfer, unlinkTransfer, listAccountTransfers (via getDb directement)
  • Tests vitest service returns (mock invoke pour computeAccountReturn)
  • Composant LinkTransfersModal.tsx (filtres période + catégorie + recherche, sélection multi avec sens auto-proposé)
  • Logique UI suppression transaction liée : la transactionService existante doit détecter le FK RESTRICT et afficher "Cette transaction est liée au compte de bilan X — déliez-la avant de supprimer" avec lien vers le compte concerné
  • Étendre BalanceAccountsTable.tsx avec 3 colonnes rendement (3M / 1A / depuis création) + colonne rendement non-ajusté côte-à-côte
  • Inliner TransactionTransferIcon (span+tooltip) dans TransactionTable.tsx existant — apparaît seulement pour transactions liées (PAS un composant séparé)
  • Marqueurs verticaux dans BalanceEvolutionChart.tsx (transferts taggés : vert in / rouge out)
  • Entrée CHANGELOG

Critères dacceptation

  • Un utilisateur peut lier des transactions à un compte (modal de sélection avec filtres)
  • Une transaction liée affiche une icône dattribution dans la page transactions (span+tooltip inline)
  • Le calcul Modified Dietz retourne les warnings appropriés (is_partial, has_no_transfers_warning)
  • Le rendement non-ajusté est affiché côte-à-côte du rendement ajusté
  • Tentative de supprimer une transaction liée affiche un message clair (FK RESTRICT respectée)
  • cargo test passe (7 cas Modified Dietz)
  • Coverage cible 80% sur return_calculator.rs
Refs: spec-decisions-bilan.md + spec-plan-bilan.md (v2) Depends on #141 Plan v2 : Modified Dietz dans src-tauri/src/commands/return_calculator.rs (co-localisé), tests TDD co-localisés via #[cfg(test)] mod tests, FK RESTRICT sur transferts. ## Tâches ### Setup - [ ] Ajouter chrono = "0.4" à src-tauri/Cargo.toml (arithmétique de dates en jours pour pondération Modified Dietz). reqwest = "0.12" déjà présent. ### Module Modified Dietz (Rust) - [ ] Créer src-tauri/src/commands/return_calculator.rs (module privé) - Type AccountReturn { value_start, value_end, net_contributions, return_pct, annualized_pct, is_partial, has_no_transfers_warning } - Fonction pub(crate) fn modified_dietz(value_start, value_end, cash_flows: &[(NaiveDate, f64)], period_start, period_end) -> AccountReturn - Gestion cas limites (voir tests) - [ ] Tests Rust **co-localisés** dans le même fichier (#[cfg(test)] mod tests) : - Cas nominal (snapshot début + fin + 2 apports répartis) - Pas de snapshot avant période → value_start: None - Snapshot manquant après → is_partial: true - Compte créé en cours (V_début = 0) - Compte vidé puis rechargé → warning - Aucun transfert lié → has_no_transfers_warning: true - Annualisation correcte (1+R)^(365/days)-1 - [ ] Déclarer mod return_calculator; dans src-tauri/src/commands/mod.rs ### Commande Tauri - [ ] Créer src-tauri/src/commands/balance_commands.rs avec UNIQUEMENT compute_account_return(account_id, period_start, period_end) : - Lit snapshots + transfers via tauri_plugin_sql côté Rust - Appelle return_calculator::modified_dietz, retourne AccountReturn - [ ] Enregistrer la commande dans lib.rs ### Frontend - [ ] Étendre balance.service.ts avec section returns : - computeAccountReturn (via invoke) - linkTransfer, unlinkTransfer, listAccountTransfers (via getDb directement) - [ ] Tests vitest service returns (mock invoke pour computeAccountReturn) - [ ] Composant LinkTransfersModal.tsx (filtres période + catégorie + recherche, sélection multi avec sens auto-proposé) - [ ] **Logique UI suppression transaction liée** : la transactionService existante doit détecter le FK RESTRICT et afficher "Cette transaction est liée au compte de bilan X — déliez-la avant de supprimer" avec lien vers le compte concerné - [ ] Étendre BalanceAccountsTable.tsx avec 3 colonnes rendement (3M / 1A / depuis création) + colonne rendement non-ajusté côte-à-côte - [ ] Inliner TransactionTransferIcon (span+tooltip) dans TransactionTable.tsx existant — apparaît seulement pour transactions liées (PAS un composant séparé) - [ ] Marqueurs verticaux dans BalanceEvolutionChart.tsx (transferts taggés : vert in / rouge out) - [ ] Entrée CHANGELOG ## Critères dacceptation - Un utilisateur peut lier des transactions à un compte (modal de sélection avec filtres) - Une transaction liée affiche une icône dattribution dans la page transactions (span+tooltip inline) - Le calcul Modified Dietz retourne les warnings appropriés (is_partial, has_no_transfers_warning) - Le rendement non-ajusté est affiché côte-à-côte du rendement ajusté - Tentative de supprimer une transaction liée affiche un message clair (FK RESTRICT respectée) - cargo test passe (7 cas Modified Dietz) - Coverage cible 80% sur return_calculator.rs
maximus added this to the spec-price-fetching milestone 2026-04-25 16:08:40 +00:00
maximus added the
status:ready
type:feature
source:human
labels 2026-04-25 16:08:40 +00:00
Author
Owner

/review-spec — findings Modified Dietz + structure module Rust

🔴 Critique : src-tauri/src/services/ n'existe pas

Le code Rust ne déclare que mod commands; et mod database;. Créer src-tauri/src/services/return_calculator.rs introduirait un nouveau top-level module juste pour Modified Dietz.
Fix : Trancher. Préféré : placer return_calculator.rs à côté de balance_commands.rs dans commands/ (mod return_calculator; dans commands/mod.rs). Toujours unit-testable, pas de nouveau layer.

🟡 Améliorations

1. chrono manquant dans Cargo.toml
reqwest = "0.12" est déjà présent (ligne 43) — mention "ajouter reqwest" no-op. Mais chrono n'y est pas (chrono_now est un stub). Modified Dietz nécessite arithmétiques de dates en jours (poids W_i = (T - t_i) / T), fragile sans crate dédié.
Fix : Ajouter chrono = "0.4" (ou time) dans Cargo.toml comme tâche de cette issue.

2. Tests Modified Dietz reportés trop tard (TDD opportunity)
Modified Dietz est la pièce la plus à risque (correction financière), construite ici, mais testée dans Issue 6 (qui dépend d'Issue 5 bloquée externe). Si Issue 5 reste en blocage long, Modified Dietz ship sans tests.
Fix : Déplacer les tests Rust unitaires de return_calculator.rs + tests migration FK/UNIQUE/CHECK directement dans cette issue (TDD). Garder Issue 6 pour les tests cross-cutting (vitest, mocks priceFetcher).

3. FK CASCADE sur balance_account_transfers.transaction_id
Si l'utilisateur supprime une transaction taggée, le lien disparaît silencieusement et les rendements Modified Dietz passés changent rétroactivement — problème de reproductibilité des rapports.
Fix : Soit ON DELETE RESTRICT (force unlink avant suppression), soit garder CASCADE mais snapshot des return_pct historiques. Trancher dans l'ADR.

## /review-spec — findings Modified Dietz + structure module Rust ### 🔴 Critique : `src-tauri/src/services/` n'existe pas Le code Rust ne déclare que `mod commands;` et `mod database;`. Créer `src-tauri/src/services/return_calculator.rs` introduirait un nouveau top-level module juste pour Modified Dietz. **Fix :** Trancher. Préféré : placer `return_calculator.rs` à côté de `balance_commands.rs` dans `commands/` (`mod return_calculator;` dans `commands/mod.rs`). Toujours unit-testable, pas de nouveau layer. ### 🟡 Améliorations **1. `chrono` manquant dans `Cargo.toml`** `reqwest = "0.12"` est déjà présent (ligne 43) — mention "ajouter reqwest" no-op. Mais `chrono` n'y est pas (`chrono_now` est un stub). Modified Dietz nécessite arithmétiques de dates en jours (poids `W_i = (T - t_i) / T`), fragile sans crate dédié. **Fix :** Ajouter `chrono = "0.4"` (ou `time`) dans `Cargo.toml` comme tâche de cette issue. **2. Tests Modified Dietz reportés trop tard (TDD opportunity)** Modified Dietz est la pièce la plus à risque (correction financière), construite ici, mais testée dans Issue 6 (qui dépend d'Issue 5 bloquée externe). Si Issue 5 reste en blocage long, Modified Dietz ship sans tests. **Fix :** Déplacer les tests Rust unitaires de `return_calculator.rs` + tests migration FK/UNIQUE/CHECK directement dans cette issue (TDD). Garder Issue 6 pour les tests cross-cutting (vitest, mocks priceFetcher). **3. FK CASCADE sur `balance_account_transfers.transaction_id`** Si l'utilisateur supprime une transaction taggée, le lien disparaît silencieusement et les rendements Modified Dietz passés changent rétroactivement — problème de reproductibilité des rapports. **Fix :** Soit `ON DELETE RESTRICT` (force unlink avant suppression), soit garder CASCADE mais snapshot des `return_pct` historiques. Trancher dans l'ADR.
maximus modified the milestone from spec-price-fetching to overnight-2026-04-26-bilan 2026-04-25 18:18:11 +00:00
maximus added the
status:in-progress
label 2026-04-25 20:13:21 +00:00
maximus removed the
status:in-progress
label 2026-04-25 20:42:48 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#142
No description provided.