< Summary

Information
Class: FAU.API.Controllers.IrpfController
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/IrpfController.cs
Line coverage
95%
Covered lines: 86
Uncovered lines: 4
Coverable lines: 90
Total lines: 252
Line coverage: 95.5%
Branch coverage
78%
Covered branches: 39
Total branches: 50
Branch coverage: 78%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetFranjas()100%11100%
GetFranja()100%22100%
CreateFranja()87.5%9876.92%
UpdateFranja()91.66%1212100%
DeleteFranja()75%44100%
GetDeducciones()50%66100%
GetDeduccion()100%22100%
CreateDeduccion()50%8892.3%
UpdateDeduccion()87.5%88100%

File(s)

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

#LineLine coverage
 1using FAU.Logica.DTOs;
 2using FAU.Logica.Services;
 3using Microsoft.AspNetCore.Authorization;
 4using Microsoft.AspNetCore.Mvc;
 5
 6namespace FAU.API.Controllers;
 7
 8/// <summary>
 9/// Gestión de configuración IRPF: franjas progresivas y deducciones por funcionario
 10/// </summary>
 11[ApiController]
 12[Route("api/irpf")]
 13[Authorize(Roles = "Administrador")]
 14public class IrpfController : ControllerBase
 15{
 16    private readonly IIrpfService _irpfService;
 17    private readonly ILogger<IrpfController> _logger;
 18
 2819    public IrpfController(IIrpfService irpfService, ILogger<IrpfController> logger)
 20    {
 2821        _irpfService = irpfService;
 2822        _logger = logger;
 2823    }
 24
 25    // ── Franjas ──────────────────────────────────────────────────────────────
 26
 27    /// <summary>
 28    /// Listar franjas IRPF vigentes
 29    /// GET /api/irpf/franjas?fecha=2025-01-01
 30    /// </summary>
 31    [HttpGet("franjas")]
 32    public async Task<IActionResult> GetFranjas([FromQuery] DateTime? fecha = null)
 33    {
 34        try
 35        {
 236            var franjas = await _irpfService.GetFranjasVigentesAsync(fecha);
 137            return Ok(ApiResponse<object>.SuccessResult(franjas));
 38        }
 139        catch (Exception ex)
 40        {
 141            _logger.LogError(ex, "Error al obtener franjas IRPF");
 142            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 43        }
 244    }
 45
 46    /// <summary>
 47    /// Obtener franja IRPF por ID
 48    /// GET /api/irpf/franjas/{id}
 49    /// </summary>
 50    [HttpGet("franjas/{id}")]
 51    public async Task<IActionResult> GetFranja(long id)
 52    {
 53        try
 54        {
 355            var franja = await _irpfService.GetFranjaByIdAsync(id);
 256            if (franja == null)
 157                return NotFound(ApiResponse<string>.ErrorResult("Franja no encontrada"));
 58
 159            return Ok(ApiResponse<object>.SuccessResult(franja));
 60        }
 161        catch (Exception ex)
 62        {
 163            _logger.LogError(ex, "Error al obtener franja IRPF {Id}", id);
 164            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 65        }
 366    }
 67
 68    /// <summary>
 69    /// Crear nueva franja IRPF
 70    /// POST /api/irpf/franjas
 71    /// </summary>
 72    [HttpPost("franjas")]
 73    public async Task<IActionResult> CreateFranja([FromBody] CreateFranjaIrpfRequest request)
 74    {
 75        try
 76        {
 377            var (success, franja, error) = await _irpfService.CreateFranjaAsync(request);
 378            if (!success)
 79            {
 280                if (error?.Contains("Ya existe", StringComparison.OrdinalIgnoreCase) == true)
 181                    return Conflict(ApiResponse<string>.ErrorResult(error));
 182                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al crear franja"));
 83            }
 84
 185            return CreatedAtAction(
 186                nameof(GetFranja),
 187                new { id = franja!.Id },
 188                ApiResponse<object>.SuccessResult(new { id = franja.Id, creado = true }, "Franja IRPF creada exitosament
 89        }
 090        catch (Exception ex)
 91        {
 092            _logger.LogError(ex, "Error al crear franja IRPF");
 093            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 94        }
 395    }
 96
 97    /// <summary>
 98    /// Actualizar franja IRPF
 99    /// PUT /api/irpf/franjas/{id}
 100    /// </summary>
 101    [HttpPut("franjas/{id}")]
 102    public async Task<IActionResult> UpdateFranja(long id, [FromBody] CreateFranjaIrpfRequest request)
 103    {
 104        try
 105        {
 5106            var (success, _, error) = await _irpfService.UpdateFranjaAsync(id, request);
 4107            if (!success)
 108            {
 3109                if (error?.Contains("no encontrada", StringComparison.OrdinalIgnoreCase) == true)
 1110                    return NotFound(ApiResponse<string>.ErrorResult(error));
 2111                if (error?.Contains("Ya existe", StringComparison.OrdinalIgnoreCase) == true)
 1112                    return Conflict(ApiResponse<string>.ErrorResult(error));
 1113                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al actualizar franja"));
 114            }
 115
 1116            return Ok(ApiResponse<object>.SuccessResult(new { actualizado = true }, "Franja IRPF actualizada exitosament
 117        }
 1118        catch (Exception ex)
 119        {
 1120            _logger.LogError(ex, "Error al actualizar franja IRPF {Id}", id);
 1121            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 122        }
 5123    }
 124
 125    /// <summary>
 126    /// Eliminar franja IRPF
 127    /// DELETE /api/irpf/franjas/{id}
 128    /// </summary>
 129    [HttpDelete("franjas/{id}")]
 130    public async Task<IActionResult> DeleteFranja(long id)
 131    {
 132        try
 133        {
 3134            var (success, error) = await _irpfService.DeleteFranjaAsync(id);
 2135            if (!success)
 1136                return NotFound(ApiResponse<string>.ErrorResult(error ?? "Franja no encontrada"));
 137
 1138            return NoContent();
 139        }
 1140        catch (Exception ex)
 141        {
 1142            _logger.LogError(ex, "Error al eliminar franja IRPF {Id}", id);
 1143            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 144        }
 3145    }
 146
 147    // ── Deducciones ──────────────────────────────────────────────────────────
 148
 149    /// <summary>
 150    /// Listar deducciones IRPF con filtros y paginación
 151    /// GET /api/irpf/deducciones?personaId=&tipo=&activo=&page=&pageSize=
 152    /// </summary>
 153    [HttpGet("deducciones")]
 154    public async Task<IActionResult> GetDeducciones(
 155        [FromQuery] long? personaId = null,
 156        [FromQuery] string? tipo = null,
 157        [FromQuery] bool? activo = null,
 158        [FromQuery] int page = 1,
 159        [FromQuery] int pageSize = 20)
 160    {
 161        try
 162        {
 2163            if (page < 1) page = 1;
 2164            if (pageSize < 1 || pageSize > 100) pageSize = 20;
 165
 2166            var resultado = await _irpfService.GetDeduccionesPagedAsync(page, pageSize, personaId, tipo, activo);
 1167            return Ok(ApiResponse<object>.SuccessResult(resultado));
 168        }
 1169        catch (Exception ex)
 170        {
 1171            _logger.LogError(ex, "Error al obtener deducciones IRPF");
 1172            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 173        }
 2174    }
 175
 176    /// <summary>
 177    /// Obtener deducción IRPF por ID
 178    /// GET /api/irpf/deducciones/{id}
 179    /// </summary>
 180    [HttpGet("deducciones/{id}")]
 181    public async Task<IActionResult> GetDeduccion(long id)
 182    {
 183        try
 184        {
 3185            var deduccion = await _irpfService.GetDeduccionByIdAsync(id);
 2186            if (deduccion == null)
 1187                return NotFound(ApiResponse<string>.ErrorResult("Deducción no encontrada"));
 188
 1189            return Ok(ApiResponse<object>.SuccessResult(deduccion));
 190        }
 1191        catch (Exception ex)
 192        {
 1193            _logger.LogError(ex, "Error al obtener deducción IRPF {Id}", id);
 1194            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 195        }
 3196    }
 197
 198    /// <summary>
 199    /// Crear deducción IRPF para un funcionario
 200    /// POST /api/irpf/deducciones
 201    /// </summary>
 202    [HttpPost("deducciones")]
 203    public async Task<IActionResult> CreateDeduccion([FromBody] CreateDeduccionIrpfRequest request)
 204    {
 205        try
 206        {
 3207            var (success, deduccion, error) = await _irpfService.CreateDeduccionAsync(request);
 2208            if (!success)
 209            {
 1210                if (error?.Contains("Ya existe", StringComparison.OrdinalIgnoreCase) == true)
 1211                    return Conflict(ApiResponse<string>.ErrorResult(error));
 0212                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al crear deducción"));
 213            }
 214
 1215            return CreatedAtAction(
 1216                nameof(GetDeduccion),
 1217                new { id = deduccion!.Id },
 1218                ApiResponse<object>.SuccessResult(new { id = deduccion.Id, creado = true }, "Deducción IRPF creada exito
 219        }
 1220        catch (Exception ex)
 221        {
 1222            _logger.LogError(ex, "Error al crear deducción IRPF");
 1223            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 224        }
 3225    }
 226
 227    /// <summary>
 228    /// Actualizar deducción IRPF
 229    /// PUT /api/irpf/deducciones/{id}
 230    /// </summary>
 231    [HttpPut("deducciones/{id}")]
 232    public async Task<IActionResult> UpdateDeduccion(long id, [FromBody] UpdateDeduccionIrpfRequest request)
 233    {
 234        try
 235        {
 4236            var (success, _, error) = await _irpfService.UpdateDeduccionAsync(id, request);
 3237            if (!success)
 238            {
 2239                if (error?.Contains("no encontrada", StringComparison.OrdinalIgnoreCase) == true)
 1240                    return NotFound(ApiResponse<string>.ErrorResult(error));
 1241                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al actualizar deducción"));
 242            }
 243
 1244            return Ok(ApiResponse<object>.SuccessResult(new { actualizado = true }, "Deducción IRPF actualizada exitosam
 245        }
 1246        catch (Exception ex)
 247        {
 1248            _logger.LogError(ex, "Error al actualizar deducción IRPF {Id}", id);
 1249            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 250        }
 4251    }
 252}