Aller au contenu

Ajout d'un registre des transactions par titre

Billet #329 : Registre des transactions par titre
Type : Fonctionnalité / Expérience utilisateur / Intégrité des données
Composants concernés : code_source_simule/transaction_service.py, code_source_simule/flask_app.py, code_source_simule/import_data.py, run_pipeline.sh, scripts/load_initial_transactions.py, scripts/apply_migrations.py, migrations/0002_add_transactions.sql, migrations/0003_expand_transaction_source_precision.sql, templates/titre_detail.html, tests/test_transaction_service.py, tests/test_holding_transactions.py, tests/test_load_initial_transactions.py, tests/test_demo.py, tests/test_apply_migrations.py, e2e/src/pages/TitreDetailPage.ts, e2e/src/tests/titreDetail.spec.ts, docs/features/chapter2.md, docs/fr/features/chapter2.md, docs/features/chapter3.md, docs/fr/features/chapter3.md, specs/022-holding-transactions/


1. Contexte

La fiche de chaque titre n'affichait que les relevés de marché, c'est-à-dire les prix observés jour après jour. Rien ne permettait de retrouver les décisions d'achat et de vente à l'origine d'une position : ni la date d'entrée, ni le prix payé, ni le montant réellement engagé.

L'historique complet de mes opérations existait pourtant déjà, mais uniquement sous forme de fichier externe, inutilisable depuis l'application. Impossible, en ouvrant un titre, de répondre à une question aussi simple que : « à quel prix suis-je entré, et combien ai-je investi ? »

2. Objectif

  • Afficher, sur la fiche de chaque titre, un tableau des transactions clairement distinct de l'historique des prix du marché.
  • Permettre d'ajouter, corriger et supprimer une opération directement depuis cette fiche, sans dépendre d'un nouveau fichier.
  • Charger l'historique existant par une opération d'administration, sans jamais exposer de fonction d'import de fichier aux utilisateurs de l'application.
  • Offrir les mêmes actions dans la version démo, sur des données isolées, sans aucun risque pour les données réelles.

3. Ce qui a été livré

  • Un registre séparé (nouvelle table transactions) rattaché à chaque titre, qui ne modifie ni les relevés de prix existants, ni les indicateurs du tableau de bord.
  • Chargement initial automatisé : après la synchronisation quotidienne des titres, le pipeline lit le fichier fourni et ajoute les opérations sans doublon. La commande dédiée reste disponible en simulation pour contrôler le résultat avant toute écriture.
  • Fidélité au fichier fourni : les 390 lignes sont prises en charge, dont les anciens prix à trois décimales, deux lignes à zéro action, quatre écarts d'arrondi d'un cent et deux opérations distinctes partageant le même identifiant source. Ces exceptions restent réservées à l'historique; les nouvelles saisies conservent les règles strictes à deux décimales.
  • Gestion complète depuis la fiche titre : ajout, modification et suppression avec confirmation explicite, les opérations les plus récentes apparaissant en premier.
  • Garde-fous métier automatiques :
    • le montant total n'est jamais saisi à la main : il est toujours recalculé (actions × prix) et arrondi commercialement à deux décimales ;
    • les quantités, les prix unitaires et les montants utilisent deux décimales ;
    • la première transaction chronologique d'un titre doit toujours être un BUY ;
    • une vente antidatée avant le premier achat est refusée, tandis qu'un achat antidaté reste autorisé lorsqu'il corrige légitimement l'historique ;
    • une vente qui ferait passer le nombre d'actions détenues sous zéro à sa date est refusée, y compris lorsqu'une opération est ajoutée rétroactivement dans le passé ;
    • la suppression d'un BUY est refusée si les SELL ultérieurs feraient alors passer le total de Shares sous zéro, avec un message explicatif spécifique en anglais ;
    • lorsque plusieurs opérations portent la même date, les BUY sont comptés avant les SELL, indépendamment de l'ordre de saisie ;
    • si plusieurs demandes tentent de modifier les transactions d'un même titre en même temps, l'application les traite une par une et recalcule le solde après chacune ;
    • l'unique transaction BUY restante ne peut pas être supprimée comme une simple ligne : les ventes restantes doivent d'abord être retirées, puis la suppression du titre complet exige une confirmation explicite.
  • Parité en démonstration : chaque titre affiche des transactions en ordre récent. Le visiteur peut les consulter, ajouter, modifier et supprimer ; retirer le dernier BUY masque temporairement ce titre du dashboard et des fiches accessibles seulement après confirmation. Le résultat est affiché une fois, puis tout rafraîchissement restaure la démo initiale ; aucun changement n'est écrit dans la base sécurisée.
  • Aucune fonction de téléversement n'a été ajoutée à l'application : le périmètre a été volontairement restreint sur ce point.
  • Processus complet Spec Kit suivi de bout en bout : spécification, clarification (5 décisions arbitrées, dont la précision monétaire et la durée de vie des données de démonstration), plan technique, tâches, analyse de cohérence, puis implémentation test-first.

4. Impact business

  • Lecture financière complète : la fiche d'un titre réunit désormais ce que le marché affiche et ce que j'ai réellement fait, au même endroit.
  • Fiabilité des chiffres : le montant total ne peut plus diverger des données saisies, et le portefeuille ne peut plus afficher une position négative issue d'une erreur de saisie.
  • Vitrine cohérente : la démonstration publique montre la fonctionnalité réelle, sans exposer ni altérer la moindre donnée du portefeuille.

5. Validation et statut

  • Suite de tests complète au vert : 332/332 tests passent.
  • Couverture du code applicatif : 83,29 % (code_source_simule/*), au-dessus du seuil qualité de 80 %.
  • Score qualité global recalculé : 91,65/100, avec 9/9 validations E2E réussies.
  • Cas de test dédiés ajoutés : tc-transaction-04a, tc-transaction-04b, tc-transaction-04c, tc-transaction-05, tc-transaction-07, tc-transaction-07a, tc-transaction-07b, tc-transaction-07c, tc-transaction-07d, tc-transaction-07e, tc-transaction-07f, tc-transaction-19 (fiche titre), tc-demo18, tc-demo19, tc-demo20, tc-demo21, tc-transaction-20 (démonstration) et tc-pipe-migrate04, en complément des tests de calcul, de validation et de solde chronologique. Les refus de suppression comparent désormais l'état complet avant et après, au lieu de vérifier uniquement le nombre de lignes.
  • Rapports régénérés : coverage.xml, docs/reports/report.xml, docs/reports/report.jsonl, docs/reports/coverage.xml, docs/reports/quality_score.json.
  • Le parcours navigateur du cycle ajout/modification/suppression a réussi dans Google Chrome contre un serveur local isolé et une base en mémoire. La suite générale Chrome compte également 23 tests réussis et 3 scénarios ignorés intentionnellement; aucune mutation E2E n'est envoyée vers la production.

6. Bilan d'utilisation de jetons

Cette implémentation complète (spécification, clarification, plan, tâches, analyse de cohérence, implémentation test-first, documentation, et revue de PR) a consommé 8300,7 crédits Copilot AI, pour un coût de 82,53 $. Ce coût reste très marginal comparé à la valeur livrée — une nouvelle fonctionnalité métier créée et améliorée, ses garde-fous financiers, sa parité en démonstration, sa couverture de tests et sa documentation — qui aurait mobilisé une petite équipe de TI (PO, dev et QA) pendant plusieurs semaines.