using Microsoft.EntityFrameworkCore;
using TrajetKmTracker.Api.Data;
using TrajetKmTracker.Api.Models.DTOs;
namespace TrajetKmTracker.Api.Services;
///
public class TotauxService : ITotauxService
{
private readonly AppDbContext _context;
private readonly IVehiculeService _vehiculeService;
public TotauxService(AppDbContext context, IVehiculeService vehiculeService)
{
_context = context;
_vehiculeService = vehiculeService;
}
///
public async Task 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));
}
///
public async Task> 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;
}
///
public async Task> 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;
}
///
public async Task> 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;
}
}