- 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.
88 lines
4.5 KiB
C#
88 lines
4.5 KiB
C#
using SchotzIadKmTracker.Api.Models.Entities;
|
|
|
|
namespace SchotzIadKmTracker.Api.Repositories;
|
|
|
|
/// <summary>
|
|
/// Accès aux données des trajets et gestion des positions au sein d'une journée.
|
|
/// <para>
|
|
/// La <see cref="Trajet.Position"/> est une valeur décimale (REAL) permettant l'insertion
|
|
/// sans réordonnancement systématique : ajout en fin de journée → <c>max(Position) + 1.0</c>,
|
|
/// insertion entre deux positions P₁ et P₂ → <c>(P₁ + P₂) / 2</c>. Lorsque l'écart devient
|
|
/// trop faible (< <see cref="SeuilRenumerotation"/>), la journée est renumérotée par pas de
|
|
/// 1.0 en transaction en préservant l'ordre relatif (Property 15, Exigences 11.7/11.8).
|
|
/// </para>
|
|
/// <para>
|
|
/// Ce repository fournit uniquement les primitives d'accès et de calcul de position ;
|
|
/// la logique métier (validation, calcul de distance, mise en cache) relève de TrajetService.
|
|
/// </para>
|
|
/// </summary>
|
|
public interface ITrajetRepository
|
|
{
|
|
/// <summary>
|
|
/// Seuil de précision en deçà duquel une renumérotation de la journée est déclenchée.
|
|
/// Conforme à la conception : écart < 0.001.
|
|
/// </summary>
|
|
const decimal SeuilRenumerotation = 0.001m;
|
|
|
|
/// <summary>Retourne le trajet par identifiant, ou <c>null</c> s'il n'existe pas.</summary>
|
|
Task<Trajet?> GetByIdAsync(int id, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>Retourne les trajets d'une journée triés par <see cref="Trajet.Position"/> croissante.</summary>
|
|
Task<List<Trajet>> GetByDateAsync(DateOnly date, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Résout le véhicule applicable à la date du trajet et copie sa <c>PuissanceFiscale</c>
|
|
/// sur le trajet (dénormalisation, Exigence 10.14). Ne modifie ni <c>VehiculeId</c> ni
|
|
/// <c>PuissanceFiscale</c> si aucun véhicule n'est applicable à cette date.
|
|
/// Coordonné avec <see cref="Services.IVehiculeService.GetVehiculeADateAsync"/>.
|
|
/// </summary>
|
|
Task AppliquerVehiculeADateAsync(Trajet trajet, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Calcule la position d'un trajet ajouté en fin de journée : <c>max(Position) + 1.0</c>
|
|
/// pour la date, ou <c>1.0</c> si la journée est vide.
|
|
/// </summary>
|
|
Task<decimal> CalculerPositionFinDeJourneeAsync(DateOnly date, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Calcule la position d'un trajet inséré entre les positions <paramref name="positionPrecedente"/>
|
|
/// (P₁) et <paramref name="positionSuivante"/> (P₂) : <c>(P₁ + P₂) / 2</c>.
|
|
/// </summary>
|
|
/// <exception cref="ArgumentException">Si P₁ n'est pas strictement inférieure à P₂.</exception>
|
|
decimal CalculerPositionEntre(decimal positionPrecedente, decimal positionSuivante);
|
|
|
|
/// <summary>
|
|
/// Indique si l'écart entre deux positions adjacentes est devenu trop faible
|
|
/// (< <see cref="SeuilRenumerotation"/>) pour insérer une nouvelle valeur intermédiaire.
|
|
/// </summary>
|
|
bool NecessiteRenumerotation(decimal positionPrecedente, decimal positionSuivante);
|
|
|
|
/// <summary>Ajoute un trajet (sans persister). L'appelant gère la transaction et l'appel à <see cref="SauvegarderAsync"/>.</summary>
|
|
Task AddAsync(Trajet trajet, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>Marque un trajet existant comme modifié (sans persister).</summary>
|
|
void Update(Trajet trajet);
|
|
|
|
/// <summary>Supprime un trajet (sans persister).</summary>
|
|
void Delete(Trajet trajet);
|
|
|
|
/// <summary>Persiste les changements en attente.</summary>
|
|
Task<int> SauvegarderAsync(CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Applique un réordonnancement manuel : met à jour uniquement la <see cref="Trajet.Position"/>
|
|
/// des trajets fournis (par identifiant) sans altérer leurs autres champs, en transaction.
|
|
/// Les identifiants inconnus sont ignorés.
|
|
/// </summary>
|
|
Task ReordonnerAsync(
|
|
IReadOnlyList<(int Id, decimal Position)> positions,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Renumérote les trajets d'une journée par pas de 1.0 (1.0, 2.0, 3.0, …) en préservant
|
|
/// l'ordre relatif courant (tri par Position puis Id), en transaction. Retourne la liste
|
|
/// renumérotée triée par Position croissante (Property 15).
|
|
/// </summary>
|
|
Task<List<Trajet>> RenumeroterJourneeAsync(DateOnly date, CancellationToken cancellationToken = default);
|
|
}
|