< Summary

Information
Class: FAU.Logica.Services.InsumosPeriodoLoader
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/InsumosPeriodoLoader.cs
Line coverage
91%
Covered lines: 159
Uncovered lines: 15
Coverable lines: 174
Total lines: 236
Line coverage: 91.3%
Branch coverage
38%
Covered branches: 7
Total branches: 18
Branch coverage: 38.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
CargarAsync()60%101097.65%

File(s)

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

#LineLine coverage
 1using FAU.DataAccess;
 2using FAU.Entidades;
 3using FAU.Logica.DTOs;
 4using Microsoft.EntityFrameworkCore;
 5
 6namespace FAU.Logica.Services;
 7
 8public class InsumosPeriodoLoader : IInsumosPeriodoLoader
 9{
 10    private readonly ApplicationDbContext _context;
 11
 1512    public InsumosPeriodoLoader(ApplicationDbContext context)
 13    {
 1514        _context = context;
 1515    }
 16
 17    public async Task<InsumosPeriodo> CargarAsync(long periodoId)
 18    {
 1519        var periodo = await _context.PeriodosLiquidacion
 1520            .AsNoTracking()
 1521            .FirstOrDefaultAsync(p => p.Id == periodoId && p.Activo);
 22
 1523        if (periodo is null)
 24        {
 025            throw new InvalidOperationException($"Periodo de liquidación {periodoId} no encontrado o no está activo.");
 26        }
 27
 1528        var periodoDate = new DateTime(periodo.Anio, periodo.Mes, 1);
 1529        var ultimoDiaPeriodo = new DateTime(periodo.Anio, periodo.Mes, DateTime.DaysInMonth(periodo.Anio, periodo.Mes));
 30
 1531        var parametros = await _context.ParametrosPeriodo
 1532            .AsNoTracking()
 1533            .FirstOrDefaultAsync(pp => pp.Anio == periodo.Anio && pp.Mes == periodo.Mes);
 34
 1535        if (parametros is null)
 36        {
 037            throw new InvalidOperationException($"Parámetros de período para {periodo.Anio}/{periodo.Mes} no encontrados
 38        }
 39
 1540        var catalogoItems = await _context.CatalogoItems
 1541            .AsNoTracking()
 1542            .ToListAsync();
 43
 1544        var remuneraciones = await _context.RemuneracionesGrado
 1545            .AsNoTracking()
 1546            .Include(r => r.Item)
 1547            .Where(r => r.VigenteDesde <= periodoDate && (r.VigenteHasta == null || r.VigenteHasta >= periodoDate))
 1548            .ToListAsync();
 49
 1550        var permanencias = await _context.Set<TablaPermanencia>()
 1551            .AsNoTracking()
 1552            .Where(t => t.VigenteDesde <= periodoDate && (t.VigenteHasta == null || t.VigenteHasta >= periodoDate))
 1553            .ToListAsync();
 54
 1555        var franjasIrpfRaw = await _context.FranjasIrpf
 1556            .AsNoTracking()
 1557            .Where(f => f.VigenteDesde <= periodoDate && (f.VigenteHasta == null || f.VigenteHasta >= periodoDate))
 1558            .ToListAsync();
 59
 60        // Deduplicar: una franja por NumeroFranja, la más reciente según VigenteDesde
 1561        var franjasIrpf = franjasIrpfRaw
 2962            .GroupBy(f => f.NumeroFranja)
 5863            .Select(g => g.OrderByDescending(f => f.VigenteDesde).First())
 2964            .OrderBy(f => f.NumeroFranja)
 1565            .ToList();
 66
 1567        var beneficios = await _context.BeneficiosSociales
 1568            .AsNoTracking()
 1569            .Where(b => b.Estado == "activo"
 1570                     && b.VigenteDesde <= ultimoDiaPeriodo          // inició antes del fin del período
 1571                     && (b.VigenteHasta == null || b.VigenteHasta >= periodoDate))  // no terminó antes del inicio
 1572            .ToListAsync();
 73
 1574        var tiposBeneficio = await _context.TiposBeneficio
 1575            .AsNoTracking()
 1576            .ToDictionaryAsync(t => t.Id);
 77
 3278        foreach (var b in beneficios)
 79        {
 180            if (tiposBeneficio.TryGetValue(b.TipoBeneficioId, out var tipo))
 081                b.TipoBeneficio = tipo;
 82        }
 83
 84        // Cargar hijos registrados para beneficios de tipo Asignación Familiar
 1585        var idsAsigFamiliar = beneficios
 186            .Where(b => b.TipoBeneficio is not null &&
 187                        (b.TipoBeneficio.Codigo == "ASIGNACION_FAMILIAR" ||
 188                         b.TipoBeneficio.Codigo.StartsWith("300") ||
 189                         b.TipoBeneficio.Nombre.ToUpperInvariant().Contains("ASIGNACION FAMILIAR") ||
 190                         b.TipoBeneficio.Nombre.ToUpperInvariant().Contains("ASIGNACIÓN FAMILIAR")))
 091            .Select(b => b.Id)
 1592            .ToHashSet();
 93
 1594        var beneficiariosAsigFam = idsAsigFamiliar.Count > 0
 1595            ? await _context.BeneficioSocialBeneficiarios
 1596                .AsNoTracking()
 1597                .Where(bh => idsAsigFamiliar.Contains(bh.BeneficioId) &&
 1598                             bh.Activo &&
 1599                             bh.VigenteDesde <= ultimoDiaPeriodo &&
 15100                             (bh.VigenteHasta == null || bh.VigenteHasta >= periodoDate))
 15101                .ToListAsync()
 15102            : [];
 103
 15104        var beneficiariosPorBeneficio = beneficiariosAsigFam
 0105            .GroupBy(bh => bh.BeneficioId)
 15106            .ToDictionary(g => g.Key, g => (IReadOnlyList<BeneficioSocialBeneficiario>)g.ToList());
 107
 15108        var compensaciones = await _context.ItemsLoteCompensacion
 15109            .AsNoTracking()
 15110            .Include(i => i.LoteCompensacion)
 15111                .ThenInclude(l => l.TipoCompensacion)
 15112                .ThenInclude(t => t.Configuraciones)
 15113                    .ThenInclude(c => c.CatalogoItem)
 15114            .Where(i => i.LoteCompensacion.Estado == "aprobado"
 15115                        && i.LoteCompensacion.Periodo.Year == periodo.Anio
 15116                        && i.LoteCompensacion.Periodo.Month == periodo.Mes)
 15117            .ToListAsync();
 118
 15119        var novedadesConfirmadas = await _context.NovedadesPeriodo
 15120            .AsNoTracking()
 15121            .Where(n => n.PeriodoId == periodoId && n.Estado == "confirmada")
 15122            .ToListAsync();
 123
 15124        var remuneracionesPorGrado = remuneraciones
 35125            .GroupBy(r => r.GradoId)
 15126            .ToDictionary(
 16127                g => g.Key,
 31128                g => (IReadOnlyDictionary<int, RemuneracionGrado>)g
 35129                    .GroupBy(r => r.Item.Codigo)
 31130                    .ToDictionary(
 35131                        gg => gg.Key,
 101132                        gg => gg.OrderByDescending(r => r.VigenteDesde).First()));
 133
 15134        var permanenciasPorEscalafon = permanencias
 1135            .GroupBy(t => t.EscalafonId)
 18136            .ToDictionary(g => g.Key, g => (IReadOnlyList<TablaPermanencia>)g.OrderBy(t => t.AniosDesde).ToList());
 137
 15138        var beneficiosPorPersona = beneficios
 1139            .GroupBy(b => b.PersonaId)
 17140            .ToDictionary(g => g.Key, g => (IReadOnlyList<BeneficioSocial>)g.ToList());
 141
 15142        var compensacionesPorPersona = compensaciones
 3143            .GroupBy(i => i.PersonaId)
 21144            .ToDictionary(g => g.Key, g => (IReadOnlyList<ItemLoteCompensacion>)g.ToList());
 145
 15146        var novedadesPorPersona = novedadesConfirmadas
 3147            .GroupBy(n => n.PersonaId)
 21148            .ToDictionary(g => g.Key, g => (IReadOnlyList<NovedadPeriodo>)g.ToList());
 149
 150        // Instructivo Asignación Familiar: fila más reciente por tipo_franja
 15151        var instructivoAsigFamiliarRaw = await _context.InstructivosAsigFamiliar
 15152            .AsNoTracking()
 15153            .Where(i => i.VigenteDesde <= periodoDate)
 15154            .ToListAsync();
 155
 15156        var instructivoAsigFamiliar = instructivoAsigFamiliarRaw
 0157            .GroupBy(i => i.TipoFranja)
 15158            .ToDictionary(
 0159                g => g.Key,
 15160                g => g.OrderByDescending(i => i.VigenteDesde).First());
 161
 162        // Instructivo PSF: fila más reciente por numero_categoria
 15163        var instructivoPsfRaw = await _context.InstructivosPsf
 15164            .AsNoTracking()
 15165            .Where(i => i.VigenteDesde <= periodoDate)
 15166            .ToListAsync();
 167
 15168        var instructivoPsf = instructivoPsfRaw
 0169            .GroupBy(i => (int)i.NumeroCategoria)
 15170            .ToDictionary(
 0171                g => g.Key,
 15172                g => g.OrderByDescending(i => i.VigenteDesde).First());
 173
 174        // Tabla Hogar: tramos vigentes, ordenados ASC con NULL al final
 15175        var tablaPorHogarRaw = await _context.TablasHogarConstituido
 15176            .AsNoTracking()
 15177            .Where(t => t.VigenteDesde <= periodoDate)
 15178            .ToListAsync();
 179
 15180        var tablaPorHogar = tablaPorHogarRaw
 0181            .GroupBy(t => t.HastaHaberes)
 0182            .Select(g => g.OrderByDescending(t => t.VigenteDesde).First())
 0183            .OrderBy(t => t.HastaHaberes.HasValue ? 0 : 1)
 0184            .ThenBy(t => t.HastaHaberes ?? decimal.MaxValue)
 15185            .ToList();
 186
 15187        var aguinaldos = await _context.Set<Aguinaldo>()
 15188            .AsNoTracking()
 15189            .Where(a => a.Anio == periodo.Anio)
 15190            .ToListAsync();
 191
 15192        var aguinaldosPorPersona = aguinaldos
 0193            .GroupBy(a => a.PersonaId)
 15194            .ToDictionary(g => g.Key, g => (IReadOnlyList<Aguinaldo>)g.ToList());
 195
 15196        var ordenPorGrado = await _context.Grados
 15197            .AsNoTracking()
 15198            .Where(g => g.Vigente)
 45199            .ToDictionaryAsync(g => g.Id, g => g.Orden);
 200
 15201        var diferenciaAscenso = await _context.CompensacionesDiferenciaAscenso
 15202            .AsNoTracking()
 15203            .Where(c => c.PeriodoId == periodoId && c.Estado == "pendiente")
 16204            .ToDictionaryAsync(c => c.PersonaId);
 205
 15206        var descuentosPersonales = await _context.DescuentosPersonalesPeriodo
 15207            .AsNoTracking()
 15208            .Where(d => d.PeriodoId == periodoId && d.Estado == "aprobado")
 15209            .ToListAsync();
 210
 15211        var descuentosPersonalesPorPersona = descuentosPersonales
 0212            .GroupBy(d => d.PersonaId)
 15213            .ToDictionary(g => g.Key, g => (IReadOnlyList<DescuentoPersonalPeriodo>)g.ToList());
 214
 15215        return new InsumosPeriodo
 15216        {
 15217            PeriodoId = periodoId,
 15218            ParametroPeriodo = parametros,
 15219            CatalogoItems = catalogoItems,
 15220            RemuneracionesPorGrado = remuneracionesPorGrado,
 15221            PermanenciasPorEscalafon = permanenciasPorEscalafon,
 15222            FranjasIrpf = franjasIrpf,
 15223            BeneficiosPorPersona = beneficiosPorPersona,
 15224            CompensacionesPorPersona = compensacionesPorPersona,
 15225            NovedadesPorPersona = novedadesPorPersona,
 15226            BeneficiariosPorBeneficio = beneficiariosPorBeneficio,
 15227            InstructivoAsigFamiliar = instructivoAsigFamiliar,
 15228            InstructivoPsf = instructivoPsf,
 15229            TablaPorHogar = tablaPorHogar,
 15230            AguinaldosPorPersona = aguinaldosPorPersona,
 15231            OrdenPorGrado = ordenPorGrado,
 15232            CompensacionesDiferenciaAscensoPorPersona = diferenciaAscenso,
 15233            DescuentosPersonalesPorPersona = descuentosPersonalesPorPersona
 15234        };
 15235    }
 236}