Exports PDF : total mensuel à fin de mois et mise en avant de la régularisation

Report mensuel :
- « Total parcouru sur l'année » devient « Total annuel (à fin de mois) »
  et affiche le cumul jusqu'au mois de restitution inclus
  (Total_Annuel_Partiel, via ITotauxService)
- la tranche de barème (coefficient, base, TOTAL IK du mois) est
  déterminée sur ce même cumul, cohérent avec le Panneau_Totaux du site
  et stable même si le PDF est édité plus tard

Report annuel :
- ligne « Formule réelle » centrée (comme la régularisation)
- ligne « Régularisation (réel − payé) » agrandie (14 pt, gras) pour la
  mettre en avant comme action finale

Test d'intégration PDF mis à jour (injection d'ITotauxService). Specs
requirements/design-requirements/design synchronisées (Exigence 7).
This commit is contained in:
2026-10-13 07:08:12 +02:00
parent df259258a0
commit 0e14a8f806
5 changed files with 28 additions and 14 deletions
@@ -30,6 +30,7 @@ public class PdfService : IPdfService
private readonly IMontantRegleService _montantRegleService;
private readonly IRemboursementService _remboursementService;
private readonly IPrecisionDistanceService _precisionDistanceService;
private readonly ITotauxService _totauxService;
private readonly AppDbContext _context;
/// <summary>Logo carré, chargé une seule fois depuis la ressource embarquée (Assets/logo-carre.png).</summary>
@@ -43,6 +44,7 @@ public class PdfService : IPdfService
IMontantRegleService montantRegleService,
IRemboursementService remboursementService,
IPrecisionDistanceService precisionDistanceService,
ITotauxService totauxService,
AppDbContext context)
{
_resumeService = resumeService;
@@ -52,6 +54,7 @@ public class PdfService : IPdfService
_montantRegleService = montantRegleService;
_remboursementService = remboursementService;
_precisionDistanceService = precisionDistanceService;
_totauxService = totauxService;
_context = context;
}
@@ -228,11 +231,15 @@ public class PdfService : IPdfService
// Résumé mensuel filtré sur le véhicule (trajets triés + total km du mois).
var resumeMensuel = await _resumeService.GetResumeMensuelAsync(annee, mois, vehiculeId, cancellationToken);
// Total kilométrique annuel cumulé (tous mois de l'année, même véhicule).
var resumeAnnuel = await _resumeService.GetResumeAnnuelAsync(annee, vehiculeId, cancellationToken);
var totalKmAnnuel = resumeAnnuel.TotalKm;
// Total annuel « à fin de mois » : cumul de l'année jusqu'au mois de restitution INCLUS
// (Total_Annuel_Partiel), cohérent avec le Panneau_Totaux du site et avec la situation à la
// date du mois — y compris si le PDF est édité plusieurs mois plus tard. Les distances
// sommées sont déjà arrondies selon Precision_Distance et tiennent compte des allers/retours.
var totaux = await _totauxService.GetTotauxAsync(new DateOnly(annee, mois, 1), vehiculeId, cancellationToken);
var totalKmAnnuel = totaux.TotalAnnuelPartiel;
// Coefficient et base de la tranche ANNUELLE applicable (déterminée par le total annuel).
// Coefficient et base de la tranche applicable, déterminée par ce même cumul « à fin de mois »
// (et non par le total des 12 mois), pour rester cohérent avec l'affichage du site.
var bareme = await _baremeService.CalculerMontantAsync(
annee, vehicule.PuissanceFiscale, totalKmAnnuel, cancellationToken);
@@ -420,7 +427,7 @@ public class PdfService : IPdfService
});
c.Item().Text(txt =>
{
txt.Span("Total parcouru sur l'année : ").SemiBold();
txt.Span("Total annuel (à fin de mois) : ").SemiBold();
txt.Span($"{FormatKm(modele.TotalKmAnnuel, precision)} km");
});
});
@@ -765,14 +772,17 @@ public class PdfService : IPdfService
container.Column(col =>
{
col.Spacing(3);
col.Item().Text(txt =>
// Formule réelle centrée (comme la régularisation).
col.Item().AlignCenter().Text(txt =>
{
txt.Span("Formule réelle : ").SemiBold();
txt.Span(formule);
});
// Espace entre la formule réelle et la régularisation, puis régularisation centrée.
// Espace puis régularisation centrée, mise en avant (14 pt) car c'est l'action
// comptable finale à entreprendre (régulariser les frais).
col.Item().PaddingTop(8).AlignCenter().Text(txt =>
{
txt.DefaultTextStyle(x => x.FontSize(14));
txt.Span("Régularisation (réel − payé) : ").SemiBold();
txt.Span($"{FormatMontant(reg.Regularisation)} €");
});