< Summary

Information
Line coverage
100%
Covered lines: 2
Uncovered lines: 0
Coverable lines: 2
Total lines: 202
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_VigenteDesde()100%11100%
get_Categorias()100%11100%

File(s)

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

#LineLine coverage
 1using FAU.Logica.DTOs;
 2using FAU.Logica.Services;
 3using Microsoft.AspNetCore.Authorization;
 4using Microsoft.AspNetCore.Http;
 5using Microsoft.AspNetCore.Mvc;
 6
 7namespace FAU.API.Controllers;
 8
 9[ApiController]
 10[Route("api/instructivos")]
 11[Authorize(Roles = "Administrador")]
 12[Produces("application/json")]
 13public class InstructivosBeneficiosController : ControllerBase
 14{
 15    private readonly IInstructivoBeneficiosService _service;
 16    private readonly ILogger<InstructivosBeneficiosController> _logger;
 17
 18    public InstructivosBeneficiosController(
 19        IInstructivoBeneficiosService service,
 20        ILogger<InstructivosBeneficiosController> logger)
 21    {
 22        _service = service;
 23        _logger  = logger;
 24    }
 25
 26    // ── Asignación Familiar ───────────────────────────────────────────────────
 27
 28    [HttpGet("asig-familiar")]
 29    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 30    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 31    public async Task<IActionResult> GetAsigFamiliar([FromQuery] bool vigente = true)
 32    {
 33        try
 34        {
 35            var items = await _service.ObtenerAsigFamiliarAsync(vigente);
 36            return Ok(ApiResponse<object>.SuccessResult(items));
 37        }
 38        catch (Exception ex)
 39        {
 40            _logger.LogError(ex, "Error al obtener instructivo asig. familiar");
 41            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 42        }
 43    }
 44
 45    private static DateTime ToFirstDayUtc(string vigenteDesdeStr)
 46    {
 47        // Parse YYYY-MM-DD directly to avoid timezone conversion issues
 48        // The frontend sends "YYYY-MM-01T00:00:00Z" so we extract year and month
 49        if (DateTime.TryParse(vigenteDesdeStr, out var dt))
 50            return DateTime.SpecifyKind(new DateTime(dt.Year, dt.Month, 1), DateTimeKind.Utc);
 51        throw new ArgumentException($"Formato de fecha inválido: {vigenteDesdeStr}");
 52    }
 53
 54    [HttpPost("asig-familiar")]
 55    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 56    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status400BadRequest)]
 57    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 58    public async Task<IActionResult> PostAsigFamiliar([FromBody] RegistrarAsigFamiliarRequest request)
 59    {
 60        try
 61        {
 62            var items = await _service.RegistrarAsigFamiliarAsync(
 63                ToFirstDayUtc(request.VigenteDesde.ToString()), request.Franja8, request.Franja16, request.Discapacidad)
 64            return Ok(ApiResponse<object>.SuccessResult(items, "Instructivo Asig. Familiar registrado correctamente"));
 65        }
 66        catch (ArgumentException ex)
 67        {
 68            return BadRequest(ApiResponse<string>.ErrorResult(ex.Message));
 69        }
 70        catch (Exception ex)
 71        {
 72            _logger.LogError(ex, "Error al registrar instructivo asig. familiar");
 73            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 74        }
 75    }
 76
 77    // ── PSF ───────────────────────────────────────────────────────────────────
 78
 79    [HttpGet("psf")]
 80    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 81    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 82    public async Task<IActionResult> GetPsf([FromQuery] bool vigente = true)
 83    {
 84        try
 85        {
 86            var items = await _service.ObtenerPsfAsync(vigente);
 87            return Ok(ApiResponse<object>.SuccessResult(items));
 88        }
 89        catch (Exception ex)
 90        {
 91            _logger.LogError(ex, "Error al obtener instructivo PSF");
 92            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 93        }
 94    }
 95
 96    [HttpPost("psf")]
 97    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 98    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status400BadRequest)]
 99    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status409Conflict)]
 100    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 101    public async Task<IActionResult> PostPsf([FromBody] RegistrarPsfRequest request)
 102    {
 103        try
 104        {
 105            var categorias = request.Categorias
 106                .Select(c => ((short)c.NumeroCategoria, c.Descripcion, c.Importe))
 107                .ToList()
 108                .AsReadOnly();
 109            var items = await _service.RegistrarPsfAsync(
 110                ToFirstDayUtc(request.VigenteDesde.ToString()), categorias);
 111            return Ok(ApiResponse<object>.SuccessResult(items, "Instructivo PSF registrado correctamente"));
 112        }
 113        catch (ArgumentException ex)  { return BadRequest(ApiResponse<string>.ErrorResult(ex.Message)); }
 114        catch (InvalidOperationException ex) { return Conflict(ApiResponse<string>.ErrorResult(ex.Message)); }
 115        catch (Exception ex)
 116        {
 117            _logger.LogError(ex, "Error al registrar instructivo PSF");
 118            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 119        }
 120    }
 121
 122    // ── Hogar Constituido ─────────────────────────────────────────────────────
 123
 124    [HttpGet("hogar")]
 125    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 126    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 127    public async Task<IActionResult> GetHogar([FromQuery] bool vigente = true)
 128    {
 129        try
 130        {
 131            var items = await _service.ObtenerHogarAsync(vigente);
 132            return Ok(ApiResponse<object>.SuccessResult(items));
 133        }
 134        catch (Exception ex)
 135        {
 136            _logger.LogError(ex, "Error al obtener tabla hogar constituido");
 137            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 138        }
 139    }
 140
 141    [HttpPost("hogar")]
 142    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
 143    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status400BadRequest)]
 144    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status409Conflict)]
 145    [ProducesResponseType(typeof(ApiResponse<string>), StatusCodes.Status500InternalServerError)]
 146    public async Task<IActionResult> PostHogar([FromBody] RegistrarHogarRequest request)
 147    {
 148        try
 149        {
 150            var tramos = request.Tramos
 151                .Select(t => (t.HastaHaberes, t.Importe, t.RefPorcentaje))
 152                .ToList()
 153                .AsReadOnly();
 154            var items = await _service.RegistrarHogarAsync(
 155                ToFirstDayUtc(request.VigenteDesde.ToString()), tramos);
 156            return Ok(ApiResponse<object>.SuccessResult(items, "Tabla Hogar Constituido registrada correctamente"));
 157        }
 158        catch (ArgumentException ex)  { return BadRequest(ApiResponse<string>.ErrorResult(ex.Message)); }
 159        catch (InvalidOperationException ex) { return Conflict(ApiResponse<string>.ErrorResult(ex.Message)); }
 160        catch (Exception ex)
 161        {
 162            _logger.LogError(ex, "Error al registrar tabla hogar");
 163            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 164        }
 165    }
 166}
 167
 168// ── Request DTOs ──────────────────────────────────────────────────────────────
 169
 170public class RegistrarAsigFamiliarRequest
 171{
 172    public DateTime VigenteDesde { get; set; }
 173    public decimal Franja8 { get; set; }
 174    public decimal Franja16 { get; set; }
 175    public decimal Discapacidad { get; set; }
 176}
 177
 178public class RegistrarPsfRequest
 179{
 6180    public DateTime VigenteDesde { get; set; }
 9181    public List<PsfCategoriaRequest> Categorias { get; set; } = [];
 182}
 183
 184public class PsfCategoriaRequest
 185{
 186    public int NumeroCategoria { get; set; }
 187    public string Descripcion { get; set; } = string.Empty;
 188    public decimal Importe { get; set; }
 189}
 190
 191public class RegistrarHogarRequest
 192{
 193    public DateTime VigenteDesde { get; set; }
 194    public List<HogarTramoRequest> Tramos { get; set; } = [];
 195}
 196
 197public class HogarTramoRequest
 198{
 199    public decimal? HastaHaberes { get; set; }
 200    public decimal Importe { get; set; }
 201    public string? RefPorcentaje { get; set; }
 202}