< Summary

Information
Class: FAU.API.Controllers.DescuentosPersonalesController
Assembly: FAU.API
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.API/Controllers/DescuentosPersonalesController.cs
Line coverage
76%
Covered lines: 89
Uncovered lines: 27
Coverable lines: 116
Total lines: 291
Line coverage: 76.7%
Branch coverage
26%
Covered branches: 8
Total branches: 30
Branch coverage: 26.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%
Crear()62.5%8881.25%
Listar()50%3250%
Editar()50%2257.14%
Eliminar()100%1150%
ConfirmarUno()100%1158.33%
Confirmar()50%2290%

File(s)

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

#LineLine coverage
 1using FAU.Entidades;
 2using FAU.Logica.DTOs;
 3using FAU.Logica.Services;
 4using Microsoft.AspNetCore.Authorization;
 5using Microsoft.AspNetCore.Mvc;
 6using System.ComponentModel.DataAnnotations;
 7
 8namespace FAU.API.Controllers;
 9
 10/// <summary>
 11/// Gestión de descuentos personales del período
 12/// </summary>
 13[ApiController]
 14[Route("api/descuentos-personales")]
 15[Authorize]
 16public class DescuentosPersonalesController : ControllerBase
 17{
 18    private readonly IDescuentoPersonalService _service;
 19    private readonly ICurrentUserContext _currentUser;
 20    private readonly ILogger<DescuentosPersonalesController> _logger;
 21
 1322    public DescuentosPersonalesController(
 1323        IDescuentoPersonalService service,
 1324        ICurrentUserContext currentUser,
 1325        ILogger<DescuentosPersonalesController> logger)
 26    {
 1327        _service = service;
 1328        _currentUser = currentUser;
 1329        _logger = logger;
 1330    }
 31
 32    /// <summary>
 33    /// Crear un descuento personal en borrador
 34    /// POST /api/descuentos-personales
 35    /// </summary>
 36    [HttpPost]
 37    [FAU.API.Security.RequirePermission(PermisoEnum.CrearDescuentosPersonales)]
 38    public async Task<IActionResult> Crear([FromBody] CrearDescuentoPersonalRequest request)
 39    {
 40        try
 41        {
 442            if (request.PeriodoId <= 0)
 043                return BadRequest(ApiResponse<string>.ErrorResult("periodoId es requerido"));
 444            if (string.IsNullOrWhiteSpace(request.CedulaTitular))
 045                return BadRequest(ApiResponse<string>.ErrorResult("cedulaTitular es requerida"));
 446            if (request.AcreedorId <= 0)
 047                return BadRequest(ApiResponse<string>.ErrorResult("acreedorId es requerido"));
 448            if (request.Importe <= 0)
 149                return BadRequest(ApiResponse<string>.ErrorResult("importe debe ser mayor a cero"));
 50
 351            var usuarioId = _currentUser.UserId ?? 0;
 352            var creado = await _service.CrearAsync(
 353                request.PeriodoId,
 354                request.CedulaTitular,
 355                request.CodigoConcepto,
 356                request.AcreedorId,
 357                request.Importe,
 358                request.Observaciones,
 359                usuarioId,
 360                request.FechaComunicacion);
 61
 162            return CreatedAtAction(
 163                nameof(Listar),
 164                new { periodoId = request.PeriodoId },
 165                ApiResponse<object>.SuccessResult(
 166                    new { id = creado.Id, creado = true },
 167                    "Descuento personal creado exitosamente"));
 68        }
 169        catch (ArgumentException ex)
 70        {
 171            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 72        }
 173        catch (InvalidOperationException ex)
 74        {
 175            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 76        }
 077        catch (Exception ex)
 78        {
 079            _logger.LogError(ex, "Error al crear descuento personal");
 080            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 81        }
 482    }
 83
 84    /// <summary>
 85    /// Listar descuentos personales del período
 86    /// GET /api/descuentos-personales?periodoId=...&cedulaTitular=...&codigoConcepto=...&estado=...
 87    /// </summary>
 88    [HttpGet]
 89    [FAU.API.Security.RequirePermission(PermisoEnum.VerDescuentosPersonales)]
 90    public async Task<IActionResult> Listar(
 91        [FromQuery] long periodoId,
 92        [FromQuery] string? cedulaTitular = null,
 93        [FromQuery] int? codigoConcepto = null,
 94        [FromQuery] string? estado = null)
 95    {
 96        try
 97        {
 198            if (periodoId <= 0)
 099                return BadRequest(ApiResponse<string>.ErrorResult("periodoId es requerido"));
 100
 1101            var items = await _service.ListarAsync(periodoId, cedulaTitular, codigoConcepto, estado);
 102
 1103            var response = items.Select(d => new
 1104            {
 1105                id = d.Id,
 1106                periodoId = d.PeriodoId,
 1107                personaId = d.PersonaId,
 1108                cedula = d.Persona?.Cedula,
 1109                nombreCompleto = d.Persona?.NombreCompleto,
 1110                acreedorId = d.AcreedorId,
 1111                acreedorCodigo = d.Acreedor?.Codigo,
 1112                acreedorNombre = d.Acreedor?.Nombre,
 1113                categoriaDeficit = d.Acreedor?.CategoriaDeficit,
 1114                ordenLegalDeficit = d.Acreedor?.OrdenLegalDeficit,
 1115                catalogoItemId = d.CatalogoItemId,
 1116                codigoConcepto = d.CatalogoItem?.Codigo,
 1117                nombreConcepto = d.CatalogoItem?.Nombre,
 1118                importe = d.Importe,
 1119                estado = d.Estado,
 1120                observaciones = d.Observaciones,
 1121                fechaComunicacion = d.FechaComunicacion,
 1122                fechaCreacion = d.FechaCreacion,
 1123                usuarioCreacionId = d.UsuarioCreacionId
 1124            });
 125
 1126            return Ok(ApiResponse<object>.SuccessResult(response));
 127        }
 0128        catch (Exception ex)
 129        {
 0130            _logger.LogError(ex, "Error al listar descuentos personales");
 0131            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 132        }
 1133    }
 134
 135    /// <summary>
 136    /// Editar un descuento personal en borrador
 137    /// PUT /api/descuentos-personales/{id}
 138    /// </summary>
 139    [HttpPut("{id}")]
 140    [FAU.API.Security.RequirePermission(PermisoEnum.ActualizarDescuentosPersonales)]
 141    public async Task<IActionResult> Editar(long id, [FromBody] EditarDescuentoPersonalRequest request)
 142    {
 143        try
 144        {
 2145            if (request.Importe <= 0)
 0146                return BadRequest(ApiResponse<string>.ErrorResult("importe debe ser mayor a cero"));
 147
 2148            var actualizado = await _service.EditarAsync(id, request.Importe, request.Observaciones, request.FechaComuni
 1149            return Ok(ApiResponse<object>.SuccessResult(
 1150                new { id = actualizado.Id, actualizado = true },
 1151                "Descuento personal actualizado exitosamente"));
 152        }
 0153        catch (ArgumentException ex)
 154        {
 0155            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 156        }
 1157        catch (InvalidOperationException ex)
 158        {
 1159            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 160        }
 0161        catch (Exception ex)
 162        {
 0163            _logger.LogError(ex, "Error al actualizar descuento personal {Id}", id);
 0164            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 165        }
 2166    }
 167
 168    /// <summary>
 169    /// Eliminar un descuento personal en borrador
 170    /// DELETE /api/descuentos-personales/{id}
 171    /// </summary>
 172    [HttpDelete("{id}")]
 173    [FAU.API.Security.RequirePermission(PermisoEnum.ActualizarDescuentosPersonales)]
 174    public async Task<IActionResult> Eliminar(long id)
 175    {
 176        try
 177        {
 2178            await _service.EliminarAsync(id);
 1179            return NoContent();
 180        }
 0181        catch (ArgumentException ex)
 182        {
 0183            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 184        }
 1185        catch (InvalidOperationException ex)
 186        {
 1187            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 188        }
 0189        catch (Exception ex)
 190        {
 0191            _logger.LogError(ex, "Error al eliminar descuento personal {Id}", id);
 0192            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 193        }
 2194    }
 195
 196    /// <summary>
 197    /// Confirmar un descuento personal en borrador
 198    /// POST /api/descuentos-personales/{id}/confirmar
 199    /// </summary>
 200    [HttpPost("{id}/confirmar")]
 201    [FAU.API.Security.RequirePermission(PermisoEnum.ConfirmarDescuentosPersonales)]
 202    public async Task<IActionResult> ConfirmarUno(long id)
 203    {
 204        try
 205        {
 2206            var confirmado = await _service.ConfirmarAsync(id);
 1207            return Ok(ApiResponse<object>.SuccessResult(
 1208                new { confirmado = true },
 1209                $"Descuento personal {confirmado.Id} confirmado exitosamente"));
 210        }
 0211        catch (ArgumentException ex)
 212        {
 0213            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 214        }
 1215        catch (InvalidOperationException ex)
 216        {
 1217            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 218        }
 0219        catch (Exception ex)
 220        {
 0221            _logger.LogError(ex, "Error al confirmar descuento personal {Id}", id);
 0222            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 223        }
 2224    }
 225
 226    /// <summary>
 227    /// Confirmar todos los borradores de un período
 228    /// POST /api/descuentos-personales/confirmar
 229    /// </summary>
 230    [HttpPost("confirmar")]
 231    [FAU.API.Security.RequirePermission(PermisoEnum.ConfirmarDescuentosPersonales)]
 232    public async Task<IActionResult> Confirmar([FromBody] ConfirmarDescuentosRequest request)
 233    {
 234        try
 235        {
 2236            if (request.PeriodoId <= 0)
 0237                return BadRequest(ApiResponse<string>.ErrorResult("periodoId es requerido"));
 238
 2239            var cantidad = await _service.ConfirmarBorradoresAsync(request.PeriodoId);
 1240            return Ok(ApiResponse<object>.SuccessResult(
 1241                new { confirmados = cantidad },
 1242                $"Se confirmaron {cantidad} descuento(s) personal(es)"));
 243        }
 1244        catch (Exception ex)
 245        {
 1246            _logger.LogError(ex, "Error al confirmar descuentos personales del período {PeriodoId}", request.PeriodoId);
 1247            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 248        }
 2249    }
 250}
 251
 252public class CrearDescuentoPersonalRequest
 253{
 254    [Required]
 255    public long PeriodoId { get; set; }
 256
 257    [Required]
 258    [MaxLength(12)]
 259    public string CedulaTitular { get; set; } = string.Empty;
 260
 261    [Required]
 262    public int CodigoConcepto { get; set; }
 263
 264    [Required]
 265    public long AcreedorId { get; set; }
 266
 267    [Required]
 268    public decimal Importe { get; set; }
 269
 270    [MaxLength(500)]
 271    public string? Observaciones { get; set; }
 272
 273    public DateTime? FechaComunicacion { get; set; }
 274}
 275
 276public class EditarDescuentoPersonalRequest
 277{
 278    [Required]
 279    public decimal Importe { get; set; }
 280
 281    [MaxLength(500)]
 282    public string? Observaciones { get; set; }
 283
 284    public DateTime? FechaComunicacion { get; set; }
 285}
 286
 287public class ConfirmarDescuentosRequest
 288{
 289    [Required]
 290    public long PeriodoId { get; set; }
 291}