Files
MadJax 7e80427e09 Precision configurable des distances (arrondi superieur 0/1/2 decimales)
- Nouveau parametre global Precision_Distance (sous-menu Application de la
  Page_Parametrage, entre Compte et Vehicules), persiste via une entite
  singleton ParametresApplication, expose par GET/PUT /api/parametres-application
- Arrondi superieur (ceiling) applique a l'affichage et aux agregats : trajet
  simple, aller/retour (arrondi puis doublement), totaux jour/mois/annee,
  carte, export PDF et bareme kilometrique - jamais a la distance brute stockee
- Refonte du Montant_Previsionnel : le montant mensuel (80%) porte desormais
  sur le seul mois affiche (tranche determinee par le cumul annuel) ; nouvelle
  ligne Montant_Previsionnel_Annuel (100%, sans minoration, sur le cumul)
- Backend : PrecisionDistanceService (ArrondirDistance), integration dans
  ResumeService/TotauxService/RemboursementService/MontantRegleService,
  migration EF Core ; 7 tests de propriete (FsCheck) + tests existants, 62/62 verts
- Frontend : ParametresApplicationService (signal partage), composant de
  parametrage, fonction miroir arrondirDistance, adaptation de la liste des
  trajets, du panneau des totaux, de la carte et des montants regles
- Specs : nouvelle spec precision-distances-km (requirements/design/tasks) ;
  mise a jour de requirements.md, design.md et design-requirements.md de
  schotziad-km-tracker (Requirement 22, renvois croises, Montant_Previsionnel)
- Suppression du fichier chromium .deb suivi par erreur dans le depot
2026-09-25 12:02:52 +02:00

15 KiB
Raw Permalink Blame History

Implementation Plan: Précision des distances (km)

Overview

Cette implémentation ajoute un paramètre global Precision_Distance (0/1/2 décimales) avec arrondi supérieur (ceiling) systématique côté backend et frontend, refond le calcul du Montant_Previsionnel (mensuel recentré sur le mois affiché + nouveau montant annuel 100%), et propage la cohérence de l'arrondi à la liste des trajets, aux totaux, à la carte, à l'export PDF et au barème kilométrique.

L'ordre des tâches suit les dépendances réelles : entité + migration → service de précision pur → intégration dans les services d'agrégation existants → refonte du calcul prévisionnel → cohérence carte/PDF → tests backend → couche frontend (service/util → composant/route → consommateurs) → vérification finale.

Tasks

  • 1. Backend — Entité ParametresApplication et migration EF Core

    • Créer Models/Entities/ParametresApplication.cs (singleton Id = 1, PrecisionDistanceKm défaut 2, UpdatedAt)
    • Ajouter DbSet<ParametresApplication> ParametresApplication et la configuration OnModelCreating (contrainte CHECK IN (0,1,2), clé ValueGeneratedNever(), index unique singleton) dans Data/AppDbContext.cs
    • Générer la migration EF Core (dotnet ef migrations add AjoutParametresApplication) créant la table avec la contrainte CHECK
    • Requirements: 1.1, 1.2
  • 2. Backend — Service de précision et exception métier

    • 2.1 Créer l'exception Services/Exceptions/PrecisionDistanceInvalideException.cs (même modèle que MontantRegleNegatifException)
      • Requirements: 1.6
    • 2.2 Créer Services/IPrecisionDistanceService.cs (ObtenirAsync, DefinirAsync, ArrondirDistance)
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.6, 1.8, 3.1, 3.2, 3.3, 3.4, 3.5, 4.2
    • 2.3 Implémenter Services/PrecisionDistanceService.cs
      • GetOrCreateAsync privé créant la ligne singleton par défaut (2) si absente
      • ObtenirAsync/DefinirAsync avec validation stricte {0,1,2} levant PrecisionDistanceInvalideException
      • ArrondirDistance : Ceiling(distance × 10^precision) / 10^precision
      • Requirements: 1.1, 1.2, 1.5, 1.6, 1.8, 3.1, 3.2, 3.3, 3.4, 3.5
    • * 2.4 Écrire les tests de propriété pour PrecisionDistanceService
      • Property 1: Arrondi supérieur exact et jamais inférieur à la distance brute — Validates: Requirements 3.1, 3.2, 3.3, 3.4, 3.5
      • Property 4: Validation stricte de la précision — Validates: Requirements 1.6
      • Property 5: Invariance de la distance brute stockée face à un changement de précision — Validates: Requirements 1.5, 1.8
    • * 2.5 Écrire les tests unitaires PrecisionDistanceService
      • ObtenirAsync retourne 2 par défaut quand la table est vide (Exigence 1.2)
      • DefinirAsync(3) lève PrecisionDistanceInvalideException (Exigence 1.6, cas concret)
      • Requirements: 1.2, 1.6
  • 3. Backend — DTOs et contrôleur ParametresApplicationController

    • 3.1 Créer Models/DTOs/ParametresApplicationDtos.cs (ParametresApplicationDto, SavePrecisionDistanceDto)
      • Requirements: 1.3, 1.4
    • 3.2 Créer Controllers/ParametresApplicationController.cs (GET/PUT api/parametres-application, mapping PrecisionDistanceInvalideException → 400)
      • Requirements: 1.3, 1.4, 1.6, 1.7
    • 3.3 Enregistrer IPrecisionDistanceService/PrecisionDistanceService dans Program.cs (AddScoped, section services métier)
      • Requirements: 1.1, 1.3, 1.4
    • * 3.4 Écrire les tests d'intégration du contrôleur
      • PUT /api/parametres-application avec precisionDistanceKm = 3 retourne 400 (Exigence 1.6)
      • GET/PUT /api/parametres-application sans jeton retourne 401 (Exigence 1.7)
      • Requirements: 1.3, 1.4, 1.6, 1.7
  • 4. Checkpoint — Ensure all tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 5. Backend — Intégration de l'arrondi dans les services d'agrégation existants

    • 5.1 Modifier Services/ResumeService.cs : injecter IPrecisionDistanceService, appliquer ArrondirDistance(Distance, precision) × (AllerRetour ? 2 : 1) par trajet dans ConstruireResumeMensuel, exposer TrajetDto.Distance déjà arrondi, sommer les valeurs déjà arrondies pour TotalKm sans second arrondi
      • Requirements: 4.1, 4.2, 4.3, 5.2, 5.3
    • 5.2 Modifier Services/TotauxService.cs : injecter IPrecisionDistanceService, remplacer la fonction locale Effective(distance, allerRetour) par l'arrondi avant doublement, supprimer le Math.Round(..., 2, ...) final existant sur TotalJour/TotalMois/TotalAnnuelPartiel
      • Requirements: 4.1, 4.2, 4.3, 5.1, 5.4
    • 5.3 Modifier Services/RemboursementService.cs : injecter IPrecisionDistanceService, construire kmMoisMap à partir des distances arrondies par trajet (au lieu de la distance brute), garantissant totalKmAnnuel et chaque KmMois comme sommes de distances déjà arrondies
      • Requirements: 4.1, 4.2, 4.3, 6.3, 6.4, 6.6
    • * 5.4 Écrire le test de propriété pour la sommation
      • Property 2: Arrondi avant doublement pour Aller_Retour — Validates: Requirements 4.1, 4.2, 4.3
      • Property 3: Sommation de distances déjà arrondies sans arrondi supplémentaire — Validates: Requirements 5.1, 5.2, 5.3, 5.4
    • * 5.5 Écrire le test unitaire de l'exemple chiffré Aller_Retour
      • Cas 12.30 km, précision 0 → 26 km (et non 25 km), en plus de la Property 2
      • Requirements: 4.2
  • 6. Backend — Refonte de MontantRegleService.GetMontantPrevisionnelAsync

    • 6.1 Créer/modifier le DTO MontantPrevisionnelDto (TotalMoisKm, TotalAnnuelPartielKm, MontantPrevisionnelMensuel, MontantPrevisionnelAnnuel) dans Models/DTOs/
      • Requirements: 6.1, 6.2, 7.1, 8.1, 8.2, 8.4
    • 6.2 Modifier Services/IMontantRegleService.cs et Services/MontantRegleService.cs : injecter IPrecisionDistanceService, calculer totalMoisAffiche/totalAnnuelPartiel à partir des distances arrondies, déterminer la tranche via le cumul annuel (baremeAnnuel), appliquer son coefficient/base au total du mois pour MontantPrevisionnelMensuel (80%), calculer MontantPrevisionnelAnnuel (100% sur le cumul)
      • Requirements: 6.1, 6.2, 6.6, 7.1, 7.2, 7.4, 8.1, 8.2, 8.5
    • * 6.3 Écrire les tests de propriété pour le calcul prévisionnel
      • Property 6: Montant_Previsionnel_Mensuel dépend uniquement du mois affiché — Validates: Requirements 7.1, 7.2
      • Property 7: Montant_Previsionnel_Annuel égal au barème plein sur le cumul — Validates: Requirements 8.2, 8.5
    • * 6.4 Écrire les tests unitaires de GetMontantPrevisionnelAsync
      • Véhicule introuvable → VehiculeNotFoundException (comportement existant inchangé)
      • Cas limite : trajets avec distance null ignorés dans la somme
      • Requirements: 6.1, 6.2, 7.1, 8.1, 8.2
  • 7. Backend — Cohérence carte et export PDF

    • 7.1 Vérifier/corriger l'endpoint trajets/journée (ITrajetService/TrajetsController, méthode consommée par TrajetService.getTrajetsJournee) pour renvoyer la Distance_Effective_Arrondie via IPrecisionDistanceService
      • Requirements: 9.1, 9.4
    • 7.2 Vérifier Services/PdfService.cs (AssemblerModeleMensuelAsync, composition des tables mensuelle/annuelle) : confirmer qu'aucun recalcul de distance brute ne subsiste et que le modèle assemblé provient intégralement de IResumeService/IRemboursementService déjà corrigés
      • Requirements: 9.2, 9.3
    • * 7.3 Écrire les tests de propriété de cohérence carte/PDF
      • Property 8: Cohérence de l'infobulle carte avec la Distance_Effective_Arrondie — Validates: Requirements 9.1
      • Property 9: Modèle de données PDF cohérent avec les résumés/régularisations — Validates: Requirements 9.2, 9.3
    • * 7.4 Écrire le test d'intégration de cohérence croisée
      • Scénario bout-en-bout (SQLite en mémoire) : créer des trajets sur plusieurs mois, changer Precision_Distance, vérifier l'égalité des valeurs entre ResumeService, TotauxService et RemboursementService (Exigence 9.4)
      • Requirements: 9.4
    • * 7.5 Écrire les tests d'intégration de génération PDF
      • Génération effective d'un PDF mensuel et d'un PDF annuel (1 exemple chacun), vérifier l'absence d'exception après les changements de modèle
      • Requirements: 9.2, 9.3
  • 8. Checkpoint — Ensure all tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 9. Frontend — Modèle, service et utilitaire d'arrondi

    • 9.1 Créer core/models/parametres-application.model.ts (ParametresApplication { precisionDistanceKm: number })
      • Requirements: 1.3, 1.4
    • 9.2 Créer core/services/parametres-application.service.ts (ParametresApplicationService : signal partagé precisionDistance, charger(), definirPrecisionDistance())
      • Requirements: 1.3, 1.4, 2.3, 2.4, 2.5
    • 9.3 Créer shared/utils/arrondir-distance.ts (arrondirDistance, distanceEffectiveArrondie), miroir exact de la formule backend
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 4.1, 4.2, 4.3, 5.5
    • * 9.4 Écrire les tests unitaires de arrondirDistance/distanceEffectiveArrondie
      • Cas 12.30 km, précision 0, aller-retour → 26 km (miroir du test backend)
      • Cas limites par précision (0/1/2) et valeurs proches d'un seuil d'arrondi
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 4.1, 4.2, 4.3
    • * 9.5 Mettre à jour core/models/bareme.model.ts et core/services/bareme.service.ts avec les nouveaux champs MontantPrevisionnel (totalMoisKm, totalAnnuelPartielKm, montantPrevisionnelMensuel, montantPrevisionnelAnnuel)
      • Requirements: 6.1, 7.1, 8.1, 8.2, 8.4
  • 10. Frontend — Composant ParametresApplicationComponent et route/menu

    • 10.1 Créer features/parametres-application/parametres-application.component.ts (+ .html, .scss) : sélection 0/1/2, présélection de la valeur courante, confirmation de succès, restauration + notification d'erreur en cas d'échec
      • Requirements: 2.2, 2.3, 2.4, 2.5
    • 10.2 Ajouter la route /parametrage/application dans app.routes.ts, entre compte et vehicules, gardée uniquement par authGuard (pas profilConfigureGuard)
      • Requirements: 2.1, 2.6
    • 10.3 Ajouter le lien « Application » entre « Compte » et « Véhicules » dans features/parametrage/parametrage.component.html
      • Requirements: 2.1
    • * 10.4 Écrire les tests unitaires du composant ParametresApplicationComponent
      • Présélection de la valeur courante au chargement (Exigence 2.3)
      • choisir() restaure la sélection précédente et notifie une erreur si l'appel HTTP échoue (Exigence 2.5)
      • Requirements: 2.3, 2.4, 2.5
    • * 10.5 Écrire le test de structure du menu de paramétrage
      • Vérifier le positionnement du lien « Application » entre « Compte » et « Véhicules »
      • Requirements: 2.1
  • 11. Frontend — Chargement initial dans AppComponent

    • 11.1 Modifier app.component.ts pour appeler ParametresApplicationService.charger() au même moment que le chargement du profil (effect déclenché à l'authentification)
      • Requirements: 1.3, 5.5
  • 12. Checkpoint — Ensure all tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 13. Frontend — Adaptation des composants consommateurs

    • 13.1 Modifier features/trajet-list/trajet-list.component.ts (méthode distanceAffichee) : formater selon ParametresApplicationService.precisionDistance() au lieu d'un arrondi fixe à 2 décimales
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5
    • 13.2 Modifier features/panneau-totaux/panneau-totaux.component.ts + .html : format dynamique des distances basé sur precisionDistance(), ajout de la ligne « Montant prévisionnel annuel » sous l'indication de versement mensuelle, consommation de montantPrevisionnelMensuel/montantPrevisionnelAnnuel
      • Requirements: 5.4, 5.5, 8.1, 8.3, 8.4
    • 13.3 Modifier features/carte-trajets/carte-trajets.component.ts (méthode contenuInfobulle) : toFixed(precision) dynamique basé sur ParametresApplicationService.precisionDistance()
      • Requirements: 9.1
    • 13.4 Modifier features/montants-regles/montants-regles.component.ts : lire montantPrevisionnelMensuel au lieu de montantPrevisionnel
      • Requirements: 7.1, 7.3
    • * 13.5 Écrire les tests unitaires des composants adaptés
      • TrajetListComponent.distanceAffichee formate selon la précision courante
      • PanneauTotauxComponent affiche la nouvelle ligne « Montant prévisionnel annuel »
      • CarteTrajetsComponent.contenuInfobulle utilise la précision courante
      • MontantsReglesComponent affiche montantPrevisionnelMensuel sans erreur de liaison après le renommage du DTO
      • Requirements: 3.1, 5.4, 7.1, 7.3, 8.1, 8.3, 8.4, 9.1
  • 14. Checkpoint final — Ensure all tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 15. Vérification finale

    • 15.1 Exécuter le build backend (dotnet build) et le build frontend (ng build / npm run build), corriger toute erreur de compilation résultant des changements de DTO/modèle
      • Requirements: 1.1–9.4 (non-régression globale)
    • 15.2 Exécuter l'ensemble des tests backend (dotnet test) et frontend (ng test / vitest --run), vérifier que toutes les propriétés et tous les tests unitaires/intégration passent
      • Requirements: 1.1–9.4 (non-régression globale)

Notes

  • Les tâches marquées * sont optionnelles (tests) et peuvent être ignorées pour un MVP plus rapide, mais restent recommandées vu la présence de 9 Correctness Properties dans le design.
  • Chaque tâche référence les exigences granulaires concernées pour la traçabilité.
  • Les checkpoints garantissent une validation incrémentale avant de passer à la couche suivante (backend cœur → calcul prévisionnel → cohérence carte/PDF → frontend).
  • Les tests de propriété utilisent FsCheck (déjà présent dans SchotzIadKmTracker.Tests.csproj), avec au moins 100 itérations par propriété et le tag de traçabilité // Feature: precision-distances-km, Property {n}: {texte}.
  • La tâche 6.2 constitue une rupture de contrat mineure sur MontantPrevisionnelDto : les tâches frontend 9.5 et 13.4 doivent être réalisées après la tâche 6.1 pour rester synchronisées avec les nouveaux noms de champs.

Task Dependency Graph

{
  "waves": [
    { "id": 0, "tasks": ["1"] },
    { "id": 1, "tasks": ["2.1"] },
    { "id": 2, "tasks": ["2.2"] },
    { "id": 3, "tasks": ["2.3"] },
    { "id": 4, "tasks": ["2.4", "2.5", "3.1"] },
    { "id": 5, "tasks": ["3.2"] },
    { "id": 6, "tasks": ["3.3"] },
    { "id": 7, "tasks": ["3.4"] },
    { "id": 8, "tasks": ["5.1", "5.2", "5.3"] },
    { "id": 9, "tasks": ["5.4", "5.5", "6.1"] },
    { "id": 10, "tasks": ["6.2"] },
    { "id": 11, "tasks": ["6.3", "6.4", "7.1"] },
    { "id": 12, "tasks": ["7.2"] },
    { "id": 13, "tasks": ["7.3", "7.4", "7.5"] },
    { "id": 14, "tasks": ["9.1"] },
    { "id": 15, "tasks": ["9.2"] },
    { "id": 16, "tasks": ["9.3", "9.5"] },
    { "id": 17, "tasks": ["9.4", "10.1"] },
    { "id": 18, "tasks": ["10.2", "10.3"] },
    { "id": 19, "tasks": ["10.4", "10.5", "11.1"] },
    { "id": 20, "tasks": ["13.1", "13.2", "13.3", "13.4"] },
    { "id": 21, "tasks": ["13.5"] },
    { "id": 22, "tasks": ["15.1"] },
    { "id": 23, "tasks": ["15.2"] }
  ]
}