< Summary

Information
Class: FAU.API.Controllers.FranjaIrpfController
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/FranjaIrpfController.cs
Line coverage
70%
Covered lines: 46
Uncovered lines: 19
Coverable lines: 65
Total lines: 171
Line coverage: 70.7%
Branch coverage
62%
Covered branches: 31
Total branches: 50
Branch coverage: 62%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ListarFranjas()100%22100%
ObtenerPorId()100%2262.5%
Crear()78.57%191471.42%
Actualizar()37.5%421653.33%
Eliminar()62.5%251666.66%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/FranjaIrpfController.cs

#LineLine coverage
 1using System.Security.Claims;
 2using FAU.Logica.DTOs;
 3using FAU.Logica.Services;
 4using Microsoft.AspNetCore.Authorization;
 5using Microsoft.AspNetCore.Mvc;
 6
 7namespace FAU.API.Controllers;
 8
 9/// <summary>
 10/// Gestión CRUD de franjas IRPF (7 tramos de impuesto a la renta)
 11/// </summary>
 12[ApiController]
 13[Route("api/irpf/franjas")]
 14[Authorize(Roles = "Administrador")]
 15public class FranjaIrpfController : ControllerBase
 16{
 17    private readonly IFranjasIrpfService _franjasService;
 18    private readonly ILogger<FranjaIrpfController> _logger;
 19
 1420    public FranjaIrpfController(
 1421        IFranjasIrpfService franjasService,
 1422        ILogger<FranjaIrpfController> logger)
 23    {
 1424        _franjasService = franjasService;
 1425        _logger = logger;
 1426    }
 27
 28    /// <summary>
 29    /// Listar franjas IRPF vigentes en una fecha (defecto: hoy)
 30    /// GET /api/irpf/franjas?fecha=2026-01-01
 31    /// </summary>
 32    [HttpGet]
 33    public async Task<IActionResult> ListarFranjas([FromQuery] DateTime? fecha = null)
 34    {
 35        try
 36        {
 337            fecha ??= DateTime.UtcNow.Date;
 338            var franjas = await _franjasService.ObtenerFranjasVigentesAsync(fecha.Value);
 39
 240            return Ok(ApiResponse<object>.SuccessResult(franjas));
 41        }
 142        catch (Exception ex)
 43        {
 144            _logger.LogError(ex, "Error al listar franjas IRPF vigentes");
 145            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 46        }
 347    }
 48
 49    /// <summary>
 50    /// Obtener una franja IRPF por ID
 51    /// GET /api/irpf/franjas/{id}
 52    /// </summary>
 53    [HttpGet("{id}")]
 54    public async Task<IActionResult> ObtenerPorId(long id)
 55    {
 56        try
 57        {
 258            var franja = await _franjasService.ObtenerPorIdAsync(id);
 259            if (franja == null)
 160                return NotFound(ApiResponse<string>.ErrorResult("Franja IRPF no encontrada"));
 61
 162            return Ok(ApiResponse<object>.SuccessResult(franja));
 63        }
 064        catch (Exception ex)
 65        {
 066            _logger.LogError(ex, "Error al obtener franja IRPF {FranjaId}", id);
 067            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 68        }
 269    }
 70
 71    /// <summary>
 72    /// Crear una nueva franja IRPF
 73    /// POST /api/irpf/franjas
 74    /// Cierra automáticamente la franja anterior si existe vigencia igual
 75    /// </summary>
 76    [HttpPost]
 77    public async Task<IActionResult> Crear([FromBody] CrearFranjaIrpfRequest request)
 78    {
 79        try
 80        {
 381            var usuarioIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
 382            if (!long.TryParse(usuarioIdStr, out var usuarioId))
 183                return Unauthorized(ApiResponse<string>.ErrorResult("No se pudo identificar al usuario"));
 84
 285            var (success, franja, error) = await _franjasService.CrearAsync(usuarioId, request);
 286            if (!success)
 87            {
 188                if (!string.IsNullOrWhiteSpace(error) && error.Contains("Ya existe una franja", StringComparison.Ordinal
 089                    return Conflict(ApiResponse<string>.ErrorResult(error));
 90
 191                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al crear franja IRPF"));
 92            }
 93
 194            return CreatedAtAction(nameof(ObtenerPorId), new { id = franja?.Id },
 195                ApiResponse<object>.SuccessResult(franja, "Franja IRPF creada exitosamente"));
 96        }
 097        catch (Exception ex)
 98        {
 099            _logger.LogError(ex, "Error al crear franja IRPF");
 0100            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 101        }
 3102    }
 103
 104    /// <summary>
 105    /// Actualizar una franja IRPF existente
 106    /// PUT /api/irpf/franjas/{id}
 107    /// </summary>
 108    [HttpPut("{id}")]
 109    public async Task<IActionResult> Actualizar(long id, [FromBody] ActualizarFranjaIrpfRequest request)
 110    {
 111        try
 112        {
 2113            var usuarioIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
 2114            if (!long.TryParse(usuarioIdStr, out var usuarioId))
 0115                return Unauthorized(ApiResponse<string>.ErrorResult("No se pudo identificar al usuario"));
 116
 2117            var (success, franja, error) = await _franjasService.ActualizarAsync(id, usuarioId, request);
 2118            if (!success)
 119            {
 1120                if (!string.IsNullOrWhiteSpace(error) && error.Contains("no encontrada", StringComparison.OrdinalIgnoreC
 1121                    return NotFound(ApiResponse<string>.ErrorResult(error));
 122
 0123                if (!string.IsNullOrWhiteSpace(error) && error.Contains("Ya existe una franja", StringComparison.Ordinal
 0124                    return Conflict(ApiResponse<string>.ErrorResult(error));
 125
 0126                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al actualizar franja IRPF"));
 127            }
 128
 1129            return Ok(ApiResponse<object>.SuccessResult(franja, "Franja IRPF actualizada exitosamente"));
 130        }
 0131        catch (Exception ex)
 132        {
 0133            _logger.LogError(ex, "Error al actualizar franja IRPF {FranjaId}", id);
 0134            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 135        }
 2136    }
 137
 138    /// <summary>
 139    /// Eliminar una franja IRPF (solo si no está en uso en liquidaciones cerradas)
 140    /// DELETE /api/irpf/franjas/{id}
 141    /// </summary>
 142    [HttpDelete("{id}")]
 143    public async Task<IActionResult> Eliminar(long id)
 144    {
 145        try
 146        {
 3147            var usuarioIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
 3148            if (!long.TryParse(usuarioIdStr, out var usuarioId))
 0149                return Unauthorized(ApiResponse<string>.ErrorResult("No se pudo identificar al usuario"));
 150
 3151            var (success, error) = await _franjasService.EliminarAsync(id, usuarioId);
 3152            if (!success)
 153            {
 2154                if (!string.IsNullOrWhiteSpace(error) && error.Contains("no encontrada", StringComparison.OrdinalIgnoreC
 1155                    return NotFound(ApiResponse<string>.ErrorResult(error));
 156
 1157                if (!string.IsNullOrWhiteSpace(error) && error.Contains("liquidaciones cerradas", StringComparison.Ordin
 1158                    return Conflict(ApiResponse<string>.ErrorResult(error));
 159
 0160                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al eliminar franja IRPF"));
 161            }
 162
 1163            return NoContent();
 164        }
 0165        catch (Exception ex)
 166        {
 0167            _logger.LogError(ex, "Error al eliminar franja IRPF {FranjaId}", id);
 0168            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 169        }
 3170    }
 171}