< Summary

Information
Class: FAU.Logica.Services.AguinaldoPadronService
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Services/AguinaldoPadronService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 130
Coverable lines: 130
Total lines: 179
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 20
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%
GenerarPadronExcelAsync()0%4260%
GenerarExcel(...)0%4260%
EscribirFilaTotales(...)0%620%
EscribirSeccionSubtotales(...)0%620%
FormatNombre(...)0%2040%
.ctor(...)100%210%
get_Cedula()100%210%
get_NombreCompleto()100%210%
get_Grado()100%210%
get_Unidad()100%210%
get_Situacion()100%210%
get_Nominal()100%210%
get_Irpf()100%210%
get_Montepio()100%210%
get_Sanidad()100%210%
get_TotalDescuentos()100%210%
get_Liquido()100%210%

File(s)

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

#LineLine coverage
 1using ClosedXML.Excel;
 2using FAU.DataAccess;
 3using FAU.Entidades;
 4using Microsoft.EntityFrameworkCore;
 5
 6namespace FAU.Logica.Services;
 7
 8public class AguinaldoPadronService : IAguinaldoPadronService
 9{
 10    private readonly ApplicationDbContext _context;
 11
 012    public AguinaldoPadronService(ApplicationDbContext context)
 13    {
 014        _context = context;
 015    }
 16
 17    public async Task<(byte[] Bytes, string FileName)> GenerarPadronExcelAsync(int anio, int mes)
 18    {
 019        if (mes != 6 && mes != 12)
 020            throw new ArgumentException("El mes debe ser 6 o 12.", nameof(mes));
 21
 022        var semestre = (short)(mes == 6 ? 1 : 2);
 23
 024        var rawData = await (
 025            from a in _context.Aguinaldos
 026            where a.Anio == (short)anio && a.Semestre == semestre
 027            join rl in _context.RelacionesLaborales on a.PersonaId equals rl.PersonaId
 028            where rl.Estado == EstadoRelacion.Activo
 029            select new
 030            {
 031                rl.Persona.Cedula,
 032                rl.Persona.PrimerNombre,
 033                rl.Persona.SegundoNombre,
 034                rl.Persona.PrimerApellido,
 035                rl.Persona.SegundoApellido,
 036                Grado = rl.Grado.Denominacion,
 037                Unidad = rl.Unidad.Denominacion,
 038                Situacion = rl.Situacion.Denominacion,
 039                Nominal = a.Nominal ?? 0m,
 040                Irpf = a.IrpfAguinaldo,
 041                Montepio = a.Montepio ?? 0m,
 042                Sanidad = a.Sanidad ?? 0m,
 043                TotalDescuentos = a.TotalDescuentos ?? 0m,
 044                Liquido = a.Liquido ?? 0m,
 045            }).ToListAsync();
 46
 047        var filas = rawData
 048            .Select(d => new FilaPadron(
 049                d.Cedula,
 050                FormatNombre(d.PrimerNombre, d.SegundoNombre, d.PrimerApellido, d.SegundoApellido),
 051                d.Grado,
 052                d.Unidad,
 053                d.Situacion,
 054                d.Nominal,
 055                d.Irpf,
 056                d.Montepio,
 057                d.Sanidad,
 058                d.TotalDescuentos,
 059                d.Liquido))
 060            .OrderBy(f => f.NombreCompleto)
 061            .ToList();
 62
 063        var bytes = GenerarExcel(filas, anio, mes);
 064        return (bytes, $"padron_aguinaldo_{anio}_{mes:D2}.xlsx");
 065    }
 66
 67    private static byte[] GenerarExcel(List<FilaPadron> filas, int anio, int mes)
 68    {
 069        using var wb = new XLWorkbook();
 070        var ws = wb.Worksheets.Add("Padrón");
 71
 072        int row = 1;
 73
 074        var tituloSemestre = mes == 6 ? "1er Semestre (Junio)" : "2do Semestre (Diciembre)";
 075        ws.Cell(row, 1).Value = $"Padrón Aguinaldo Semestral - Año {anio} - {tituloSemestre}";
 076        ws.Range(row, 1, row, 11).Merge().Style.Font.Bold = true;
 077        ws.Range(row, 1, row, 11).Style.Font.FontSize = 14;
 078        row += 2;
 79
 080        string[] headers = ["Cédula", "Nombres y Apellidos", "Grado", "Unidad", "Situación", "Nominal", "IRPF", "Montepi
 081        for (int c = 0; c < headers.Length; c++)
 82        {
 083            var cell = ws.Cell(row, c + 1);
 084            cell.Value = headers[c];
 085            cell.Style.Font.Bold = true;
 086            cell.Style.Fill.BackgroundColor = XLColor.LightGray;
 087            cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
 88        }
 089        row++;
 90
 091        foreach (var f in filas)
 92        {
 093            ws.Cell(row, 1).Value = f.Cedula;
 094            ws.Cell(row, 2).Value = f.NombreCompleto;
 095            ws.Cell(row, 3).Value = f.Grado;
 096            ws.Cell(row, 4).Value = f.Unidad;
 097            ws.Cell(row, 5).Value = f.Situacion;
 098            ws.Cell(row, 6).Value = f.Nominal;
 099            ws.Cell(row, 7).Value = f.Irpf;
 0100            ws.Cell(row, 8).Value = f.Montepio;
 0101            ws.Cell(row, 9).Value = f.Sanidad;
 0102            ws.Cell(row, 10).Value = f.TotalDescuentos;
 0103            ws.Cell(row, 11).Value = f.Liquido;
 0104            row++;
 105        }
 0106        row++;
 107
 0108        EscribirFilaTotales(ws, ref row, $"TOTAL FUNCIONARIOS: {filas.Count}", filas);
 0109        row++;
 110
 0111        EscribirSeccionSubtotales(ws, ref row, "Totales por Situación", filas, f => f.Situacion);
 0112        row++;
 113
 0114        EscribirSeccionSubtotales(ws, ref row, "Totales por Unidad", filas, f => f.Unidad);
 0115        row++;
 116
 0117        EscribirSeccionSubtotales(ws, ref row, "Totales por Grado", filas, f => f.Grado);
 118
 0119        ws.Range(1, 6, row, 11).Style.NumberFormat.Format = "#,##0.00";
 0120        ws.Columns().AdjustToContents();
 121
 0122        using var ms = new MemoryStream();
 0123        wb.SaveAs(ms);
 0124        return ms.ToArray();
 0125    }
 126
 127    private static void EscribirFilaTotales(IXLWorksheet ws, ref int row, string etiqueta, IEnumerable<FilaPadron> filas
 128    {
 0129        var list = filas.ToList();
 0130        ws.Cell(row, 1).Value = etiqueta;
 0131        ws.Cell(row, 6).Value = list.Sum(f => f.Nominal);
 0132        ws.Cell(row, 7).Value = list.Sum(f => f.Irpf);
 0133        ws.Cell(row, 8).Value = list.Sum(f => f.Montepio);
 0134        ws.Cell(row, 9).Value = list.Sum(f => f.Sanidad);
 0135        ws.Cell(row, 10).Value = list.Sum(f => f.TotalDescuentos);
 0136        ws.Cell(row, 11).Value = list.Sum(f => f.Liquido);
 0137        for (int c = 1; c <= 11; c++)
 0138            ws.Cell(row, c).Style.Font.Bold = true;
 0139        row++;
 0140    }
 141
 142    private static void EscribirSeccionSubtotales(IXLWorksheet ws, ref int row, string titulo, List<FilaPadron> filas, F
 143    {
 0144        ws.Cell(row, 1).Value = titulo;
 0145        ws.Cell(row, 1).Style.Font.Bold = true;
 0146        ws.Cell(row, 1).Style.Font.Italic = true;
 0147        row++;
 148
 0149        foreach (var grupo in filas.GroupBy(getKey).OrderBy(g => g.Key))
 150        {
 0151            var list = grupo.ToList();
 0152            ws.Cell(row, 1).Value = grupo.Key;
 0153            ws.Cell(row, 2).Value = list.Count;
 0154            ws.Cell(row, 6).Value = list.Sum(f => f.Nominal);
 0155            ws.Cell(row, 7).Value = list.Sum(f => f.Irpf);
 0156            ws.Cell(row, 8).Value = list.Sum(f => f.Montepio);
 0157            ws.Cell(row, 9).Value = list.Sum(f => f.Sanidad);
 0158            ws.Cell(row, 10).Value = list.Sum(f => f.TotalDescuentos);
 0159            ws.Cell(row, 11).Value = list.Sum(f => f.Liquido);
 0160            row++;
 161        }
 0162    }
 163
 164    private static string FormatNombre(string primerNombre, string? segundoNombre, string primerApellido, string? segund
 0165        => $"{primerNombre}{(string.IsNullOrWhiteSpace(segundoNombre) ? "" : " " + segundoNombre)} {primerApellido}{(str
 166
 0167    private record FilaPadron(
 0168        string Cedula,
 0169        string NombreCompleto,
 0170        string Grado,
 0171        string Unidad,
 0172        string Situacion,
 0173        decimal Nominal,
 0174        decimal Irpf,
 0175        decimal Montepio,
 0176        decimal Sanidad,
 0177        decimal TotalDescuentos,
 0178        decimal Liquido);
 179}