< Summary

Information
Class: FAU.Logica.Services.AguinaldoValidador
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/AguinaldoValidador.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 72
Coverable lines: 72
Total lines: 119
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
ValidarHistoricoSemestralAsync()0%4260%
ObtenerMesesSemestre(...)0%2040%
FormatearMesAnio(...)100%210%

File(s)

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

#LineLine coverage
 1using FAU.DataAccess;
 2using FAU.DataAccess.Repositories;
 3using FAU.Logica.DTOs;
 4using Microsoft.EntityFrameworkCore;
 5
 6namespace FAU.Logica.Services;
 7
 8public class AguinaldoValidador : IAguinaldoValidador
 9{
 10    private readonly IPersonalRepository _personalRepository;
 11    private readonly ApplicationDbContext _context;
 12
 013    public AguinaldoValidador(
 014        IPersonalRepository personalRepository,
 015        ApplicationDbContext context)
 16    {
 017        _personalRepository = personalRepository;
 018        _context = context;
 019    }
 20
 21    public async Task<AguinaldoValidacionDto> ValidarHistoricoSemestralAsync(CalcularAguinaldoSemestralRequest request)
 22    {
 023        var mesesSemestre = ObtenerMesesSemestre(request);
 024        var activos = (await _personalRepository.GetActivosAsync()).ToList();
 25
 026        var personaIds = activos.Select(a => a.PersonaId).ToList();
 027        var aniosSemestre = mesesSemestre.Select(m => m.Anio).Distinct().ToList();
 028        var mesesIds = mesesSemestre.Select(m => m.Mes).Distinct().ToList();
 29
 30        // Fetch loose from DB (cross-year false positives filtered in memory)
 031        var mesesSet = mesesSemestre.ToHashSet();
 032        var registrosDb = await _context.HistoricoLiquidaciones
 033            .Where(h => personaIds.Contains(h.PersonaId)
 034                && aniosSemestre.Contains(h.Anio)
 035                && mesesIds.Contains(h.Mes))
 036            .Select(h => new { h.PersonaId, h.Anio, h.Mes })
 037            .ToListAsync();
 38
 039        var historicosPorPersona = registrosDb
 040            .Where(h => mesesSet.Contains((h.Anio, h.Mes)))
 041            .GroupBy(h => h.PersonaId)
 042            .ToDictionary(g => g.Key, g => g.Select(h => (h.Anio, h.Mes)).ToHashSet());
 43
 044        var resultado = new AguinaldoValidacionDto
 045        {
 046            TotalPersonasActivas = activos.Count
 047        };
 48
 049        foreach (var relacion in activos)
 50        {
 51            // Solo se exigen meses a partir del mes de ingreso del funcionario.
 52            // Un funcionario dado de alta en febrero no necesita diciembre ni enero.
 053            var inicioYearMonth = relacion.FechaInicio.Year * 12 + relacion.FechaInicio.Month;
 054            var mesesRequeridos = mesesSemestre
 055                .Where(m => m.Anio * 12 + m.Mes >= inicioYearMonth)
 056                .ToList();
 57
 058            var mesesConHistorico = historicosPorPersona.TryGetValue(relacion.PersonaId, out var h)
 059                ? h
 060                : new HashSet<(short, short)>();
 61
 062            var faltantes = mesesRequeridos
 063                .Where(m => !mesesConHistorico.Contains(m))
 064                .ToList();
 65
 066            if (faltantes.Any())
 67            {
 068                resultado.PersonasConHistoricoIncompleto++;
 069                resultado.Incidencias.Add(new AguinaldoIncidenciaDto
 070                {
 071                    Tipo = "HistoricoIncompleto",
 072                    Cedula = relacion.Persona.Cedula,
 073                    NombreCompleto = relacion.Persona.NombreCompleto,
 074                    MesesFaltantes = faltantes.Select(m => FormatearMesAnio(m.Anio, m.Mes)).ToList(),
 075                    Descripcion = "Faltan meses en el histórico de liquidaciones para el semestre seleccionado."
 076                });
 77            }
 78            else
 79            {
 080                resultado.PersonasListasParaCalcular++;
 81            }
 82        }
 83
 084        return resultado;
 085    }
 86
 87    private static IReadOnlyList<(short Anio, short Mes)> ObtenerMesesSemestre(CalcularAguinaldoSemestralRequest request
 88    {
 089        if (request.Mes == 6)
 90        {
 091            return new List<(short Anio, short Mes)>
 092            {
 093                ((short)(request.Anio - 1), (short)12),
 094                ((short)request.Anio, (short)1),
 095                ((short)request.Anio, (short)2),
 096                ((short)request.Anio, (short)3),
 097                ((short)request.Anio, (short)4),
 098                ((short)request.Anio, (short)5)
 099            };
 100        }
 101
 0102        if (request.Mes == 12)
 103        {
 0104            return new List<(short Anio, short Mes)>
 0105            {
 0106                ((short)request.Anio, (short)6),
 0107                ((short)request.Anio, (short)7),
 0108                ((short)request.Anio, (short)8),
 0109                ((short)request.Anio, (short)9),
 0110                ((short)request.Anio, (short)10),
 0111                ((short)request.Anio, (short)11)
 0112            };
 113        }
 114
 0115        throw new InvalidOperationException("El mes proporcionado no corresponde a un cierre de aguinaldo semestral.");
 116    }
 117
 0118    private static string FormatearMesAnio(short anio, short mes) => $"{mes:D2}/{anio:D4}";
 119}