< Summary

Information
Class: FAU.API.Controllers.TiposBeneficioController
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/TiposBeneficioController.cs
Line coverage
100%
Covered lines: 156
Uncovered lines: 0
Coverable lines: 156
Total lines: 307
Line coverage: 100%
Branch coverage
88%
Covered branches: 78
Total branches: 88
Branch coverage: 88.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetTiposBeneficio()100%11100%
GetTipoBeneficio()100%22100%
CreateTipoBeneficio()91.66%1212100%
UpdateTipoBeneficio()96.15%2626100%
ActivarTipoBeneficio()100%11100%
DesactivarTipoBeneficio()100%11100%
DeleteTipoBeneficio()85.71%1414100%
CambiarEstadoAsync()93.75%1616100%
ObtenerUsuarioIdActual()70%1010100%
ObtenerHost()75%88100%
MapearRespuesta(...)100%11100%

File(s)

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

#LineLine coverage
 1using System.Security.Claims;
 2using FAU.Entidades;
 3using FAU.Logica.DTOs;
 4using FAU.Logica.Services;
 5using Microsoft.AspNetCore.Authorization;
 6using Microsoft.AspNetCore.Mvc;
 7
 8namespace FAU.API.Controllers;
 9
 10[ApiController]
 11[Route("api/tipos-beneficio")]
 12[Authorize(Roles = "Administrador")]
 13public class TiposBeneficioController : ControllerBase
 14{
 15    private readonly ITipoBeneficioService _tipoBeneficioService;
 16    private readonly ILogger<TiposBeneficioController> _logger;
 17
 3018    public TiposBeneficioController(
 3019        ITipoBeneficioService tipoBeneficioService,
 3020        ILogger<TiposBeneficioController> logger)
 21    {
 3022        _tipoBeneficioService = tipoBeneficioService;
 3023        _logger = logger;
 3024    }
 25
 26    [HttpGet]
 27    public async Task<IActionResult> GetTiposBeneficio(
 28        [FromQuery] int pagina = 1,
 29        [FromQuery] int tamano = 10,
 30        [FromQuery] string? busqueda = null,
 31        [FromQuery] bool? activo = null)
 32    {
 33        try
 34        {
 235            var resultado = await _tipoBeneficioService.ObtenerPaginadoAsync(pagina, tamano, busqueda, activo);
 36
 137            var response = new
 138            {
 139                items = resultado.Items,
 140                page = resultado.Page,
 141                pageSize = resultado.PageSize,
 142                totalCount = resultado.TotalCount,
 143                totalPages = resultado.TotalPages,
 144                hasPreviousPage = resultado.HasPreviousPage,
 145                hasNextPage = resultado.HasNextPage
 146            };
 47
 148            return Ok(ApiResponse<object>.SuccessResult(response));
 49        }
 150        catch (Exception ex)
 51        {
 152            _logger.LogError(ex, "Error al listar tipos de beneficio");
 153            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 54        }
 255    }
 56
 57    [HttpGet("{id:long}")]
 58    public async Task<IActionResult> GetTipoBeneficio(long id)
 59    {
 60        try
 61        {
 362            var tipo = await _tipoBeneficioService.ObtenerPorIdAsync(id);
 263            if (tipo == null)
 64            {
 165                return NotFound(ApiResponse<string>.ErrorResult("Tipo de beneficio no encontrado"));
 66            }
 67
 168            return Ok(ApiResponse<object>.SuccessResult(MapearRespuesta(tipo)));
 69        }
 170        catch (Exception ex)
 71        {
 172            _logger.LogError(ex, "Error al obtener tipo de beneficio {Id}", id);
 173            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 74        }
 375    }
 76
 77    [HttpPost]
 78    public async Task<IActionResult> CreateTipoBeneficio([FromBody] CrearTipoBeneficioRequest request)
 79    {
 80        try
 81        {
 782            if (string.IsNullOrWhiteSpace(request.Codigo))
 83            {
 184                return BadRequest(ApiResponse<string>.ErrorResult("El codigo es requerido"));
 85            }
 86
 687            if (string.IsNullOrWhiteSpace(request.Nombre))
 88            {
 189                return BadRequest(ApiResponse<string>.ErrorResult("El nombre es requerido"));
 90            }
 91
 592            var (exito, resultado, error) = await _tipoBeneficioService.CrearAsync(
 593                request.Codigo,
 594                request.Nombre,
 595                request.EsMensual,
 596                request.PermiteRetroactividad,
 597                request.PlazoPresentacionDias,
 598                request.MontoReferencia,
 599                request.CatalogoItemId,
 5100                request.Activo,
 5101                ObtenerUsuarioIdActual(),
 5102                ObtenerHost());
 103
 4104            if (!exito)
 105            {
 2106                if (error?.Contains("ya existe", StringComparison.OrdinalIgnoreCase) == true)
 107                {
 1108                    return Conflict(ApiResponse<string>.ErrorResult(error));
 109                }
 110
 1111                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al crear tipo de beneficio"));
 112            }
 113
 2114            return CreatedAtAction(
 2115                nameof(GetTipoBeneficio),
 2116                new { id = resultado!.Id },
 2117                ApiResponse<object>.SuccessResult(new { id = resultado.Id, creado = true }, "Tipo de beneficio creado ex
 118        }
 1119        catch (Exception ex)
 120        {
 1121            _logger.LogError(ex, "Error al crear tipo de beneficio");
 1122            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 123        }
 7124    }
 125
 126    [HttpPut("{id:long}")]
 127    public async Task<IActionResult> UpdateTipoBeneficio(long id, [FromBody] ActualizarTipoBeneficioRequest request)
 128    {
 129        try
 130        {
 6131            if (request.Codigo == null &&
 6132                request.Nombre == null &&
 6133                !request.EsMensual.HasValue &&
 6134                !request.PermiteRetroactividad.HasValue &&
 6135                !request.PlazoPresentacionDias.HasValue &&
 6136                !request.MontoReferencia.HasValue &&
 6137                !request.CatalogoItemId.HasValue)
 138            {
 1139                return BadRequest(ApiResponse<string>.ErrorResult("Debe proporcionar al menos un campo para actualizar")
 140            }
 141
 5142            var (exito, resultado, error) = await _tipoBeneficioService.ActualizarAsync(
 5143                id,
 5144                request.Codigo,
 5145                request.Nombre,
 5146                request.EsMensual,
 5147                request.PermiteRetroactividad,
 5148                request.PlazoPresentacionDias,
 5149                request.MontoReferencia,
 5150                request.CatalogoItemId,
 5151                ObtenerUsuarioIdActual(),
 5152                ObtenerHost());
 153
 4154            if (!exito)
 155            {
 3156                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 157                {
 1158                    return NotFound(ApiResponse<string>.ErrorResult(error));
 159                }
 160
 2161                if (error?.Contains("ya existe", StringComparison.OrdinalIgnoreCase) == true)
 162                {
 1163                    return Conflict(ApiResponse<string>.ErrorResult(error));
 164                }
 165
 1166                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al actualizar tipo de beneficio"));
 167            }
 168
 1169            return Ok(ApiResponse<object>.SuccessResult(new
 1170            {
 1171                actualizado = true,
 1172                id = resultado!.Id
 1173            }, "Tipo de beneficio actualizado exitosamente"));
 174        }
 1175        catch (Exception ex)
 176        {
 1177            _logger.LogError(ex, "Error al actualizar tipo de beneficio {Id}", id);
 1178            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 179        }
 6180    }
 181
 182    [HttpPatch("{id:long}/activar")]
 183    public async Task<IActionResult> ActivarTipoBeneficio(long id)
 184    {
 3185        return await CambiarEstadoAsync(id, activar: true);
 3186    }
 187
 188    [HttpPatch("{id:long}/desactivar")]
 189    public async Task<IActionResult> DesactivarTipoBeneficio(long id)
 190    {
 4191        return await CambiarEstadoAsync(id, activar: false);
 4192    }
 193
 194    [HttpDelete("{id:long}")]
 195    public async Task<IActionResult> DeleteTipoBeneficio(long id)
 196    {
 197        try
 198        {
 5199            var (exito, bajaLogica, error) = await _tipoBeneficioService.EliminarAsync(
 5200                id,
 5201                ObtenerUsuarioIdActual(),
 5202                ObtenerHost());
 203
 4204            if (!exito)
 205            {
 3206                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 207                {
 1208                    return NotFound(ApiResponse<string>.ErrorResult(error));
 209                }
 210
 2211                if (error?.Contains("liquidaciones abiertas", StringComparison.OrdinalIgnoreCase) == true)
 212                {
 1213                    return Conflict(ApiResponse<string>.ErrorResult(error));
 214                }
 215
 1216                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al eliminar tipo de beneficio"));
 217            }
 218
 1219            return Ok(ApiResponse<object>.SuccessResult(new
 1220            {
 1221                eliminado = true,
 1222                bajaLogica
 1223            }, bajaLogica
 1224                ? "Tipo de beneficio dado de baja logicamente"
 1225                : "Tipo de beneficio eliminado exitosamente"));
 226        }
 1227        catch (Exception ex)
 228        {
 1229            _logger.LogError(ex, "Error al eliminar tipo de beneficio {Id}", id);
 1230            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 231        }
 5232    }
 233
 234    private async Task<IActionResult> CambiarEstadoAsync(long id, bool activar)
 235    {
 236        try
 237        {
 7238            var (exito, resultado, error) = activar
 7239                ? await _tipoBeneficioService.ActivarAsync(id, ObtenerUsuarioIdActual(), ObtenerHost())
 7240                : await _tipoBeneficioService.DesactivarAsync(id, ObtenerUsuarioIdActual(), ObtenerHost());
 241
 6242            if (!exito)
 243            {
 4244                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 245                {
 2246                    return NotFound(ApiResponse<string>.ErrorResult(error));
 247                }
 248
 2249                if (error?.Contains("liquidaciones abiertas", StringComparison.OrdinalIgnoreCase) == true)
 250                {
 1251                    return Conflict(ApiResponse<string>.ErrorResult(error));
 252                }
 253
 1254                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al cambiar estado"));
 255            }
 256
 2257            return Ok(ApiResponse<object>.SuccessResult(new
 2258            {
 2259                id = resultado!.Id,
 2260                activo = resultado.Activo
 2261            }, activar
 2262                ? "Tipo de beneficio activado exitosamente"
 2263                : "Tipo de beneficio desactivado exitosamente"));
 264        }
 1265        catch (Exception ex)
 266        {
 1267            _logger.LogError(ex, "Error al cambiar estado del tipo de beneficio {Id}", id);
 1268            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 269        }
 7270    }
 271
 272    private long ObtenerUsuarioIdActual()
 273    {
 22274        var usuario = HttpContext?.User;
 22275        if (usuario == null)
 276        {
 1277            return 0;
 278        }
 279
 21280        var claimId = usuario.FindFirstValue(ClaimTypes.NameIdentifier)
 21281                      ?? usuario.FindFirstValue("sub")
 21282                      ?? usuario.FindFirstValue("id");
 283
 21284        return long.TryParse(claimId, out var usuarioId) ? usuarioId : 0;
 285    }
 286
 287    private string ObtenerHost()
 288    {
 22289        return HttpContext?.Connection?.RemoteIpAddress?.ToString() ?? "Desconocido";
 290    }
 291
 292    private static object MapearRespuesta(TipoBeneficio tipo)
 293    {
 1294        return new
 1295        {
 1296            id = tipo.Id,
 1297            codigo = tipo.Codigo,
 1298            nombre = tipo.Nombre,
 1299            esMensual = tipo.EsMensual,
 1300            permiteRetroactividad = tipo.PermiteRetroactividad,
 1301            plazoPresentacionDias = tipo.PlazoPresentacionDias,
 1302            montoReferencia = tipo.MontoReferencia,
 1303            catalogoItemId = tipo.CatalogoItemId,
 1304            activo = tipo.Activo
 1305        };
 306    }
 307}