Files
SchotzIAD/backend/SchotzIadKmTracker.Api/Services/TotauxService.cs
T
MadJax 0e6a97ca61 Renommage : TrajetKmTracker -> SchotzIadKmTracker (backend, specs, frontend)
- 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.
2026-09-14 07:50:26 +02:00

111 lines
4.1 KiB
C#

using Microsoft.EntityFrameworkCore;
using SchotzIadKmTracker.Api.Data;
using SchotzIadKmTracker.Api.Models.DTOs;
namespace SchotzIadKmTracker.Api.Services;
/// <inheritdoc />
public class TotauxService : ITotauxService
{
private readonly AppDbContext _context;
private readonly IVehiculeService _vehiculeService;
public TotauxService(AppDbContext context, IVehiculeService vehiculeService)
{
_context = context;
_vehiculeService = vehiculeService;
}
/// <inheritdoc />
public async Task<TotauxDto> GetTotauxAsync(
DateOnly date, int? vehiculeId = null, CancellationToken cancellationToken = default)
{
// Véhicule cible : celui fourni, sinon le Véhicule_Courant (Exigence 12.19).
var vehiculeCible = vehiculeId
?? (await _vehiculeService.GetVehiculeCourantAsync(cancellationToken)).Id;
// Trajets du véhicule pour l'année sélectionnée (Property 21 : filtrage par véhicule).
// Distance nullable → 0 lors des sommes (traitée côté client après projection).
var trajetsAnnee = await _context.Trajets
.AsNoTracking()
.Where(t => t.VehiculeId == vehiculeCible && t.Date.Year == date.Year)
.Select(t => new { t.Date, Distance = (decimal?)t.Distance ?? 0m })
.ToListAsync(cancellationToken);
// TotalJour : somme des distances de la journée sélectionnée (Exigence 12.7).
var totalJour = trajetsAnnee
.Where(t => t.Date == date)
.Sum(t => t.Distance);
// TotalMois : somme des distances du mois de la date sélectionnée (Exigence 12.7).
var totalMois = trajetsAnnee
.Where(t => t.Date.Month == date.Month)
.Sum(t => t.Distance);
// Total_Annuel_Partiel : cumul de l'année jusqu'au mois sélectionné INCLUS,
// exclusion des mois strictement postérieurs (Exigence 12.8, Property 17).
var totalAnnuelPartiel = trajetsAnnee
.Where(t => t.Date.Month <= date.Month)
.Sum(t => t.Distance);
return new TotauxDto(
Date: date,
VehiculeId: vehiculeCible,
TotalJour: Math.Round(totalJour, 2, MidpointRounding.AwayFromZero),
TotalMois: Math.Round(totalMois, 2, MidpointRounding.AwayFromZero),
TotalAnnuelPartiel: Math.Round(totalAnnuelPartiel, 2, MidpointRounding.AwayFromZero));
}
/// <inheritdoc />
public async Task<IReadOnlyList<int>> GetAnneesDisponiblesAsync(CancellationToken cancellationToken = default)
{
// Années comportant au moins un Trajet (Exigence 12.15).
var annees = await _context.Trajets
.AsNoTracking()
.Select(t => t.Date.Year)
.Distinct()
.ToListAsync(cancellationToken);
// Ajout de l'année courante si absente.
var anneeCourante = DateOnly.FromDateTime(DateTime.Today).Year;
if (!annees.Contains(anneeCourante))
{
annees.Add(anneeCourante);
}
annees.Sort();
return annees;
}
/// <inheritdoc />
public async Task<IReadOnlyList<int>> GetMoisDisponiblesAsync(int annee, CancellationToken cancellationToken = default)
{
// Mois de l'année comportant au moins un Trajet (Exigence 12.16).
var mois = await _context.Trajets
.AsNoTracking()
.Where(t => t.Date.Year == annee)
.Select(t => t.Date.Month)
.Distinct()
.ToListAsync(cancellationToken);
mois.Sort();
return mois;
}
/// <inheritdoc />
public async Task<IReadOnlyList<int>> GetJoursDisponiblesAsync(
int annee, int mois, CancellationToken cancellationToken = default)
{
// Jours du mois comportant au moins un Trajet (Exigence 12.16).
var jours = await _context.Trajets
.AsNoTracking()
.Where(t => t.Date.Year == annee && t.Date.Month == mois)
.Select(t => t.Date.Day)
.Distinct()
.ToListAsync(cancellationToken);
jours.Sort();
return jours;
}
}