- 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.
433 lines
29 KiB
Markdown
433 lines
29 KiB
Markdown
# 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
|
||
|
||
- [x] 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, middleware `ProblemDetails`, CORS pour le frontend Angular
|
||
- _Requirements: 6.1_
|
||
|
||
- [x] 2. Modèle de données et contexte EF Core
|
||
- [x] 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_
|
||
|
||
- [x] 2.2 Configurer `AppDbContext` et 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 `AdressesNommees` avec l'index unique `UX_AdresseNommee_Denomination` sur `DenominationNormalisee`
|
||
- Générer la migration initiale et l'appliquer à `trajets.db`
|
||
- _Requirements: 6.1, 6.2, 9.6, 14.3, 15.6_
|
||
|
||
- [ ]* 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_
|
||
|
||
- [x] 3. DTOs, options de configuration et validateurs
|
||
- [x] 3.1 Créer les DTOs et enregistrements
|
||
- `CreateTrajetDto`, `UpdateTrajetDto`, `TrajetDto`, `TrajetCarteDto`, `ReordonnerTrajetsDto`, `TrajetPositionDto`
|
||
- `ResumeMensuelDto`, `ResumeAnnuelDto`, `TotauxDto`, `AdresseCacheDto`, `BANAdresseDto`
|
||
- `ProfilDto`, `SaveProfilDto`, `VehiculeDto`, `CreateVehiculeDto`, `VehiculeCreeDto`, `ReaffectationDto`
|
||
- `TrancheBaremeDto`, `SaveTrancheBaremeDto`, `MontantRegleDto`, `MontantPrevisionnelDto`, `LigneSyntheseMoisDto`, `RegularisationAnnuelleDto`
|
||
- `AdresseNommeeDto`, `SaveAdresseNommeeDto`
|
||
- `EtatProfilDto` (EstConfigure)
|
||
- Créer `BANOptions` et `ORSOptions`, les lier depuis `appsettings.json`
|
||
- _Requirements: 1.1, 1.10, 2.1, 15.4, 15.5_
|
||
|
||
- [x] 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**
|
||
|
||
- [x] 4. Intégrations externes : BAN et ORS
|
||
- [x] 4.1 Implémenter `IBANClient` / `BANClient`
|
||
- Appel `GET /search/?q={query}&limit=5` avec timeout configurable ; mapper vers `BANAdresseDto` ; lever `BANIndisponibleException` en cas d'échec/timeout
|
||
- _Requirements: 1.13, 2.4, 9.1_
|
||
|
||
- [x] 4.2 Implémenter `IORSClient` / `ORSClient`
|
||
- Appel `POST /v2/directions/driving-car` avec 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 5. Cache des adresses géocodées
|
||
- [x] 5.1 Implémenter `AdresseCacheService` et 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_
|
||
|
||
- [ ]* 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**
|
||
|
||
- [x] 6. Gestion des véhicules et du profil
|
||
- [x] 6.1 Implémenter `VehiculeService` et 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**
|
||
|
||
- [x] 6.5 Implémenter `ProfilService` et le controller `ProfilController`
|
||
- 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/etat` retournant `EtatProfilDto(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**
|
||
|
||
- [x] 7. Checkpoint — S'assurer que tous les tests passent
|
||
- Ensure all tests pass, ask the user if questions arise.
|
||
|
||
- [x] 8. Service et API des trajets (CRUD + positions)
|
||
- [x] 8.1 Implémenter `TrajetRepository` et 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [ ]* 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**
|
||
|
||
- [x] 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/reordonner` met à 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**
|
||
|
||
- [x] 8.8 Implémenter `TrajetsController` et brancher le controller adresses
|
||
- `POST/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**
|
||
|
||
- [x] 9. Résumés, totaux et navigation temporelle
|
||
- [x] 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**
|
||
|
||
- [x] 9.3 Implémenter `TotauxService` et 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**
|
||
|
||
- [x] 9.5 Implémenter `ResumesController` et les controllers de navigation
|
||
- `GET /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_
|
||
|
||
- [x] 10. Barème kilométrique et régularisation
|
||
- [x] 10.1 Implémenter `BaremeService` et 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**
|
||
|
||
- [x] 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**
|
||
|
||
- [x] 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**
|
||
|
||
- [x] 11. Export PDF (QuestPDF)
|
||
- [x] 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 11.3 Implémenter `ExportsPdfController`
|
||
- `GET /api/exports/mensuel/{annee}/{mois}` et `GET /api/exports/annuel/{annee}` ; en-tête Content-Disposition `trajets_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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 14. Socle frontend Angular et services
|
||
- [x] 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_
|
||
|
||
- [x] 14.2 Implémenter les services HTTP Angular
|
||
- `TrajetService`, `VehiculeService`, `BANService` (autocomplétion), `AdresseCacheService`, `ProfilService`, `BaremeService`, `RemboursementService`
|
||
- `ProfilService.getEtat()` : appelle `GET /api/profil/etat` et retourne `EtatProfilDto`
|
||
- _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_
|
||
|
||
- [x] 15. Saisie et édition des trajets (frontend)
|
||
- [x] 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [ ]* 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_
|
||
|
||
- [x] 16. Consultation, navigation temporelle et carte (frontend)
|
||
- [x] 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 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_
|
||
|
||
- [x] 17. Profil, véhicules, barème et montants réglés (frontend)
|
||
- [x] 17.1 Implémenter `ProfilComponent`, `VehiculesComponent` et `ReaffectationDialogComponent`
|
||
- 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_
|
||
|
||
- [x] 17.2 Implémenter `BaremeComponent` et `MontantsReglesComponent`
|
||
- 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_
|
||
|
||
- [x] 17.3 Implémenter `ResumeMensuelComponent` et `ResumeAnnuelComponent`
|
||
- 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_
|
||
|
||
- [x] 18. Checkpoint final — S'assurer que tous les tests passent
|
||
- Ensure all tests pass, ask the user if questions arise.
|
||
|
||
- [x] 19. Carnet d'adresses nommées (backend)
|
||
- [x] 19.1 Implémenter `AdresseNommeeService` et `AdressesNommeesController`
|
||
- 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 = false` et 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**
|
||
|
||
- [x] 20. Carnet d'adresses nommées (frontend)
|
||
- [x] 20.1 Implémenter `AdresseNommeeService` (Angular) et `CarnetAdressesComponent`
|
||
- `AdresseNommeeService` : `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_
|
||
|
||
- [x] 20.2 Étendre `TrajetFormComponent` avec 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_
|
||
|
||
- [x] 21. Onboarding profil à la première utilisation (frontend)
|
||
- [x] 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_
|
||
|
||
- [x] 21.2 Implémenter le guard `ProfilConfigureGuard` (CanActivate)
|
||
- Appelle `ProfilService.getEtat()` au chargement ; redirige vers `/onboarding` si `EstConfigure = false` et bloque l'accès aux routes trajets/consultation ; laisse passer si `true`
|
||
- 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_
|
||
|
||
- [ ]* 21.3 Écrire les tests du parcours d'onboarding et du guard
|
||
- Bouton « Commencer » désactivé, navigation après enregistrement, redirection du guard, cas `EstConfigure` true/false, erreur + retry
|
||
- _Requirements: 16.3, 16.8, 16.10, 16.11, 16.13_
|
||
|
||
- [x] 22. Conteneurisation et déploiement Docker Compose
|
||
- [x] 22.1 Écrire le `Dockerfile` backend multi-stage
|
||
- Étape build (SDK) → étape runtime (aspnet), exposition du port 8080
|
||
- Base SQLite sous le volume `/data/trajets.db` via `ConnectionStrings__Default`
|
||
- Application automatique des migrations EF Core au démarrage (`Database.MigrateAsync()` dans `Program.cs`)
|
||
- Endpoint de santé `GET /health` (`AddHealthChecks` / `MapHealthChecks`)
|
||
- _Requirements: 6.1_
|
||
|
||
- [x] 22.2 Écrire le `Dockerfile` frontend multi-stage et la configuration `nginx.conf`
|
||
- Étape build (node) → étape serve (nginx)
|
||
- `nginx.conf` : fallback SPA vers `index.html` + reverse-proxy `/api` vers `backend:8080`
|
||
|
||
- [x] 22.3 Écrire le `docker-compose.yml`
|
||
- Services backend + frontend, volume nommé `trajets-data:/data` pour la persistance SQLite
|
||
- Clé ORS via variable d'environnement `${ORS_API_KEY}` depuis un fichier `.env` non commité
|
||
- Mapping hôte 8080 → nginx, `depends_on: service_healthy`, `restart: unless-stopped`, healthcheck backend
|
||
- Ajouter `.env` au `.gitignore`
|
||
|
||
## 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
|
||
|
||
```json
|
||
{
|
||
"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"] }
|
||
]
|
||
}
|
||
```
|