- Backend : projets, solution, namespaces et références TrajetKmTracker.Api/.Tests -> SchotzIadKmTracker.Api/.Tests (dossiers, .csproj, .sln, .http, namespaces C#). GUID UserSecretsId préservé. - Specs : dossier .kiro/specs/trajet-km-tracker -> schotziad-km-tracker et mise à jour des références internes (chemins, tags de propriétés). - Frontend : projet Angular trajet-km-tracker -> schotziad-km-tracker (package.json, angular.json, chemin dist, Dockerfile), titre applicatif 'SchotzIAD KM Tracker'. - Docker et scripts (backend/Dockerfile, frontend/Dockerfile, run-dev.sh) mis à jour. - Suppression du fichier résiduel package.json.bak. Backend (solution) et frontend (build production) compilent sans erreur.
29 KiB
Implementation Plan: SchotzIAD KM Tracker
Overview
Ce plan décompose la conception en tâches de codage incrémentales. Le backend (ASP.NET Core / C# / EF Core / SQLite) est construit d'abord — entités, calculs métier, intégrations BAN/ORS, PDF — puis le frontend Angular consomme l'API. Chaque tâche s'appuie sur les précédentes et se termine par l'intégration, sans code orphelin. Les sous-tâches de test (unitaire, propriété, intégration) sont marquées optionnelles par * et référencent explicitement les propriétés de correction et exigences validées.
Langage backend : C# (ASP.NET Core, .NET 8). Langage frontend : TypeScript (Angular). Tests : xUnit + FsCheck + FluentAssertions + Moq (backend), Jest + Angular Testing Library (frontend).
Tasks
-
1. Initialiser la solution et le socle backend
- Créer la solution .NET et le projet
SchotzIadKmTracker.Api(ASP.NET Core Web API, .NET 8) - Créer le projet de tests
SchotzIadKmTracker.Tests(xUnit) avec les dépendances FsCheck, FluentAssertions, Moq, Microsoft.AspNetCore.Mvc.Testing - Ajouter les packages : EF Core + provider SQLite, FluentValidation.AspNetCore, QuestPDF
- Configurer
Program.cs: services de base, Swagger, middlewareProblemDetails, CORS pour le frontend Angular - Requirements: 6.1
- Créer la solution .NET et le projet
-
2. Modèle de données et contexte EF Core
-
2.1 Définir les entités du domaine
- Créer
Trajet(Date, AdresseDepart, AdresseArrivee, Distance, Commentaire, Position REAL, VehiculeId, PuissanceFiscale dénormalisée, CreatedAt/UpdatedAt) - Créer
Vehicule(Plaque, PuissanceFiscale, DateEffet),Profil(singleton Id=1, Nom/Prenom/Matricule/AdresseDomicile + coordonnées + DomicileGeocode) - Créer
AdresseCache(Adresse unique, Latitude/Longitude, GeometrieJson, DerniereUtilisation),TrancheBareme(Annee, PuissanceFiscale, KmMin, KmMax, Coefficient, Base),MontantRegle(Annee, Mois, VehiculeId, Montant) - Créer
AdresseNommee(Denomination unique 100 car., DenominationNormalisee, Adresse 255 car., Latitude?, Longitude?, GeocodageReussi, CreatedAt/UpdatedAt) - Requirements: 6.1, 6.2, 9.6, 10.1, 10.9, 13.1, 14.1, 15.4, 15.5
- Créer
-
2.2 Configurer
AppDbContextet les migrations- Déclarer les
DbSet, contraintes (CHECK Distance > 0, Montant >= 0, PuissanceFiscale > 0), index (Date, Date+Position, VehiculeId, DateEffet, Annee+PuissanceFiscale) et index uniques (Profil singleton, MontantsRegles par période/véhicule, AdresseCache par adresse) - Ajouter la table
AdressesNommeesavec l'index uniqueUX_AdresseNommee_DenominationsurDenominationNormalisee - Générer la migration initiale et l'appliquer à
trajets.db - Requirements: 6.1, 6.2, 9.6, 14.3, 15.6
- Déclarer les
-
* 2.3 Écrire les tests d'intégration du schéma
- Vérifier la création de la base, les contraintes CHECK et les index uniques (rejet des doublons de période/véhicule)
- Requirements: 6.1, 14.3
-
-
3. DTOs, options de configuration et validateurs
-
3.1 Créer les DTOs et enregistrements
CreateTrajetDto,UpdateTrajetDto,TrajetDto,TrajetCarteDto,ReordonnerTrajetsDto,TrajetPositionDtoResumeMensuelDto,ResumeAnnuelDto,TotauxDto,AdresseCacheDto,BANAdresseDtoProfilDto,SaveProfilDto,VehiculeDto,CreateVehiculeDto,VehiculeCreeDto,ReaffectationDtoTrancheBaremeDto,SaveTrancheBaremeDto,MontantRegleDto,MontantPrevisionnelDto,LigneSyntheseMoisDto,RegularisationAnnuelleDtoAdresseNommeeDto,SaveAdresseNommeeDtoEtatProfilDto(EstConfigure)- Créer
BANOptionsetORSOptions, les lier depuisappsettings.json - Requirements: 1.1, 1.10, 2.1, 15.4, 15.5
-
3.2 Implémenter les validateurs FluentValidation
CreateTrajetDtoValidator/UpdateTrajetDtoValidator: date obligatoire au format JJ/MM/AAAA et existante, adresses 1–255 car., commentaire ≤ 500 car.SaveProfilDtoValidator(matricule ≤ 8 car.),CreateVehiculeDtoValidator(DateEffet ≤ aujourd'hui),MontantRegleDto(montant ≥ 0)SaveAdresseNommeeDtoValidator: dénomination 1–100 car. (absente/vide/>100 → 15.6), adresse 1–255 car. (absente/vide/>255 → 15.8) ; l'unicité normalisée (doublon → 15.7) est vérifiée côté service- Requirements: 1.4, 1.5, 1.6, 1.7, 1.12, 6.3, 10.2, 10.11, 14.4, 15.6, 15.7, 15.8
-
* 3.3 Écrire les tests unitaires des validateurs
- Property 4 : Rejet systématique des données d'entrée invalides (backend)
- Validates: Requirements 1.5, 1.6, 1.7, 6.3
-
-
4. Intégrations externes : BAN et ORS
-
4.1 Implémenter
IBANClient/BANClient- Appel
GET /search/?q={query}&limit=5avec timeout configurable ; mapper versBANAdresseDto; leverBANIndisponibleExceptionen cas d'échec/timeout - Requirements: 1.13, 2.4, 9.1
- Appel
-
4.2 Implémenter
IORSClient/ORSClient- Appel
POST /v2/directions/driving-caravec coordonnées connues, extraction distance (km) + géométrie GeoJSON, timeout 10 s ; ne jamais appeler ORS avec des coordonnées nulles - Requirements: 2.1, 2.2, 8.7
- Appel
-
4.3 Implémenter
IDistanceCalculator/DistanceCalculatorService- Coordonnées connues → ORS ; coordonnées manquantes → géocodage BAN puis ORS ; échec ORS/timeout → fallback Haversine ; échec BAN total → distance nulle + avertissement
- Implémenter
HaversineKm, arrondi 2 décimales, borne 0,01–99 999,99 km - Requirements: 2.1, 2.2, 2.3, 2.4, 2.6
-
* 4.4 Écrire le test de propriété de priorité BAN sur ORS
- Property 16 : Priorité BAN sur ORS pour la résolution des coordonnées
- Validates: Requirements 2.4
-
* 4.5 Écrire les tests unitaires BAN/ORS/Distance
- BAN succès/non trouvé/timeout, ORS succès/timeout → Haversine, coordonnées manquantes → BAN puis ORS
- Requirements: 2.1, 2.2, 2.3, 2.6
-
-
5. Cache des adresses géocodées
-
5.1 Implémenter
AdresseCacheServiceet le repository associé- Recherche locale (min 3 car.), upsert d'une adresse (coordonnées inchangées si existante, mise à jour de
DerniereUtilisation), éviction LRU au-delà de 1 000 entrées - Requirements: 9.1, 9.2, 9.3, 9.5, 9.6
- Recherche locale (min 3 car.), upsert d'une adresse (coordonnées inchangées si existante, mise à jour de
-
* 5.2 Écrire le test de propriété de cohérence du cache
- Property 10 : Cohérence du cache adresses après géocodage
- Validates: Requirements 9.1, 9.2
-
* 5.3 Écrire le test de propriété LRU
- Property 11 : Politique LRU du cache adresses
- Validates: Requirements 9.5
-
-
6. Gestion des véhicules et du profil
-
6.1 Implémenter
VehiculeServiceet le repository véhicules- CRUD historique, détermination du Véhicule_Courant (DateEffet max ≤ aujourd'hui), rejet DateEffet future, conservation de l'historique
- Détection des trajets à réaffecter (date ≥ DateEffet et PuissanceFiscale différente) →
VehiculeCreeDto.ReaffectationProposee - Réaffectation acceptée (mise à jour VehiculeId + PuissanceFiscale des trajets ≥ DateEffet) / refusée (aucun changement), en transaction
- Requirements: 10.9, 10.10, 10.11, 10.12, 10.13, 10.15, 10.16, 10.17, 10.18
-
* 6.2 Écrire le test de propriété d'association du véhicule courant
- Property 19 : Association du véhicule courant par défaut
- Validates: Requirements 10.13, 10.14
-
* 6.3 Écrire le test de propriété de réaffectation bornée
- Property 20 : Réaffectation bornée à la date d'effet
- Validates: Requirements 10.16, 10.17
-
* 6.4 Écrire le test de propriété de conservation de l'historique
- Property 22 : Conservation de l'historique des véhicules
- Validates: Requirements 10.12, 10.18
-
6.5 Implémenter
ProfilServiceet le controllerProfilController- GET/PUT profil singleton, géocodage BAN de l'Adresse_Domicile (DomicileGeocode true/false), mise en cache, validation matricule ≤ 8 car.
- Exposer
GET /api/vehicules,GET /api/vehicules/courant,POST /api/vehicules,POST /api/vehicules/reaffectation - Exposer
GET /api/profil/etatretournantEtatProfilDto(EstConfigure)(true ssi Profil Nom+Prénom non vides ET au moins un Véhicule) - Requirements: 10.1, 10.2, 10.3, 10.7, 10.8, 10.18, 16.1, 16.2
-
* 6.6 Écrire le test de propriété de cohérence du profil domicile
- Property 12 : Cohérence du profil domicile
- Validates: Requirements 10.2, 10.7
-
* 6.7 Écrire le test de propriété de détermination de l'état de configuration du profil
- Property 31 : Détermination de l'état de configuration du profil
- Validates: Requirements 16.1, 16.2
-
-
7. Checkpoint — S'assurer que tous les tests passent
- Ensure all tests pass, ask the user if questions arise.
-
8. Service et API des trajets (CRUD + positions)
-
8.1 Implémenter
TrajetRepositoryet la gestion des positions- Résolution du véhicule à la date du trajet et copie de la PuissanceFiscale (dénormalisation)
- Attribution de Position : fin de journée
max(Position)+1.0, insertion(P1+P2)/2, renumérotation par pas de 1.0 si précision < 0.001 (transaction) - Requirements: 10.14, 11.7, 11.8
-
8.2 Implémenter
TrajetService(création)- Validation, association véhicule courant si VehiculeId absent, calcul de distance via
DistanceCalculatorService, mise en cache des adresses résolues, persistance transactionnelle - Gérer distance nulle + avertissement quand aucune coordonnée n'est résoluble
- Requirements: 1.2, 1.3, 1.11, 2.4, 2.5, 6.3, 6.7, 6.8, 10.14
- Validation, association véhicule courant si VehiculeId absent, calcul de distance via
-
* 8.3 Écrire le test de propriété de précision des distances
- Property 3 : Précision de stockage des distances
- Validates: Requirements 2.2, 2.5, 6.2
-
* 8.4 Écrire le test de propriété de persistance du commentaire
- Property 13 : Persistance optionnelle du commentaire
- Validates: Requirements 1.11, 1.12
-
8.5 Implémenter
TrajetService(modification, suppression, réordonnancement)- Modification : recalcul distance uniquement si adresse modifiée, commentaire seul sans recalcul, rollback si recalcul échoue, 404 si inexistant
- Suppression transactionnelle ;
PATCH /api/trajets/reordonnermet à jour les Position sans altérer les autres champs - Requirements: 5.2, 5.3, 5.5, 5.6, 5.8, 5.9, 5.10, 6.7, 6.8, 11.9
-
* 8.6 Écrire le test de propriété de recalcul conditionnel
- Property 6 : Recalcul conditionnel de la distance
- Validates: Requirements 5.2, 5.3
-
* 8.7 Écrire les tests de propriété sur les positions
- Property 14 : Cohérence de l'ordre des trajets d'une journée
- Property 15 : Unicité et cohérence des positions au sein d'une journée
- Validates: Requirements 11.7, 11.8, 11.9
-
8.8 Implémenter
TrajetsControlleret brancher le controller adressesPOST/GET/PUT/DELETE /api/trajets,PATCH /api/trajets/reordonner,GET /api/trajets/journee/{date}(avec géométries),GET /api/adresses/search- Requirements: 1.3, 5.5, 5.6, 8.7, 9.3
-
* 8.9 Écrire le test de propriété d'invariant de suppression
- Property 5 : Invariant de suppression
- Validates: Requirements 5.5, 6.4
-
-
9. Résumés, totaux et navigation temporelle
-
9.1 Implémenter
ResumeService(mensuel et annuel)- Résumé mensuel filtré par véhicule, trié par date puis Position, total 2 décimales ; validation mois [1,12] et année [2000,2100]
- Résumé annuel : toujours 12 mois (0 si vide), total = somme des 12 mois
- Requirements: 3.1, 3.2, 3.3, 3.4, 3.6, 3.8, 4.2, 4.3, 4.4, 4.7, 6.5, 6.6
-
* 9.2 Écrire les tests de propriété des totaux et résumés
- Property 1 : Cohérence du total mensuel — Validates: Requirements 3.3, 6.5
- Property 2 : Cohérence du total annuel — Validates: Requirements 4.3, 6.6
- Property 7 : Mois toujours présents dans le résumé annuel — Validates: Requirements 4.2, 4.4
- Property 8 : Rejet des paramètres de résumé hors plage — Validates: Requirements 3.6
-
9.3 Implémenter
TotauxServiceet la navigation temporelle- Totaux jour/mois/Total_Annuel_Partiel filtrés par véhicule (cumul jusqu'au mois inclus, exclusion des mois postérieurs)
- Années disponibles (données + année courante), mois disponibles, jours disponibles
- Requirements: 12.7, 12.8, 12.15, 12.16, 12.19
-
* 9.4 Écrire les tests de propriété des totaux filtrés et partiels
- Property 17 : Total annuel partiel borné au mois sélectionné — Validates: Requirements 12.8
- Property 21 : Totaux filtrés par véhicule — Validates: Requirements 12.19
-
9.5 Implémenter
ResumesControlleret les controllers de navigationGET /api/resumes/mensuel/{annee}/{mois},GET /api/resumes/annuel/{annee}GET /api/annees-disponibles,/api/mois-disponibles/{annee},/api/jours-disponibles/{annee}/{mois},/api/totaux/{date}- Requirements: 3.8, 4.1, 12.15, 12.16
-
-
10. Barème kilométrique et régularisation
-
10.1 Implémenter
BaremeServiceet le controller barème- CRUD des tranches, validation du non-chevauchement par (année, puissance fiscale)
- Sélection de tranche contenant le total annuel, formule
km × Coefficient + Base, barème non configuré → montant zéro + avertissement GET /api/bareme/{annee},POST/PUT/DELETE /api/bareme- Requirements: 13.1, 13.2, 13.3, 13.4
-
* 10.2 Écrire les tests de propriété de sélection de tranche
- Property 24 : Sélection de tranche du barème — Validates: Requirements 13.3, 13.4
- Property 27 : Sélection de tranche par le total annuel — Validates: Requirements 13.3, 14.6
-
10.3 Implémenter
MontantRegleService(upsert et montant prévisionnel)- Upsert par (année, mois, véhicule), rejet montant négatif
- Montant_Previsionnel = 80% du barème sur le Total_Annuel_Partiel (indicatif, hors régularisation)
- Requirements: 13.5, 13.6, 14.1, 14.2, 14.3, 14.4
-
* 10.4 Écrire les tests de propriété montants réglés / prévisionnel
- Property 23 : Indication de versement à 80% (informative) — Validates: Requirements 13.5, 13.6
- Property 26 : Unicité du montant réglé par période et véhicule — Validates: Requirements 14.3
-
10.5 Implémenter
RemboursementService(régularisation annuelle)- Montant_Reel = barème plein 100% sur total annuel, Frais_Reel_Mensuel = km_mois × coef tranche annuelle, Regularisation = Montant_Reel − total réglé
- Construire
RegularisationAnnuelleDto(12 lignes + totaux) GET /api/montant-previsionnel/...,GET/PUT /api/montants-regles,GET /api/regularisation/{annee}- Requirements: 14.5, 14.6, 14.7, 14.8
-
* 10.6 Écrire le test de propriété de régularisation
- Property 25 : Cohérence de la régularisation annuelle (barème plein)
- Validates: Requirements 13.3, 14.5, 14.6, 14.7
-
-
11. Export PDF (QuestPDF)
-
11.1 Implémenter
PdfService— rapport mensuel- En-tête : identité (nom, prénom, matricule), véhicule (plaque, puissance fiscale, coef/base tranche), période, adresse départ profil, totaux mois/année, TOTAL IK du mois, Montant_Regle
- Liste des trajets (date, motif/commentaire, départ → arrivée, km) ; timeout 15 s
- Requirements: 7.1, 7.4, 7.6, 7.8, 7.10, 7.11
-
11.2 Implémenter
PdfService— synthèse annuelle et rapports par véhicule- Page synthèse (identité, année, domicile, barème de l'année, véhicule, tranche) + 12 lignes (km, réglé, frais réel) + totaux (km annuel, réglé, réel, régularisation)
- Génération d'un PDF distinct par véhicule si plusieurs véhicules sur la période
- Requirements: 7.2, 7.4, 7.6, 7.7, 7.8, 7.9, 7.12
-
11.3 Implémenter
ExportsPdfControllerGET /api/exports/mensuel/{annee}/{mois}etGET /api/exports/annuel/{annee}; en-tête Content-Dispositiontrajets_MM_AAAA.pdf/trajets_AAAA.pdf, timeout → 503- Requirements: 7.3, 7.4, 7.5
-
* 11.4 Écrire le test de propriété de nommage PDF
- Property 9 : Nommage des fichiers PDF exportés
- Validates: Requirements 7.4
-
* 11.5 Écrire les tests unitaires PDF
- En-tête identité/véhicule, PDF distinct par véhicule, montants mensuels, régularisation annuelle
- Requirements: 7.6, 7.8, 7.9, 7.12
-
-
12. Checkpoint backend — S'assurer que tous les tests passent
- Ensure all tests pass, ask the user if questions arise.
-
* 13. Tests d'intégration backend end-to-end
-
* 13.1 Tests d'intégration trajets et distance (WebApplicationFactory + SQLite en mémoire)
- POST avec/sans coordonnées (BAN puis ORS, fallback Haversine, distance nulle + 201), insertion entre deux trajets, PATCH réordonner, PUT/DELETE
- Requirements: 1.3, 2.4, 2.6, 5.5, 11.8
-
* 13.2 Tests d'intégration résumés, totaux, véhicules, barème et exports
- Résumés mensuel/annuel, totaux partiels, réaffectation accepter/refuser, barème chevauchant → 400, upsert montant réglé, régularisation, export PDF 2 véhicules → 2 fichiers
- Requirements: 3.8, 4.1, 7.9, 10.16, 12.8, 13.2, 14.3, 14.7
-
-
14. Socle frontend Angular et services
-
14.1 Initialiser l'application Angular et le socle core
- Créer l'app Angular,
app-routing.module.ts, modèles TypeScript,notification.service.ts,TimeoutInterceptor(10 s),DateJjMmAAAAValidator - Requirements: 1.9, 1.5
- Créer l'app Angular,
-
14.2 Implémenter les services HTTP Angular
TrajetService,VehiculeService,BANService(autocomplétion),AdresseCacheService,ProfilService,BaremeService,RemboursementServiceProfilService.getEtat(): appelleGET /api/profil/etatet retourneEtatProfilDto- Requirements: 1.2, 9.3, 9.4, 16.2
-
* 14.3 Écrire les tests unitaires des services
- Mock HttpClient, comportement du TimeoutInterceptor
- Requirements: 1.9
-
-
15. Saisie et édition des trajets (frontend)
-
15.1 Implémenter
TrajetFormComponent- Reactive Form (date, adresses 1–255, commentaire 0–500), validations synchrones, mode création/édition/insertion, autocomplétion BAN dès 3 car. + stockage coordonnées, boutons « Utiliser mon domicile », avertissement saisie manuelle sans coordonnées
- Requirements: 1.1, 1.4, 1.5, 1.8, 1.10, 1.13, 1.14, 1.15, 1.16, 1.17, 5.1, 10.4, 10.5, 10.6, 11.1, 11.2, 11.3, 11.4
-
15.2 Implémenter
TrajetListComponent- Liste triée par Position, actions modifier/supprimer (avec
ConfirmDialog)/insérer après/insérer avant le suivant, drag & drop →PATCH reordonner, rafraîchissement < 1 000 ms, icône + tooltip commentaire - Requirements: 5.1, 5.4, 5.7, 11.6, 11.9
- Liste triée par Position, actions modifier/supprimer (avec
-
* 15.3 Écrire les tests des composants de saisie
- Validation, autocomplétion BAN, mode insertion pré-rempli, drag & drop, tri par Position
- Requirements: 1.4, 1.5, 1.13, 11.1, 11.6
-
-
16. Consultation, navigation temporelle et carte (frontend)
-
16.1 Implémenter
SelecteurTemporelComponent- Sélecteurs année/mois/jour avec surbrillance des périodes ayant des données, désactivation des dates futures
- Requirements: 12.1, 12.2, 12.3, 12.4, 12.5
-
16.2 Implémenter
PanneauTotauxComponent- Totaux jour/mois/Total_Annuel_Partiel à 2 décimales, Montant_Previsionnel 80% indicatif, recalcul au changement
- Requirements: 12.7, 12.8, 13.5, 13.6, 13.7, 13.8
-
16.3 Implémenter
CarteTrajetsComponent- Leaflet + tuiles OpenStreetMap, tracés GeoJSON par trajet, fallback ligne droite, infobulles, zoom/déplacement, message si vide ou carte indisponible
- Requirements: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.8
-
16.4 Implémenter
ConsultationJourComponent(layout principal)- Deux colonnes (liste scrollable + panneau sticky totaux/carte), boutons jour ±1 (« suivant » désactivé si futur), sélecteur de véhicule filtrant liste/totaux/carte, rafraîchissement < 1 000 ms
- Requirements: 12.6, 12.9, 12.10, 12.11, 12.12, 12.13, 12.14, 12.17, 12.18, 12.20
-
* 16.5 Écrire les tests des composants de consultation
- Surbrillance/dates futures, 3 totaux + prévisionnel, tracés carte + fallback, layout et filtrage par véhicule
- Requirements: 8.2, 8.5, 12.5, 12.8, 12.18
-
-
17. Profil, véhicules, barème et montants réglés (frontend)
-
17.1 Implémenter
ProfilComponent,VehiculesComponentetReaffectationDialogComponent- Profil (nom/prénom/matricule 8 car./domicile) + avertissement géocodage ; historique véhicules trié, ajout avec DateEffet ≤ aujourd'hui, dialog de réaffectation (nombre de trajets, accepter/refuser)
- Requirements: 10.1, 10.2, 10.8, 10.9, 10.10, 10.11, 10.15, 10.16, 10.17
-
17.2 Implémenter
BaremeComponentetMontantsReglesComponent- Saisie des 3 tranches par puissance fiscale/année avec détection de chevauchement ; saisie Montant_Regle par mois + prévisionnel indicatif, rejet négatif, montants 2 décimales
- Requirements: 13.1, 13.7, 14.1, 14.4, 14.8
-
17.3 Implémenter
ResumeMensuelComponentetResumeAnnuelComponent- Résumé mensuel (liste + total 2 décimales, bouton export), résumé annuel (12 lignes + total ≤ 999 999,99, bouton export), déclenchement téléchargement PDF + gestion d'erreur
- Requirements: 3.1, 3.5, 3.7, 4.1, 4.5, 4.6, 7.3
-
* 17.4 Écrire les tests des composants profil/véhicules/barème/montants/résumés
- Matricule 8 car., date effet future bloquée, dialog réaffectation, chevauchement barème, montant négatif rejeté, affichage 2 décimales et max annuel
- Requirements: 4.5, 10.2, 10.11, 13.1, 14.4
-
-
18. Checkpoint final — S'assurer que tous les tests passent
- Ensure all tests pass, ask the user if questions arise.
-
19. Carnet d'adresses nommées (backend)
-
19.1 Implémenter
AdresseNommeeServiceetAdressesNommeesController- CRUD des Adresses_Nommées ; normalisation (trim + minuscules + suppression des accents) pour l'unicité de la Dénomination et le matching du Cache_Adresses
- Réutilisation du Cache_Adresses si l'adresse normalisée y est présente (sans appel BAN) ; sinon géocodage/re-géocodage via BAN (timeout 5 s)
- Si BAN indisponible/timeout : persistance sans coordonnées +
GeocodageReussi = falseet réponse indiquant l'absence de coordonnées ; mise en cache des coordonnées obtenues - Suppression sans impact sur les Trajets existants (conservation de leur adresse et coordonnées)
- Endpoints
GET/POST/PUT/DELETE /api/adresses-nommees - Requirements: 15.1, 15.4, 15.5, 15.6, 15.7, 15.8, 15.9, 15.10, 15.11, 15.12, 15.14
-
* 19.2 Écrire le test de propriété d'unicité de la dénomination
- Property 28 : Unicité normalisée de la dénomination
- Validates: Requirements 15.6, 15.7
-
* 19.3 Écrire le test de propriété de préservation des trajets à la suppression
- Property 29 : Préservation des trajets à la suppression d'une adresse nommée
- Validates: Requirements 15.14
-
* 19.4 Écrire le test de propriété de réutilisation du cache et cohérence du géocodage
- Property 30 : Réutilisation du cache et cohérence du géocodage des adresses nommées
- Validates: Requirements 15.9, 15.10, 15.11, 15.12
-
-
20. Carnet d'adresses nommées (frontend)
-
20.1 Implémenter
AdresseNommeeService(Angular) etCarnetAdressesComponentAdresseNommeeService:getAdressesNommees,create,update,delete(HTTP)CarnetAdressesComponent: liste triée par Dénomination, formulaire de création/modification avec autocomplétion BAN (min 3 car., debounce 300 ms, max 5 suggestions), confirmation de suppression, message de succès CRUD, avertissement si le géocodage a échoué- Requirements: 15.1, 15.2, 15.3, 15.4, 15.11, 15.13, 15.15
-
20.2 Étendre
TrajetFormComponentavec le sélecteur d'Adresse_Nommee- Pour les champs adresse de départ et adresse d'arrivée, ajouter un sélecteur d'Adresse_Nommee (par Dénomination) en mode création ET insertion
- À la sélection, remplir le champ + associer les coordonnées (remplace le contenu pré-rempli en mode insertion)
- Requirements: 1.18, 1.19, 11.10, 11.11, 15.16
-
* 20.3 Écrire les tests des composants carnet et du sélecteur dans le formulaire
- Composant Carnet_Adresses (liste, formulaire, confirmation, message), sélecteur d'Adresse_Nommee dans
TrajetFormComponent - Requirements: 15.2, 15.13, 1.19
- Composant Carnet_Adresses (liste, formulaire, confirmation, message), sélecteur d'Adresse_Nommee dans
-
-
21. Onboarding profil à la première utilisation (frontend)
-
21.1 Implémenter
OnboardingComponent- Formulaire une étape : identité (nom, prénom, matricule), Adresse_Domicile optionnelle avec autocomplétion BAN, au moins un Véhicule (plaque, puissance fiscale, date d'effet ≤ aujourd'hui)
- Bouton « Commencer » désactivé tant que les champs requis manquent
- À l'enregistrement réussi du profil + véhicule → navigation vers la vue de consultation
- Gestion d'erreur de persistance : message d'erreur + conservation des données saisies
- Requirements: 16.3, 16.5, 16.6, 16.7, 16.8, 16.9, 16.10, 16.12
-
21.2 Implémenter le guard
ProfilConfigureGuard(CanActivate)- Appelle
ProfilService.getEtat()au chargement ; redirige vers/onboardingsiEstConfigure = falseet bloque l'accès aux routes trajets/consultation ; laisse passer sitrue - Gère l'échec de récupération de l'état par un message de connexion + action « Réessayer »
- Déclarer le guard sur les routes protégées dans
app-routing - Requirements: 16.3, 16.4, 16.11, 16.13
- Appelle
-
* 21.3 Écrire les tests du parcours d'onboarding et du guard
- Bouton « Commencer » désactivé, navigation après enregistrement, redirection du guard, cas
EstConfiguretrue/false, erreur + retry - Requirements: 16.3, 16.8, 16.10, 16.11, 16.13
- Bouton « Commencer » désactivé, navigation après enregistrement, redirection du guard, cas
-
-
22. Conteneurisation et déploiement Docker Compose
-
22.1 Écrire le
Dockerfilebackend multi-stage- Étape build (SDK) → étape runtime (aspnet), exposition du port 8080
- Base SQLite sous le volume
/data/trajets.dbviaConnectionStrings__Default - Application automatique des migrations EF Core au démarrage (
Database.MigrateAsync()dansProgram.cs) - Endpoint de santé
GET /health(AddHealthChecks/MapHealthChecks) - Requirements: 6.1
-
22.2 Écrire le
Dockerfilefrontend multi-stage et la configurationnginx.conf- Étape build (node) → étape serve (nginx)
nginx.conf: fallback SPA versindex.html+ reverse-proxy/apiversbackend:8080
-
22.3 Écrire le
docker-compose.yml- Services backend + frontend, volume nommé
trajets-data:/datapour la persistance SQLite - Clé ORS via variable d'environnement
${ORS_API_KEY}depuis un fichier.envnon commité - Mapping hôte 8080 → nginx,
depends_on: service_healthy,restart: unless-stopped, healthcheck backend - Ajouter
.envau.gitignore
- Services backend + frontend, volume nommé
-
Notes
- Les tâches marquées
*sont optionnelles (tests unitaires, tests de propriété, tests d'intégration) et peuvent être ignorées pour un MVP plus rapide ; les tâches d'implémentation cœur ne le sont jamais. - Chaque tâche référence des exigences précises pour la traçabilité ; les sous-tâches de test de propriété référencent explicitement la propriété de correction validée (numéro + exigences).
- Les 31 propriétés de correction sont couvertes par des tests FsCheck (backend) répartis au plus près de leur implémentation pour détecter les erreurs tôt.
- La clé ORS n'est jamais commitée : User Secrets en développement, variables d'environnement en production.
- Les checkpoints garantissent une validation incrémentale du backend puis du frontend.
Task Dependency Graph
{
"waves": [
{ "id": 0, "tasks": ["1"] },
{ "id": 1, "tasks": ["2.1"] },
{ "id": 2, "tasks": ["2.2", "3.1"] },
{ "id": 3, "tasks": ["2.3", "3.2", "4.1", "4.2"] },
{ "id": 4, "tasks": ["3.3", "4.3", "5.1", "6.1", "6.5"] },
{ "id": 5, "tasks": ["4.4", "4.5", "5.2", "5.3", "6.2", "6.3", "6.4", "6.6", "6.7", "8.1"] },
{ "id": 6, "tasks": ["8.2", "10.1", "19.1"] },
{ "id": 7, "tasks": ["8.3", "8.4", "8.5", "10.2", "10.3", "19.2", "19.3", "19.4"] },
{ "id": 8, "tasks": ["8.6", "8.7", "8.8", "10.4", "10.5"] },
{ "id": 9, "tasks": ["8.9", "9.1", "9.3", "10.6", "11.1", "11.2"] },
{ "id": 10, "tasks": ["9.2", "9.4", "9.5", "11.3"] },
{ "id": 11, "tasks": ["11.4", "11.5", "13.1", "13.2"] },
{ "id": 12, "tasks": ["14.1", "22.1"] },
{ "id": 13, "tasks": ["14.2"] },
{ "id": 14, "tasks": ["14.3", "15.1", "16.1", "16.3", "17.1", "20.1", "21.1"] },
{ "id": 15, "tasks": ["15.2", "16.2", "16.4", "17.2", "17.3", "20.2", "21.2", "22.2"] },
{ "id": 16, "tasks": ["15.3", "16.5", "17.4", "20.3", "21.3", "22.3"] }
]
}