< 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
77%
Covered lines: 73
Uncovered lines: 21
Coverable lines: 94
Total lines: 244
Line coverage: 77.6%
Branch coverage
35%
Covered branches: 7
Total branches: 20
Branch coverage: 35%
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()66.66%6682.14%
Listar()50%3250%
Editar()50%2257.14%
Eliminar()100%1150%
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
 1122    public DescuentosPersonalesController(
 1123        IDescuentoPersonalService service,
 1124        ICurrentUserContext currentUser,
 1125        ILogger<DescuentosPersonalesController> logger)
 26    {
 1127        _service = service;
 1128        _currentUser = currentUser;
 1129        _logger = logger;
 1130    }
 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.Importe <= 0)
 147                return BadRequest(ApiResponse<string>.ErrorResult("importe debe ser mayor a cero"));
 48
 349            var usuarioId = _currentUser.UserId ?? 0;
 350            var creado = await _service.CrearAsync(
 351                request.PeriodoId,
 352                request.CedulaTitular,
 353                request.CodigoConcepto,
 354                request.Importe,
 355                request.Observaciones,
 356                usuarioId);
 57
 158            return CreatedAtAction(
 159                nameof(Listar),
 160                new { periodoId = request.PeriodoId },
 161                ApiResponse<object>.SuccessResult(
 162                    new { id = creado.Id, creado = true },
 163                    "Descuento personal creado exitosamente"));
 64        }
 165        catch (ArgumentException ex)
 66        {
 167            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 68        }
 169        catch (InvalidOperationException ex)
 70        {
 171            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 72        }
 073        catch (Exception ex)
 74        {
 075            _logger.LogError(ex, "Error al crear descuento personal");
 076            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 77        }
 478    }
 79
 80    /// <summary>
 81    /// Listar descuentos personales del período
 82    /// GET /api/descuentos-personales?periodoId=...&cedulaTitular=...&codigoConcepto=...&estado=...
 83    /// </summary>
 84    [HttpGet]
 85    [FAU.API.Security.RequirePermission(PermisoEnum.VerDescuentosPersonales)]
 86    public async Task<IActionResult> Listar(
 87        [FromQuery] long periodoId,
 88        [FromQuery] string? cedulaTitular = null,
 89        [FromQuery] int? codigoConcepto = null,
 90        [FromQuery] string? estado = null)
 91    {
 92        try
 93        {
 194            if (periodoId <= 0)
 095                return BadRequest(ApiResponse<string>.ErrorResult("periodoId es requerido"));
 96
 197            var items = await _service.ListarAsync(periodoId, cedulaTitular, codigoConcepto, estado);
 98
 199            var response = items.Select(d => new
 1100            {
 1101                id = d.Id,
 1102                periodoId = d.PeriodoId,
 1103                personaId = d.PersonaId,
 1104                cedula = d.Persona?.Cedula,
 1105                nombreCompleto = d.Persona?.NombreCompleto,
 1106                catalogoItemId = d.CatalogoItemId,
 1107                codigoConcepto = d.CatalogoItem?.Codigo,
 1108                nombreConcepto = d.CatalogoItem?.Nombre,
 1109                importe = d.Importe,
 1110                estado = d.Estado,
 1111                observaciones = d.Observaciones,
 1112                fechaCreacion = d.FechaCreacion,
 1113                usuarioCreacionId = d.UsuarioCreacionId
 1114            });
 115
 1116            return Ok(ApiResponse<object>.SuccessResult(response));
 117        }
 0118        catch (Exception ex)
 119        {
 0120            _logger.LogError(ex, "Error al listar descuentos personales");
 0121            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 122        }
 1123    }
 124
 125    /// <summary>
 126    /// Editar un descuento personal en borrador
 127    /// PUT /api/descuentos-personales/{id}
 128    /// </summary>
 129    [HttpPut("{id}")]
 130    [FAU.API.Security.RequirePermission(PermisoEnum.ActualizarDescuentosPersonales)]
 131    public async Task<IActionResult> Editar(long id, [FromBody] EditarDescuentoPersonalRequest request)
 132    {
 133        try
 134        {
 2135            if (request.Importe <= 0)
 0136                return BadRequest(ApiResponse<string>.ErrorResult("importe debe ser mayor a cero"));
 137
 2138            var actualizado = await _service.EditarAsync(id, request.Importe, request.Observaciones);
 1139            return Ok(ApiResponse<object>.SuccessResult(
 1140                new { id = actualizado.Id, actualizado = true },
 1141                "Descuento personal actualizado exitosamente"));
 142        }
 0143        catch (ArgumentException ex)
 144        {
 0145            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 146        }
 1147        catch (InvalidOperationException ex)
 148        {
 1149            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 150        }
 0151        catch (Exception ex)
 152        {
 0153            _logger.LogError(ex, "Error al actualizar descuento personal {Id}", id);
 0154            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 155        }
 2156    }
 157
 158    /// <summary>
 159    /// Eliminar un descuento personal en borrador
 160    /// DELETE /api/descuentos-personales/{id}
 161    /// </summary>
 162    [HttpDelete("{id}")]
 163    [FAU.API.Security.RequirePermission(PermisoEnum.ActualizarDescuentosPersonales)]
 164    public async Task<IActionResult> Eliminar(long id)
 165    {
 166        try
 167        {
 2168            await _service.EliminarAsync(id);
 1169            return NoContent();
 170        }
 0171        catch (ArgumentException ex)
 172        {
 0173            return NotFound(ApiResponse<string>.ErrorResult(ex.Message));
 174        }
 1175        catch (InvalidOperationException ex)
 176        {
 1177            return Conflict(ApiResponse<string>.ErrorResult(ex.Message));
 178        }
 0179        catch (Exception ex)
 180        {
 0181            _logger.LogError(ex, "Error al eliminar descuento personal {Id}", id);
 0182            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 183        }
 2184    }
 185
 186    /// <summary>
 187    /// Confirmar todos los borradores de un período
 188    /// POST /api/descuentos-personales/confirmar
 189    /// </summary>
 190    [HttpPost("confirmar")]
 191    [FAU.API.Security.RequirePermission(PermisoEnum.ConfirmarDescuentosPersonales)]
 192    public async Task<IActionResult> Confirmar([FromBody] ConfirmarDescuentosRequest request)
 193    {
 194        try
 195        {
 2196            if (request.PeriodoId <= 0)
 0197                return BadRequest(ApiResponse<string>.ErrorResult("periodoId es requerido"));
 198
 2199            var cantidad = await _service.ConfirmarBorradoresAsync(request.PeriodoId);
 1200            return Ok(ApiResponse<object>.SuccessResult(
 1201                new { confirmados = cantidad },
 1202                $"Se confirmaron {cantidad} descuento(s) personal(es)"));
 203        }
 1204        catch (Exception ex)
 205        {
 1206            _logger.LogError(ex, "Error al confirmar descuentos personales del período {PeriodoId}", request.PeriodoId);
 1207            return StatusCode(500, ApiResponse<string>.ErrorResult("Error interno del servidor"));
 208        }
 2209    }
 210}
 211
 212public class CrearDescuentoPersonalRequest
 213{
 214    [Required]
 215    public long PeriodoId { get; set; }
 216
 217    [Required]
 218    [MaxLength(12)]
 219    public string CedulaTitular { get; set; } = string.Empty;
 220
 221    [Required]
 222    public int CodigoConcepto { get; set; }
 223
 224    [Required]
 225    public decimal Importe { get; set; }
 226
 227    [MaxLength(500)]
 228    public string? Observaciones { get; set; }
 229}
 230
 231public class EditarDescuentoPersonalRequest
 232{
 233    [Required]
 234    public decimal Importe { get; set; }
 235
 236    [MaxLength(500)]
 237    public string? Observaciones { get; set; }
 238}
 239
 240public class ConfirmarDescuentosRequest
 241{
 242    [Required]
 243    public long PeriodoId { get; set; }
 244}