SchotzIAD KM Tracker : suivi des trajets kilométriques (Angular + .NET 8)
Application complète de saisie et de suivi des trajets kilométriques avec calcul de distance routière (OpenRouteService), barème kilométrique, résumés et régularisation annuelle. Backend (ASP.NET Core .NET 8, EF Core, SQLite) : - Trajets (CRUD, réordonnancement, insertion), calcul de distance ORS avec fallback Haversine, géométrie d'itinéraire stockée par trajet, recalcul en masse. - Profil, véhicules (avec dénomination), carnet d'adresses nommées, cache d'adresses. - Barème kilométrique : tranches multiples par puissance fiscale, borne max exclusive avec 'illimité' (KmMax nullable), coefficient à 3 décimales, recopie du dernier barème connu. - Résumés mensuel/annuel, montants réglés, régularisation, export PDF. Frontend (Angular 22, zoneless + signals) : - Consultation par jour, navigation temporelle synchronisée, carte Leaflet, formulaire de trajet (adresses nommées, domicile, autocomplétion BAN). - Détection de changement zoneless (indépendante de zone.js). Hébergement : Docker Compose (nginx + backend), scripts run-dev.sh / run-docker.sh.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using TrajetKmTracker.Api.Models.DTOs;
|
||||
using TrajetKmTracker.Api.Services;
|
||||
|
||||
namespace TrajetKmTracker.Api.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Endpoints de navigation temporelle et de totaux du Panneau_Totaux :
|
||||
/// années/mois/jours disponibles (périodes ayant des données) et totaux
|
||||
/// jour/mois/année partiel pour une date donnée (Exigences 12.15, 12.16).
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api")]
|
||||
public class NavigationController : ControllerBase
|
||||
{
|
||||
private readonly ITotauxService _totauxService;
|
||||
|
||||
public NavigationController(ITotauxService totauxService)
|
||||
{
|
||||
_totauxService = totauxService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retourne les années comportant au moins un Trajet, complétées par l'année
|
||||
/// courante, triées croissantes (Exigence 12.15).
|
||||
/// </summary>
|
||||
[HttpGet("annees-disponibles")]
|
||||
[ProducesResponseType(typeof(IReadOnlyList<int>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<IReadOnlyList<int>>> GetAnneesDisponibles(
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var annees = await _totauxService.GetAnneesDisponiblesAsync(cancellationToken);
|
||||
return Ok(annees);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retourne les mois (1..12) de l'année comportant au moins un Trajet,
|
||||
/// triés croissants (Exigence 12.16).
|
||||
/// </summary>
|
||||
[HttpGet("mois-disponibles/{annee:int}")]
|
||||
[ProducesResponseType(typeof(IReadOnlyList<int>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<IReadOnlyList<int>>> GetMoisDisponibles(
|
||||
int annee, CancellationToken cancellationToken)
|
||||
{
|
||||
var mois = await _totauxService.GetMoisDisponiblesAsync(annee, cancellationToken);
|
||||
return Ok(mois);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retourne les jours du mois de l'année comportant au moins un Trajet,
|
||||
/// triés croissants (Exigence 12.16).
|
||||
/// </summary>
|
||||
[HttpGet("jours-disponibles/{annee:int}/{mois:int}")]
|
||||
[ProducesResponseType(typeof(IReadOnlyList<int>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<IReadOnlyList<int>>> GetJoursDisponibles(
|
||||
int annee, int mois, CancellationToken cancellationToken)
|
||||
{
|
||||
var jours = await _totauxService.GetJoursDisponiblesAsync(annee, mois, cancellationToken);
|
||||
return Ok(jours);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retourne les totaux jour/mois/année partiel du Panneau_Totaux pour la date
|
||||
/// indiquée et le véhicule (Véhicule_Courant si <paramref name="vehiculeId"/> omis).
|
||||
/// La date est attendue au format ISO <c>yyyy-MM-dd</c> ; un format invalide est
|
||||
/// rejeté avec un code HTTP 400.
|
||||
/// </summary>
|
||||
[HttpGet("totaux/{date}")]
|
||||
[ProducesResponseType(typeof(TotauxDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult<TotauxDto>> GetTotaux(
|
||||
string date, [FromQuery] int? vehiculeId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!DateOnly.TryParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.None, out var jour))
|
||||
{
|
||||
return Problem(
|
||||
detail: $"La date '{date}' est invalide. Format attendu : yyyy-MM-dd.",
|
||||
statusCode: StatusCodes.Status400BadRequest);
|
||||
}
|
||||
|
||||
var totaux = await _totauxService.GetTotauxAsync(jour, vehiculeId, cancellationToken);
|
||||
return Ok(totaux);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user