< Summary

Information
Class: FAU.API.Controllers.InstructivosBeneficiosController
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/InstructivosBeneficiosController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 62
Coverable lines: 62
Total lines: 202
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetAsigFamiliar()100%210%
ToFirstDayUtc(...)0%620%
PostAsigFamiliar()100%210%
GetPsf()100%210%
PostPsf()100%210%
GetHogar()100%210%
PostHogar()100%210%

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
 018    public InstructivosBeneficiosController(
 019        IInstructivoBeneficiosService service,
 020        ILogger<InstructivosBeneficiosController> logger)
 21    {
 022        _service = service;
 023        _logger  = logger;
 024    }
 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        {
 035            var items = await _service.ObtenerAsigFamiliarAsync(vigente);
 036            return Ok(ApiResponse<object>.SuccessResult(items));
 37        }
 038        catch (Exception ex)
 39        {
 040            _logger.LogError(ex, "Error al obtener instructivo asig. familiar");
 041            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 42        }
 043    }
 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
 049        if (DateTime.TryParse(vigenteDesdeStr, out var dt))
 050            return DateTime.SpecifyKind(new DateTime(dt.Year, dt.Month, 1), DateTimeKind.Utc);
 051        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        {
 062            var items = await _service.RegistrarAsigFamiliarAsync(
 063                ToFirstDayUtc(request.VigenteDesde.ToString()), request.Franja8, request.Franja16, request.Discapacidad)
 064            return Ok(ApiResponse<object>.SuccessResult(items, "Instructivo Asig. Familiar registrado correctamente"));
 65        }
 066        catch (ArgumentException ex)
 67        {
 068            return BadRequest(ApiResponse<string>.ErrorResult(ex.Message));
 69        }
 070        catch (Exception ex)
 71        {
 072            _logger.LogError(ex, "Error al registrar instructivo asig. familiar");
 073            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 74        }
 075    }
 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        {
 086            var items = await _service.ObtenerPsfAsync(vigente);
 087            return Ok(ApiResponse<object>.SuccessResult(items));
 88        }
 089        catch (Exception ex)
 90        {
 091            _logger.LogError(ex, "Error al obtener instructivo PSF");
 092            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 93        }
 094    }
 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        {
 0105            var categorias = request.Categorias
 0106                .Select(c => ((short)c.NumeroCategoria, c.Descripcion, c.Importe))
 0107                .ToList()
 0108                .AsReadOnly();
 0109            var items = await _service.RegistrarPsfAsync(
 0110                ToFirstDayUtc(request.VigenteDesde.ToString()), categorias);
 0111            return Ok(ApiResponse<object>.SuccessResult(items, "Instructivo PSF registrado correctamente"));
 112        }
 0113        catch (ArgumentException ex)  { return BadRequest(ApiResponse<string>.ErrorResult(ex.Message)); }
 0114        catch (InvalidOperationException ex) { return Conflict(ApiResponse<string>.ErrorResult(ex.Message)); }
 0115        catch (Exception ex)
 116        {
 0117            _logger.LogError(ex, "Error al registrar instructivo PSF");
 0118            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 119        }
 0120    }
 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        {
 0131            var items = await _service.ObtenerHogarAsync(vigente);
 0132            return Ok(ApiResponse<object>.SuccessResult(items));
 133        }
 0134        catch (Exception ex)
 135        {
 0136            _logger.LogError(ex, "Error al obtener tabla hogar constituido");
 0137            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 138        }
 0139    }
 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        {
 0150            var tramos = request.Tramos
 0151                .Select(t => (t.HastaHaberes, t.Importe, t.RefPorcentaje))
 0152                .ToList()
 0153                .AsReadOnly();
 0154            var items = await _service.RegistrarHogarAsync(
 0155                ToFirstDayUtc(request.VigenteDesde.ToString()), tramos);
 0156            return Ok(ApiResponse<object>.SuccessResult(items, "Tabla Hogar Constituido registrada correctamente"));
 157        }
 0158        catch (ArgumentException ex)  { return BadRequest(ApiResponse<string>.ErrorResult(ex.Message)); }
 0159        catch (InvalidOperationException ex) { return Conflict(ApiResponse<string>.ErrorResult(ex.Message)); }
 0160        catch (Exception ex)
 161        {
 0162            _logger.LogError(ex, "Error al registrar tabla hogar");
 0163            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 164        }
 0165    }
 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{
 180    public DateTime VigenteDesde { get; set; }
 181    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}