< 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: 313
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")]
 12public class TiposBeneficioController : ControllerBase
 13{
 14    private readonly ITipoBeneficioService _tipoBeneficioService;
 15    private readonly ILogger<TiposBeneficioController> _logger;
 16
 3017    public TiposBeneficioController(
 3018        ITipoBeneficioService tipoBeneficioService,
 3019        ILogger<TiposBeneficioController> logger)
 20    {
 3021        _tipoBeneficioService = tipoBeneficioService;
 3022        _logger = logger;
 3023    }
 24
 25    [HttpGet]
 26    [FAU.API.Security.RequirePermission(PermisoEnum.VerBeneficios)]
 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    [FAU.API.Security.RequirePermission(PermisoEnum.VerBeneficios)]
 59    public async Task<IActionResult> GetTipoBeneficio(long id)
 60    {
 61        try
 62        {
 363            var tipo = await _tipoBeneficioService.ObtenerPorIdAsync(id);
 264            if (tipo == null)
 65            {
 166                return NotFound(ApiResponse<string>.ErrorResult("Tipo de beneficio no encontrado"));
 67            }
 68
 169            return Ok(ApiResponse<object>.SuccessResult(MapearRespuesta(tipo)));
 70        }
 171        catch (Exception ex)
 72        {
 173            _logger.LogError(ex, "Error al obtener tipo de beneficio {Id}", id);
 174            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 75        }
 376    }
 77
 78    [HttpPost]
 79    [FAU.API.Security.RequirePermission(PermisoEnum.CrearBeneficios)]
 80    public async Task<IActionResult> CreateTipoBeneficio([FromBody] CrearTipoBeneficioRequest request)
 81    {
 82        try
 83        {
 784            if (string.IsNullOrWhiteSpace(request.Codigo))
 85            {
 186                return BadRequest(ApiResponse<string>.ErrorResult("El codigo es requerido"));
 87            }
 88
 689            if (string.IsNullOrWhiteSpace(request.Nombre))
 90            {
 191                return BadRequest(ApiResponse<string>.ErrorResult("El nombre es requerido"));
 92            }
 93
 594            var (exito, resultado, error) = await _tipoBeneficioService.CrearAsync(
 595                request.Codigo,
 596                request.Nombre,
 597                request.EsMensual,
 598                request.PermiteRetroactividad,
 599                request.PlazoPresentacionDias,
 5100                request.MontoReferencia,
 5101                request.CatalogoItemId,
 5102                request.Activo,
 5103                ObtenerUsuarioIdActual(),
 5104                ObtenerHost());
 105
 4106            if (!exito)
 107            {
 2108                if (error?.Contains("ya existe", StringComparison.OrdinalIgnoreCase) == true)
 109                {
 1110                    return Conflict(ApiResponse<string>.ErrorResult(error));
 111                }
 112
 1113                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al crear tipo de beneficio"));
 114            }
 115
 2116            return CreatedAtAction(
 2117                nameof(GetTipoBeneficio),
 2118                new { id = resultado!.Id },
 2119                ApiResponse<object>.SuccessResult(new { id = resultado.Id, creado = true }, "Tipo de beneficio creado ex
 120        }
 1121        catch (Exception ex)
 122        {
 1123            _logger.LogError(ex, "Error al crear tipo de beneficio");
 1124            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 125        }
 7126    }
 127
 128    [HttpPut("{id:long}")]
 129    [FAU.API.Security.RequirePermission(PermisoEnum.ActualizarBeneficios)]
 130    public async Task<IActionResult> UpdateTipoBeneficio(long id, [FromBody] ActualizarTipoBeneficioRequest request)
 131    {
 132        try
 133        {
 6134            if (request.Codigo == null &&
 6135                request.Nombre == null &&
 6136                !request.EsMensual.HasValue &&
 6137                !request.PermiteRetroactividad.HasValue &&
 6138                !request.PlazoPresentacionDias.HasValue &&
 6139                !request.MontoReferencia.HasValue &&
 6140                !request.CatalogoItemId.HasValue)
 141            {
 1142                return BadRequest(ApiResponse<string>.ErrorResult("Debe proporcionar al menos un campo para actualizar")
 143            }
 144
 5145            var (exito, resultado, error) = await _tipoBeneficioService.ActualizarAsync(
 5146                id,
 5147                request.Codigo,
 5148                request.Nombre,
 5149                request.EsMensual,
 5150                request.PermiteRetroactividad,
 5151                request.PlazoPresentacionDias,
 5152                request.MontoReferencia,
 5153                request.CatalogoItemId,
 5154                ObtenerUsuarioIdActual(),
 5155                ObtenerHost());
 156
 4157            if (!exito)
 158            {
 3159                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 160                {
 1161                    return NotFound(ApiResponse<string>.ErrorResult(error));
 162                }
 163
 2164                if (error?.Contains("ya existe", StringComparison.OrdinalIgnoreCase) == true)
 165                {
 1166                    return Conflict(ApiResponse<string>.ErrorResult(error));
 167                }
 168
 1169                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al actualizar tipo de beneficio"));
 170            }
 171
 1172            return Ok(ApiResponse<object>.SuccessResult(new
 1173            {
 1174                actualizado = true,
 1175                id = resultado!.Id
 1176            }, "Tipo de beneficio actualizado exitosamente"));
 177        }
 1178        catch (Exception ex)
 179        {
 1180            _logger.LogError(ex, "Error al actualizar tipo de beneficio {Id}", id);
 1181            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 182        }
 6183    }
 184
 185    [HttpPatch("{id:long}/activar")]
 186    [FAU.API.Security.RequirePermission(PermisoEnum.ActivarBeneficios)]
 187    public async Task<IActionResult> ActivarTipoBeneficio(long id)
 188    {
 3189        return await CambiarEstadoAsync(id, activar: true);
 3190    }
 191
 192    [HttpPatch("{id:long}/desactivar")]
 193    [FAU.API.Security.RequirePermission(PermisoEnum.DesactivarBeneficios)]
 194    public async Task<IActionResult> DesactivarTipoBeneficio(long id)
 195    {
 4196        return await CambiarEstadoAsync(id, activar: false);
 4197    }
 198
 199    [HttpDelete("{id:long}")]
 200    [FAU.API.Security.RequirePermission(PermisoEnum.EliminarBeneficios)]
 201    public async Task<IActionResult> DeleteTipoBeneficio(long id)
 202    {
 203        try
 204        {
 5205            var (exito, bajaLogica, error) = await _tipoBeneficioService.EliminarAsync(
 5206                id,
 5207                ObtenerUsuarioIdActual(),
 5208                ObtenerHost());
 209
 4210            if (!exito)
 211            {
 3212                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 213                {
 1214                    return NotFound(ApiResponse<string>.ErrorResult(error));
 215                }
 216
 2217                if (error?.Contains("liquidaciones abiertas", StringComparison.OrdinalIgnoreCase) == true)
 218                {
 1219                    return Conflict(ApiResponse<string>.ErrorResult(error));
 220                }
 221
 1222                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al eliminar tipo de beneficio"));
 223            }
 224
 1225            return Ok(ApiResponse<object>.SuccessResult(new
 1226            {
 1227                eliminado = true,
 1228                bajaLogica
 1229            }, bajaLogica
 1230                ? "Tipo de beneficio dado de baja logicamente"
 1231                : "Tipo de beneficio eliminado exitosamente"));
 232        }
 1233        catch (Exception ex)
 234        {
 1235            _logger.LogError(ex, "Error al eliminar tipo de beneficio {Id}", id);
 1236            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 237        }
 5238    }
 239
 240    private async Task<IActionResult> CambiarEstadoAsync(long id, bool activar)
 241    {
 242        try
 243        {
 7244            var (exito, resultado, error) = activar
 7245                ? await _tipoBeneficioService.ActivarAsync(id, ObtenerUsuarioIdActual(), ObtenerHost())
 7246                : await _tipoBeneficioService.DesactivarAsync(id, ObtenerUsuarioIdActual(), ObtenerHost());
 247
 6248            if (!exito)
 249            {
 4250                if (error?.Contains("no encontrado", StringComparison.OrdinalIgnoreCase) == true)
 251                {
 2252                    return NotFound(ApiResponse<string>.ErrorResult(error));
 253                }
 254
 2255                if (error?.Contains("liquidaciones abiertas", StringComparison.OrdinalIgnoreCase) == true)
 256                {
 1257                    return Conflict(ApiResponse<string>.ErrorResult(error));
 258                }
 259
 1260                return BadRequest(ApiResponse<string>.ErrorResult(error ?? "Error al cambiar estado"));
 261            }
 262
 2263            return Ok(ApiResponse<object>.SuccessResult(new
 2264            {
 2265                id = resultado!.Id,
 2266                activo = resultado.Activo
 2267            }, activar
 2268                ? "Tipo de beneficio activado exitosamente"
 2269                : "Tipo de beneficio desactivado exitosamente"));
 270        }
 1271        catch (Exception ex)
 272        {
 1273            _logger.LogError(ex, "Error al cambiar estado del tipo de beneficio {Id}", id);
 1274            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 275        }
 7276    }
 277
 278    private long ObtenerUsuarioIdActual()
 279    {
 22280        var usuario = HttpContext?.User;
 22281        if (usuario == null)
 282        {
 1283            return 0;
 284        }
 285
 21286        var claimId = usuario.FindFirstValue(ClaimTypes.NameIdentifier)
 21287                      ?? usuario.FindFirstValue("sub")
 21288                      ?? usuario.FindFirstValue("id");
 289
 21290        return long.TryParse(claimId, out var usuarioId) ? usuarioId : 0;
 291    }
 292
 293    private string ObtenerHost()
 294    {
 22295        return HttpContext?.Connection?.RemoteIpAddress?.ToString() ?? "Desconocido";
 296    }
 297
 298    private static object MapearRespuesta(TipoBeneficio tipo)
 299    {
 1300        return new
 1301        {
 1302            id = tipo.Id,
 1303            codigo = tipo.Codigo,
 1304            nombre = tipo.Nombre,
 1305            esMensual = tipo.EsMensual,
 1306            permiteRetroactividad = tipo.PermiteRetroactividad,
 1307            plazoPresentacionDias = tipo.PlazoPresentacionDias,
 1308            montoReferencia = tipo.MontoReferencia,
 1309            catalogoItemId = tipo.CatalogoItemId,
 1310            activo = tipo.Activo
 1311        };
 312    }
 313}