using Microsoft.AspNetCore.Mvc; using SchotzIadKmTracker.Api.Models.DTOs; using SchotzIadKmTracker.Api.Services; using SchotzIadKmTracker.Api.Services.Exceptions; namespace SchotzIadKmTracker.Api.Controllers; /// /// Endpoints de gestion du barème kilométrique : consultation par année et CRUD des tranches. /// La validation du non-chevauchement des tranches ([KmMin, KmMax]) par (année, puissance fiscale) /// est appliquée à l'ajout et à la modification (Exigences 13.1–13.2). /// [ApiController] [Route("api/bareme")] public class BaremeController : ControllerBase { private readonly IBaremeService _baremeService; public BaremeController(IBaremeService baremeService) { _baremeService = baremeService; } /// Retourne toutes les tranches du barème pour l'année indiquée. [HttpGet("{annee:int}")] [ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)] public async Task>> GetBareme( int annee, CancellationToken cancellationToken) { var tranches = await _baremeService.GetBaremeAsync(annee, cancellationToken); return Ok(tranches); } /// /// Ajoute une tranche du barème. Rejette (400) si l'intervalle chevauche une tranche existante /// pour la même (année, puissance fiscale). /// [HttpPost] [ProducesResponseType(typeof(TrancheBaremeDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task> AddTranche( [FromBody] SaveTrancheBaremeDto dto, CancellationToken cancellationToken) { try { var tranche = await _baremeService.AddTrancheAsync(dto, cancellationToken); return CreatedAtAction(nameof(GetBareme), new { annee = tranche.Annee }, tranche); } catch (TranchesBaremeChevauchantesException ex) { return Problem(detail: ex.Message, statusCode: StatusCodes.Status400BadRequest); } } /// /// Met à jour une tranche existante. Rejette (400) en cas de chevauchement, 404 si la tranche est absente. /// [HttpPut("{id:int}")] [ProducesResponseType(typeof(TrancheBaremeDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> UpdateTranche( int id, [FromBody] SaveTrancheBaremeDto dto, CancellationToken cancellationToken) { try { var tranche = await _baremeService.UpdateTrancheAsync(id, dto, cancellationToken); return Ok(tranche); } catch (TrancheBaremeNotFoundException ex) { return Problem(detail: ex.Message, statusCode: StatusCodes.Status404NotFound); } catch (TranchesBaremeChevauchantesException ex) { return Problem(detail: ex.Message, statusCode: StatusCodes.Status400BadRequest); } } /// Années pour lesquelles un barème (au moins une tranche) est défini, triées croissantes. [HttpGet("annees-disponibles")] [ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)] public async Task>> GetAnneesDisponibles(CancellationToken cancellationToken) { var annees = await _baremeService.GetAnneesAvecBaremeAsync(cancellationToken); return Ok(annees); } /// /// Copie le dernier barème connu (année la plus récente antérieure ayant un barème) vers /// l'année cible. Remplace les tranches existantes de l'année cible (annule et remplace). /// Retourne le nombre de tranches copiées (0 si aucun barème antérieur n'existe). /// [HttpPost("copier/{anneeCible:int}")] [ProducesResponseType(typeof(CopieBaremeResultDto), StatusCodes.Status200OK)] public async Task> CopierDernierBareme( int anneeCible, CancellationToken cancellationToken) { var nombre = await _baremeService.CopierDernierBaremeAsync(anneeCible, cancellationToken); return Ok(new CopieBaremeResultDto(nombre)); } /// Supprime une tranche du barème. Retourne 404 si la tranche est absente. [HttpDelete("{id:int}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteTranche(int id, CancellationToken cancellationToken) { try { await _baremeService.DeleteTrancheAsync(id, cancellationToken); return NoContent(); } catch (TrancheBaremeNotFoundException ex) { return Problem(detail: ex.Message, statusCode: StatusCodes.Status404NotFound); } } }