using Microsoft.EntityFrameworkCore; using SchotzIadKmTracker.Api.Data; using SchotzIadKmTracker.Api.Models.DTOs; namespace SchotzIadKmTracker.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; } }