< 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
90%
Covered lines: 166
Uncovered lines: 18
Coverable lines: 184
Total lines: 250
Line coverage: 90.2%
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.77%

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
 1612    public InsumosPeriodoLoader(ApplicationDbContext context)
 13    {
 1614        _context = context;
 1615    }
 16
 17    public async Task<InsumosPeriodo> CargarAsync(long periodoId)
 18    {
 1619        var periodo = await _context.PeriodosLiquidacion
 1620            .AsNoTracking()
 1621            .FirstOrDefaultAsync(p => p.Id == periodoId && p.Activo);
 22
 1623        if (periodo is null)
 24        {
 025            throw new InvalidOperationException($"Periodo de liquidación {periodoId} no encontrado o no está activo.");
 26        }
 27
 1628        var periodoDate = new DateTime(periodo.Anio, periodo.Mes, 1);
 1629        var ultimoDiaPeriodo = new DateTime(periodo.Anio, periodo.Mes, DateTime.DaysInMonth(periodo.Anio, periodo.Mes));
 30
 1631        var parametros = await _context.ParametrosPeriodo
 1632            .AsNoTracking()
 1633            .FirstOrDefaultAsync(pp => pp.Anio == periodo.Anio && pp.Mes == periodo.Mes);
 34
 1635        if (parametros is null)
 36        {
 037            throw new InvalidOperationException($"Parámetros de período para {periodo.Anio}/{periodo.Mes} no encontrados
 38        }
 39
 1640        var catalogoItems = await _context.CatalogoItems
 1641            .AsNoTracking()
 1642            .ToListAsync();
 43
 1644        var remuneraciones = await _context.RemuneracionesGrado
 1645            .AsNoTracking()
 1646            .Include(r => r.Item)
 1647            .Where(r => r.VigenteDesde <= periodoDate && (r.VigenteHasta == null || r.VigenteHasta >= periodoDate))
 1648            .ToListAsync();
 49
 1650        var permanencias = await _context.Set<TablaPermanencia>()
 1651            .AsNoTracking()
 1652            .Where(t => t.VigenteDesde <= periodoDate && (t.VigenteHasta == null || t.VigenteHasta >= periodoDate))
 1653            .ToListAsync();
 54
 1655        var franjasIrpfRaw = await _context.FranjasIrpf
 1656            .AsNoTracking()
 1657            .Where(f => f.VigenteDesde <= periodoDate && (f.VigenteHasta == null || f.VigenteHasta >= periodoDate))
 1658            .ToListAsync();
 59
 60        // Deduplicar: una franja por NumeroFranja, la más reciente según VigenteDesde
 1661        var franjasIrpf = franjasIrpfRaw
 3262            .GroupBy(f => f.NumeroFranja)
 6463            .Select(g => g.OrderByDescending(f => f.VigenteDesde).First())
 3264            .OrderBy(f => f.NumeroFranja)
 1665            .ToList();
 66
 67        // Tramos de Sanidad Militar vigentes (Art. 94 Ley 18.834)
 1668        var tramosSanidadRaw = await _context.TramosSanidadMilitar
 1669            .AsNoTracking()
 1670            .Where(t => t.VigenteDesde <= periodoDate && (t.VigenteHasta == null || t.VigenteHasta >= periodoDate))
 1671            .ToListAsync();
 72
 73        // Deduplicar por código de retención, el más reciente según VigenteDesde; ordenar por Desde
 1674        var tramosSanidad = tramosSanidadRaw
 075            .GroupBy(t => t.CodigoRetencion)
 076            .Select(g => g.OrderByDescending(t => t.VigenteDesde).First())
 077            .OrderBy(t => t.Desde)
 1678            .ToList();
 79
 1680        var beneficios = await _context.BeneficiosSociales
 1681            .AsNoTracking()
 1682            .Where(b => b.Estado == "activo"
 1683                     && b.VigenteDesde <= ultimoDiaPeriodo          // inició antes del fin del período
 1684                     && (b.VigenteHasta == null || b.VigenteHasta >= periodoDate))  // no terminó antes del inicio
 1685            .ToListAsync();
 86
 1687        var tiposBeneficio = await _context.TiposBeneficio
 1688            .AsNoTracking()
 1689            .ToDictionaryAsync(t => t.Id);
 90
 3491        foreach (var b in beneficios)
 92        {
 193            if (tiposBeneficio.TryGetValue(b.TipoBeneficioId, out var tipo))
 094                b.TipoBeneficio = tipo;
 95        }
 96
 97        // Cargar hijos registrados para beneficios de tipo Asignación Familiar
 1698        var idsAsigFamiliar = beneficios
 199            .Where(b => b.TipoBeneficio is not null &&
 1100                        (b.TipoBeneficio.Codigo == "ASIGNACION_FAMILIAR" ||
 1101                         b.TipoBeneficio.Codigo.StartsWith("300") ||
 1102                         b.TipoBeneficio.Nombre.ToUpperInvariant().Contains("ASIGNACION FAMILIAR") ||
 1103                         b.TipoBeneficio.Nombre.ToUpperInvariant().Contains("ASIGNACIÓN FAMILIAR")))
 0104            .Select(b => b.Id)
 16105            .ToHashSet();
 106
 16107        var beneficiariosAsigFam = idsAsigFamiliar.Count > 0
 16108            ? await _context.BeneficioSocialBeneficiarios
 16109                .AsNoTracking()
 16110                .Where(bh => idsAsigFamiliar.Contains(bh.BeneficioId) &&
 16111                             bh.Activo &&
 16112                             bh.VigenteDesde <= ultimoDiaPeriodo &&
 16113                             (bh.VigenteHasta == null || bh.VigenteHasta >= periodoDate))
 16114                .ToListAsync()
 16115            : [];
 116
 16117        var beneficiariosPorBeneficio = beneficiariosAsigFam
 0118            .GroupBy(bh => bh.BeneficioId)
 16119            .ToDictionary(g => g.Key, g => (IReadOnlyList<BeneficioSocialBeneficiario>)g.ToList());
 120
 16121        var compensaciones = await _context.ItemsLoteCompensacion
 16122            .AsNoTracking()
 16123            .Include(i => i.LoteCompensacion)
 16124                .ThenInclude(l => l.TipoCompensacion)
 16125                .ThenInclude(t => t.Configuraciones)
 16126                    .ThenInclude(c => c.CatalogoItem)
 16127            .Where(i => i.LoteCompensacion.Estado == "aprobado"
 16128                        && i.LoteCompensacion.Periodo.Year == periodo.Anio
 16129                        && i.LoteCompensacion.Periodo.Month == periodo.Mes)
 16130            .ToListAsync();
 131
 16132        var novedadesConfirmadas = await _context.NovedadesPeriodo
 16133            .AsNoTracking()
 16134            .Where(n => n.PeriodoId == periodoId && n.Estado == "confirmada")
 16135            .ToListAsync();
 136
 16137        var remuneracionesPorGrado = remuneraciones
 37138            .GroupBy(r => r.GradoId)
 16139            .ToDictionary(
 17140                g => g.Key,
 33141                g => (IReadOnlyDictionary<int, RemuneracionGrado>)g
 37142                    .GroupBy(r => r.Item.Codigo)
 33143                    .ToDictionary(
 37144                        gg => gg.Key,
 107145                        gg => gg.OrderByDescending(r => r.VigenteDesde).First()));
 146
 16147        var permanenciasPorEscalafon = permanencias
 1148            .GroupBy(t => t.EscalafonId)
 19149            .ToDictionary(g => g.Key, g => (IReadOnlyList<TablaPermanencia>)g.OrderBy(t => t.AniosDesde).ToList());
 150
 16151        var beneficiosPorPersona = beneficios
 1152            .GroupBy(b => b.PersonaId)
 18153            .ToDictionary(g => g.Key, g => (IReadOnlyList<BeneficioSocial>)g.ToList());
 154
 16155        var compensacionesPorPersona = compensaciones
 3156            .GroupBy(i => i.PersonaId)
 22157            .ToDictionary(g => g.Key, g => (IReadOnlyList<ItemLoteCompensacion>)g.ToList());
 158
 16159        var novedadesPorPersona = novedadesConfirmadas
 4160            .GroupBy(n => n.PersonaId)
 24161            .ToDictionary(g => g.Key, g => (IReadOnlyList<NovedadPeriodo>)g.ToList());
 162
 163        // Instructivo Asignación Familiar: fila más reciente por tipo_franja
 16164        var instructivoAsigFamiliarRaw = await _context.InstructivosAsigFamiliar
 16165            .AsNoTracking()
 16166            .Where(i => i.VigenteDesde <= periodoDate)
 16167            .ToListAsync();
 168
 16169        var instructivoAsigFamiliar = instructivoAsigFamiliarRaw
 0170            .GroupBy(i => i.TipoFranja)
 16171            .ToDictionary(
 0172                g => g.Key,
 16173                g => g.OrderByDescending(i => i.VigenteDesde).First());
 174
 175        // Instructivo PSF: fila más reciente por numero_categoria
 16176        var instructivoPsfRaw = await _context.InstructivosPsf
 16177            .AsNoTracking()
 16178            .Where(i => i.VigenteDesde <= periodoDate)
 16179            .ToListAsync();
 180
 16181        var instructivoPsf = instructivoPsfRaw
 0182            .GroupBy(i => (int)i.NumeroCategoria)
 16183            .ToDictionary(
 0184                g => g.Key,
 16185                g => g.OrderByDescending(i => i.VigenteDesde).First());
 186
 187        // Tabla Hogar: tramos vigentes, ordenados ASC con NULL al final
 16188        var tablaPorHogarRaw = await _context.TablasHogarConstituido
 16189            .AsNoTracking()
 16190            .Where(t => t.VigenteDesde <= periodoDate)
 16191            .ToListAsync();
 192
 16193        var tablaPorHogar = tablaPorHogarRaw
 0194            .GroupBy(t => t.HastaHaberes)
 0195            .Select(g => g.OrderByDescending(t => t.VigenteDesde).First())
 0196            .OrderBy(t => t.HastaHaberes.HasValue ? 0 : 1)
 0197            .ThenBy(t => t.HastaHaberes ?? decimal.MaxValue)
 16198            .ToList();
 199
 16200        var aguinaldos = await _context.Set<Aguinaldo>()
 16201            .AsNoTracking()
 16202            .Where(a => a.Anio == periodo.Anio)
 16203            .ToListAsync();
 204
 16205        var aguinaldosPorPersona = aguinaldos
 0206            .GroupBy(a => a.PersonaId)
 16207            .ToDictionary(g => g.Key, g => (IReadOnlyList<Aguinaldo>)g.ToList());
 208
 16209        var ordenPorGrado = await _context.Grados
 16210            .AsNoTracking()
 16211            .Where(g => g.Vigente)
 48212            .ToDictionaryAsync(g => g.Id, g => g.Orden);
 213
 16214        var diferenciaAscenso = await _context.CompensacionesDiferenciaAscenso
 16215            .AsNoTracking()
 16216            .Where(c => c.PeriodoId == periodoId && c.Estado == "pendiente")
 17217            .ToDictionaryAsync(c => c.PersonaId);
 218
 16219        var descuentosPersonales = await _context.DescuentosPersonalesPeriodo
 16220            .AsNoTracking()
 16221            .Where(d => d.PeriodoId == periodoId && d.Estado == "aprobado")
 16222            .ToListAsync();
 223
 16224        var descuentosPersonalesPorPersona = descuentosPersonales
 0225            .GroupBy(d => d.PersonaId)
 16226            .ToDictionary(g => g.Key, g => (IReadOnlyList<DescuentoPersonalPeriodo>)g.ToList());
 227
 16228        return new InsumosPeriodo
 16229        {
 16230            PeriodoId = periodoId,
 16231            ParametroPeriodo = parametros,
 16232            CatalogoItems = catalogoItems,
 16233            RemuneracionesPorGrado = remuneracionesPorGrado,
 16234            PermanenciasPorEscalafon = permanenciasPorEscalafon,
 16235            FranjasIrpf = franjasIrpf,
 16236            TramosSanidad = tramosSanidad,
 16237            BeneficiosPorPersona = beneficiosPorPersona,
 16238            CompensacionesPorPersona = compensacionesPorPersona,
 16239            NovedadesPorPersona = novedadesPorPersona,
 16240            BeneficiariosPorBeneficio = beneficiariosPorBeneficio,
 16241            InstructivoAsigFamiliar = instructivoAsigFamiliar,
 16242            InstructivoPsf = instructivoPsf,
 16243            TablaPorHogar = tablaPorHogar,
 16244            AguinaldosPorPersona = aguinaldosPorPersona,
 16245            OrdenPorGrado = ordenPorGrado,
 16246            CompensacionesDiferenciaAscensoPorPersona = diferenciaAscenso,
 16247            DescuentosPersonalesPorPersona = descuentosPersonalesPorPersona
 16248        };
 16249    }
 250}