< Summary

Information
Class: FAU.Logica.Services.DescuentoPersonalService
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/DescuentoPersonalService.cs
Line coverage
87%
Covered lines: 68
Uncovered lines: 10
Coverable lines: 78
Total lines: 134
Line coverage: 87.1%
Branch coverage
66%
Covered branches: 28
Total branches: 42
Branch coverage: 66.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%
CrearAsync()72.72%222291.66%
EditarAsync()75%8891.66%
EliminarAsync()75%44100%
ConfirmarAsync()75%44100%
ListarAsync()0%2040%
ConfirmarBorradoresAsync(...)100%11100%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/DescuentoPersonalService.cs

#LineLine coverage
 1using FAU.DataAccess;
 2using FAU.DataAccess.Repositories;
 3using FAU.Entidades;
 4using Microsoft.EntityFrameworkCore;
 5
 6namespace FAU.Logica.Services;
 7
 8public class DescuentoPersonalService : IDescuentoPersonalService
 9{
 10    private readonly IDescuentoPersonalRepository _repo;
 11    private readonly IPersonalRepository          _personalRepo;
 12    private readonly IPeriodosRepository          _periodosRepo;
 13    private readonly ApplicationDbContext         _context;
 14
 1215    public DescuentoPersonalService(
 1216        IDescuentoPersonalRepository repo,
 1217        IPersonalRepository personalRepo,
 1218        IPeriodosRepository periodosRepo,
 1219        ApplicationDbContext context)
 20    {
 1221        _repo         = repo;
 1222        _personalRepo = personalRepo;
 1223        _periodosRepo = periodosRepo;
 1224        _context      = context;
 1225    }
 26
 27    public async Task<DescuentoPersonalPeriodo> CrearAsync(
 28        long periodoId, string cedulaTitular, int codigoConcepto, long acreedorId,
 29        decimal importe, string? observaciones, long usuarioId, DateTime? fechaComunicacion = null)
 30    {
 531        if (importe <= 0)
 132            throw new ArgumentException("El importe debe ser mayor a cero.");
 33
 434        if (acreedorId <= 0)
 035            throw new ArgumentException("El acreedor es requerido.");
 36
 437        var relacion = await _personalRepo.GetByCedulaAsync(cedulaTitular)
 438            ?? throw new ArgumentException($"Funcionario {cedulaTitular} no encontrado.");
 39
 440        var periodo = await _periodosRepo.ObtenerPorIdAsync(periodoId)
 441            ?? throw new ArgumentException($"Período {periodoId} no encontrado.");
 42
 443        if (periodo.Estado != "ABIERTA" && periodo.Estado != Periodo.EstadoListoPCalculo)
 144            throw new InvalidOperationException($"El período está en estado {periodo.Estado} y no admite modificaciones.
 45
 346        var catalogoItem = await _context.CatalogoItems
 347            .FirstOrDefaultAsync(c => c.Codigo == codigoConcepto && c.Vigente)
 348            ?? throw new ArgumentException($"Concepto con código {codigoConcepto} no encontrado o no vigente.");
 49
 350        if (catalogoItem.Tipo != "descuento_personal")
 151            throw new InvalidOperationException($"El concepto {codigoConcepto} (tipo '{catalogoItem.Tipo}') no es un des
 52
 253        if (catalogoItem.ItemParFictoId.HasValue)
 054            throw new InvalidOperationException(
 055                "Los fictos se gestionan en el padrón permanente mediante /api/fictos.");
 56
 257        var acreedor = await _context.Acreedores
 258            .AsNoTracking()
 259            .FirstOrDefaultAsync(a => a.Id == acreedorId && a.Activo)
 260            ?? throw new ArgumentException($"Acreedor {acreedorId} no encontrado o no activo.");
 61
 162        var descuento = new DescuentoPersonalPeriodo
 163        {
 164            PeriodoId         = periodoId,
 165            PersonaId         = relacion.PersonaId,
 166            AcreedorId        = acreedor.Id,
 167            CatalogoItemId    = catalogoItem.Id,
 168            Importe           = importe,
 169            Estado            = "borrador",
 170            Observaciones     = observaciones,
 171            FechaComunicacion = fechaComunicacion ?? DateTime.Now,
 172            UsuarioCreacionId = usuarioId
 173        };
 74
 175        return await _repo.CreateAsync(descuento);
 176    }
 77
 78    public async Task<DescuentoPersonalPeriodo> EditarAsync(long id, decimal importe, string? observaciones, DateTime? f
 79    {
 280        if (importe <= 0)
 081            throw new ArgumentException("El importe debe ser mayor a cero.");
 82
 283        var d = await _repo.GetByIdAsync(id)
 284            ?? throw new ArgumentException($"Descuento {id} no encontrado.");
 85
 286        if (d.Estado != "borrador")
 187            throw new InvalidOperationException("Solo se pueden editar descuentos en estado borrador.");
 88
 189        d.Importe      = importe;
 190        d.Observaciones = observaciones;
 191        if (fechaComunicacion.HasValue)
 192            d.FechaComunicacion = fechaComunicacion.Value;
 93
 194        return await _repo.UpdateAsync(d);
 195    }
 96
 97    public async Task EliminarAsync(long id)
 98    {
 299        var d = await _repo.GetByIdAsync(id)
 2100            ?? throw new ArgumentException($"Descuento {id} no encontrado.");
 101
 2102        if (d.Estado != "borrador")
 1103            throw new InvalidOperationException("Solo se pueden eliminar descuentos en estado borrador.");
 104
 1105        await _repo.DeleteAsync(id);
 1106    }
 107
 108    public async Task<DescuentoPersonalPeriodo> ConfirmarAsync(long id)
 109    {
 2110        var descuento = await _repo.GetByIdAsync(id)
 2111            ?? throw new ArgumentException($"Descuento {id} no encontrado.");
 112
 2113        if (descuento.Estado != "borrador")
 1114            throw new InvalidOperationException("Solo se pueden confirmar descuentos en estado borrador.");
 115
 1116        descuento.Estado = "confirmado";
 1117        return await _repo.UpdateAsync(descuento);
 1118    }
 119
 120    public async Task<IEnumerable<DescuentoPersonalPeriodo>> ListarAsync(
 121        long periodoId, string? cedulaTitular, int? codigoConcepto, string? estado)
 122    {
 0123        long? personaId = null;
 0124        if (!string.IsNullOrEmpty(cedulaTitular))
 125        {
 0126            var relacion = await _personalRepo.GetByCedulaAsync(cedulaTitular);
 0127            personaId = relacion?.PersonaId;
 128        }
 0129        return await _repo.GetByPeriodoAsync(periodoId, personaId, codigoConcepto, estado);
 0130    }
 131
 132    public Task<int> ConfirmarBorradoresAsync(long periodoId) =>
 1133        _repo.ConfirmarBorradoresAsync(periodoId);
 134}