| | | 1 | | using System.Globalization; |
| | | 2 | | using System.Text; |
| | | 3 | | using FAU.DataAccess; |
| | | 4 | | using FAU.Entidades; |
| | | 5 | | using FAU.Logica.DTOs; |
| | | 6 | | using Microsoft.EntityFrameworkCore; |
| | | 7 | | |
| | | 8 | | namespace FAU.Logica.Services; |
| | | 9 | | |
| | | 10 | | public class ReporteMDNService : IReporteMDNService |
| | | 11 | | { |
| | | 12 | | private readonly ApplicationDbContext _context; |
| | | 13 | | |
| | 0 | 14 | | public ReporteMDNService(ApplicationDbContext context) |
| | | 15 | | { |
| | 0 | 16 | | _context = context; |
| | 0 | 17 | | } |
| | | 18 | | |
| | | 19 | | // ─── Helpers ───────────────────────────────────────────────────────────── |
| | | 20 | | |
| | | 21 | | private async Task<int> ObtenerVersionMaximaAsync(long periodoId) |
| | | 22 | | { |
| | 0 | 23 | | return await _context.LiquidacionItems |
| | 0 | 24 | | .AsNoTracking() |
| | 0 | 25 | | .Where(i => i.PeriodoId == periodoId) |
| | 0 | 26 | | .MaxAsync(i => (int?)i.Version) ?? 0; |
| | 0 | 27 | | } |
| | | 28 | | |
| | | 29 | | private async Task<Dictionary<string, (string Tipo, bool EsGravado)>> CargarCatalogoAsync() |
| | | 30 | | { |
| | 0 | 31 | | return await _context.CatalogoItems |
| | 0 | 32 | | .AsNoTracking() |
| | 0 | 33 | | .ToDictionaryAsync(ci => ci.Codigo.ToString(), ci => (ci.Tipo, ci.EsGravado)); |
| | 0 | 34 | | } |
| | | 35 | | |
| | 0 | 36 | | private static string ClasificarMdn((string Tipo, bool EsGravado) entry) => entry.Tipo switch |
| | 0 | 37 | | { |
| | 0 | 38 | | "haber_normal" => entry.EsGravado ? "HabNorGrab" : "HabsNoGrab", |
| | 0 | 39 | | "haber_no_gravado" => "HabsNoGrab", |
| | 0 | 40 | | "beneficio_social_grav" => "BenSocGrab", |
| | 0 | 41 | | "beneficio_social_no_grav" => "BenSocNoGr", |
| | 0 | 42 | | "descuento_legal" => entry.EsGravado ? "DtoLegGrab" : "DtoLegNoGr", |
| | 0 | 43 | | "descuento_personal" => "DtoPerGrab", |
| | 0 | 44 | | "ficto_descuento" => "DtoPerGrab", |
| | 0 | 45 | | _ => "" |
| | 0 | 46 | | }; |
| | | 47 | | |
| | 0 | 48 | | private static string F(decimal value) => value.ToString("F2", CultureInfo.InvariantCulture); |
| | | 49 | | |
| | | 50 | | // ─── RPT-MDN-1: Padrón del Personal ─────────────────────────────────────── |
| | | 51 | | |
| | | 52 | | public async Task<List<PadronPersonalMdnDto>> ObtenerPadronPersonalAsync(long periodoId, long? regimenId = null) |
| | | 53 | | { |
| | 0 | 54 | | var version = await ObtenerVersionMaximaAsync(periodoId); |
| | | 55 | | |
| | 0 | 56 | | var cedulasConLiquidacion = await _context.LiquidacionItems |
| | 0 | 57 | | .AsNoTracking() |
| | 0 | 58 | | .Where(i => i.PeriodoId == periodoId && i.Version == version) |
| | 0 | 59 | | .Select(i => i.Cedula) |
| | 0 | 60 | | .Distinct() |
| | 0 | 61 | | .ToListAsync(); |
| | | 62 | | |
| | 0 | 63 | | var query = _context.RelacionesLaborales |
| | 0 | 64 | | .AsNoTracking() |
| | 0 | 65 | | .Where(r => cedulasConLiquidacion.Contains(r.Persona.Cedula)) |
| | 0 | 66 | | .Where(r => r.Estado == EstadoRelacion.Activo) |
| | 0 | 67 | | .Select(r => new |
| | 0 | 68 | | { |
| | 0 | 69 | | r.Persona.Cedula, |
| | 0 | 70 | | r.Persona.PrimerApellido, |
| | 0 | 71 | | r.Persona.SegundoApellido, |
| | 0 | 72 | | r.Persona.PrimerNombre, |
| | 0 | 73 | | r.Persona.SegundoNombre, |
| | 0 | 74 | | Situacion = r.Situacion.Denominacion, |
| | 0 | 75 | | Grado = r.Grado.Denominacion, |
| | 0 | 76 | | Escalafon = r.Escalafon.Denominacion, |
| | 0 | 77 | | Regimen = r.Regimen.Denominacion, |
| | 0 | 78 | | r.AniosServicioAnterior, |
| | 0 | 79 | | r.FechaInicio, |
| | 0 | 80 | | r.FechaFin, |
| | 0 | 81 | | r.FechaAscensoOficial, |
| | 0 | 82 | | r.FechaUltimoAscenso |
| | 0 | 83 | | }); |
| | | 84 | | |
| | 0 | 85 | | if (regimenId.HasValue) |
| | 0 | 86 | | query = query.Where(r => r.Regimen == _context.Regimenes.AsNoTracking().First(rg => rg.Id == regimenId.Value |
| | | 87 | | |
| | 0 | 88 | | var raw = await query |
| | 0 | 89 | | .OrderBy(r => r.PrimerApellido) |
| | 0 | 90 | | .ThenBy(r => r.SegundoApellido) |
| | 0 | 91 | | .ThenBy(r => r.PrimerNombre) |
| | 0 | 92 | | .ToListAsync(); |
| | | 93 | | |
| | 0 | 94 | | return raw.Select(r => new PadronPersonalMdnDto |
| | 0 | 95 | | { |
| | 0 | 96 | | Cedula = r.Cedula, |
| | 0 | 97 | | Apellidos = $"{r.PrimerApellido} {r.SegundoApellido}".Trim(), |
| | 0 | 98 | | Nombres = $"{r.PrimerNombre} {r.SegundoNombre}".Trim(), |
| | 0 | 99 | | Situacion = r.Situacion, |
| | 0 | 100 | | Grado = r.Grado, |
| | 0 | 101 | | Escalafon = r.Escalafon, |
| | 0 | 102 | | Regimen = r.Regimen, |
| | 0 | 103 | | AniosTropa = r.AniosServicioAnterior, |
| | 0 | 104 | | FechaIngreso = r.FechaInicio, |
| | 0 | 105 | | FechaRetiro = r.FechaFin, |
| | 0 | 106 | | FechaOficialidad = r.FechaAscensoOficial, |
| | 0 | 107 | | FechaUltimoAscenso = r.FechaUltimoAscenso |
| | 0 | 108 | | }).ToList(); |
| | 0 | 109 | | } |
| | | 110 | | |
| | | 111 | | public async Task<byte[]> GenerarCsvPadronPersonalAsync(long periodoId, long? regimenId = null) |
| | | 112 | | { |
| | 0 | 113 | | var data = await ObtenerPadronPersonalAsync(periodoId, regimenId); |
| | 0 | 114 | | var sb = new StringBuilder(); |
| | 0 | 115 | | sb.AppendLine("Cédula;Apellidos;Nombres;Situación;Grado;Escalafón;Régimen;Años Tropa;Fecha Ingreso;Fecha Retiro; |
| | | 116 | | |
| | 0 | 117 | | foreach (var f in data) |
| | | 118 | | { |
| | 0 | 119 | | sb.AppendLine( |
| | 0 | 120 | | $"{f.Cedula};{f.Apellidos};{f.Nombres};{f.Situacion};{f.Grado};{f.Escalafon};{f.Regimen};" + |
| | 0 | 121 | | $"{f.AniosTropa?.ToString() ?? ""};" + |
| | 0 | 122 | | $"{f.FechaIngreso:dd/MM/yyyy};{f.FechaRetiro:dd/MM/yyyy};{f.FechaOficialidad:dd/MM/yyyy};{f.FechaUltimoA |
| | | 123 | | } |
| | | 124 | | |
| | 0 | 125 | | return Encoding.UTF8.GetBytes(sb.ToString()); |
| | 0 | 126 | | } |
| | | 127 | | |
| | | 128 | | // ─── RPT-MDN-2: Liquidación por Rubros ──────────────────────────────────── |
| | | 129 | | |
| | | 130 | | public async Task<LiquidacionRubrosMdnDto> ObtenerLiquidacionPorRubrosAsync(long periodoId, long? regimenId = null) |
| | | 131 | | { |
| | 0 | 132 | | var version = await ObtenerVersionMaximaAsync(periodoId); |
| | | 133 | | |
| | 0 | 134 | | var itemsQuery = _context.LiquidacionItems |
| | 0 | 135 | | .AsNoTracking() |
| | 0 | 136 | | .Where(i => i.PeriodoId == periodoId && i.Version == version); |
| | | 137 | | |
| | 0 | 138 | | var items = await itemsQuery |
| | 0 | 139 | | .Select(i => new |
| | 0 | 140 | | { |
| | 0 | 141 | | i.Cedula, |
| | 0 | 142 | | i.CodigoConcepto, |
| | 0 | 143 | | i.NombreConcepto, |
| | 0 | 144 | | i.Importe, |
| | 0 | 145 | | i.RubroContable, |
| | 0 | 146 | | i.ObjetoGasto, |
| | 0 | 147 | | i.RegimenId, |
| | 0 | 148 | | i.ProgramaId |
| | 0 | 149 | | }) |
| | 0 | 150 | | .ToListAsync(); |
| | | 151 | | |
| | 0 | 152 | | var catalogoDict = await CargarCatalogoAsync(); |
| | 0 | 153 | | items = items.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) != "DtoPerGrab").ToList |
| | | 154 | | |
| | 0 | 155 | | var cedulas = items.Select(i => i.Cedula).Distinct().ToList(); |
| | | 156 | | |
| | 0 | 157 | | var personasDict = await _context.RelacionesLaborales |
| | 0 | 158 | | .AsNoTracking() |
| | 0 | 159 | | .Where(r => cedulas.Contains(r.Persona.Cedula)) |
| | 0 | 160 | | .Select(r => new |
| | 0 | 161 | | { |
| | 0 | 162 | | r.Persona.Cedula, |
| | 0 | 163 | | Nombre = $"{r.Persona.PrimerApellido} {r.Persona.SegundoApellido}, {r.Persona.PrimerNombre}", |
| | 0 | 164 | | Grado = r.Grado.Denominacion, |
| | 0 | 165 | | Regimen = r.Regimen.Denominacion, |
| | 0 | 166 | | Programa = r.Programa.Denominacion |
| | 0 | 167 | | }) |
| | 0 | 168 | | .ToDictionaryAsync(x => x.Cedula); |
| | | 169 | | |
| | 0 | 170 | | var objetosGasto = items |
| | 0 | 171 | | .Where(i => !string.IsNullOrEmpty(i.ObjetoGasto)) |
| | 0 | 172 | | .Select(i => i.ObjetoGasto!) |
| | 0 | 173 | | .Distinct() |
| | 0 | 174 | | .OrderBy(o => o) |
| | 0 | 175 | | .ToList(); |
| | | 176 | | |
| | 0 | 177 | | var filas = items |
| | 0 | 178 | | .GroupBy(i => i.Cedula) |
| | 0 | 179 | | .Select(g => |
| | 0 | 180 | | { |
| | 0 | 181 | | var persona = personasDict.GetValueOrDefault(g.Key); |
| | 0 | 182 | | var montosPorOG = g |
| | 0 | 183 | | .Where(i => !string.IsNullOrEmpty(i.ObjetoGasto)) |
| | 0 | 184 | | .GroupBy(i => i.ObjetoGasto!) |
| | 0 | 185 | | .ToDictionary(og => og.Key, og => og.Sum(i => i.Importe)); |
| | 0 | 186 | | |
| | 0 | 187 | | var haberes = g.Where(i => i.Importe > 0).Sum(i => i.Importe); |
| | 0 | 188 | | var descuentos = g.Where(i => i.Importe < 0).Sum(i => i.Importe); |
| | 0 | 189 | | |
| | 0 | 190 | | return new LiquidacionRubrosMdnFilaDto |
| | 0 | 191 | | { |
| | 0 | 192 | | Cedula = g.Key, |
| | 0 | 193 | | Nombre = persona?.Nombre ?? g.Key, |
| | 0 | 194 | | Grado = persona?.Grado ?? "", |
| | 0 | 195 | | Regimen = persona?.Regimen ?? "", |
| | 0 | 196 | | Programa = persona?.Programa ?? "", |
| | 0 | 197 | | MontosPorObjetoGasto = montosPorOG, |
| | 0 | 198 | | TotalHaberes = haberes, |
| | 0 | 199 | | TotalDescuentosLegales = Math.Abs(descuentos), |
| | 0 | 200 | | LiquidoMDN = haberes + descuentos |
| | 0 | 201 | | }; |
| | 0 | 202 | | }) |
| | 0 | 203 | | .ToList(); |
| | | 204 | | |
| | 0 | 205 | | return new LiquidacionRubrosMdnDto |
| | 0 | 206 | | { |
| | 0 | 207 | | ObjetosGasto = objetosGasto, |
| | 0 | 208 | | Filas = filas, |
| | 0 | 209 | | TotalHaberes = filas.Sum(f => f.TotalHaberes), |
| | 0 | 210 | | TotalDescuentosLegales = filas.Sum(f => f.TotalDescuentosLegales), |
| | 0 | 211 | | LiquidoMDN = filas.Sum(f => f.LiquidoMDN) |
| | 0 | 212 | | }; |
| | 0 | 213 | | } |
| | | 214 | | |
| | | 215 | | public async Task<byte[]> GenerarCsvLiquidacionPorRubrosAsync(long periodoId, long? regimenId = null) |
| | | 216 | | { |
| | 0 | 217 | | var dto = await ObtenerLiquidacionPorRubrosAsync(periodoId, regimenId); |
| | 0 | 218 | | var sb = new StringBuilder(); |
| | | 219 | | |
| | 0 | 220 | | var headers = "Cédula;Nombre;Grado;Régimen;Programa;" + |
| | 0 | 221 | | string.Join(";", dto.ObjetosGasto) + |
| | 0 | 222 | | ";Total Haberes;Total Descuentos Legales;Líquido MDN"; |
| | 0 | 223 | | sb.AppendLine(headers); |
| | | 224 | | |
| | 0 | 225 | | foreach (var f in dto.Filas) |
| | | 226 | | { |
| | 0 | 227 | | var ogValues = string.Join(";", |
| | 0 | 228 | | dto.ObjetosGasto.Select(og => f.MontosPorObjetoGasto.TryGetValue(og, out var m) ? F(m) : "0.00")); |
| | | 229 | | |
| | 0 | 230 | | sb.AppendLine( |
| | 0 | 231 | | $"{f.Cedula};{f.Nombre};{f.Grado};{f.Regimen};{f.Programa};" + |
| | 0 | 232 | | $"{ogValues};{F(f.TotalHaberes)};{F(f.TotalDescuentosLegales)};{F(f.LiquidoMDN)}"); |
| | | 233 | | } |
| | | 234 | | |
| | 0 | 235 | | sb.AppendLine( |
| | 0 | 236 | | $"TOTAL;;;;;" + |
| | 0 | 237 | | $"{string.Join(";", dto.ObjetosGasto.Select(_ => ""))};" + |
| | 0 | 238 | | $"{F(dto.TotalHaberes)};{F(dto.TotalDescuentosLegales)};{F(dto.LiquidoMDN)}"); |
| | | 239 | | |
| | 0 | 240 | | return Encoding.UTF8.GetBytes(sb.ToString()); |
| | 0 | 241 | | } |
| | | 242 | | |
| | | 243 | | // ─── RPT-MDN-3: Control Porcentual ──────────────────────────────────────── |
| | | 244 | | |
| | | 245 | | public async Task<ControlPorcentualMdnDto> ObtenerControlPorcentualAsync(long periodoId, long? regimenId = null) |
| | | 246 | | { |
| | 0 | 247 | | var version = await ObtenerVersionMaximaAsync(periodoId); |
| | | 248 | | |
| | 0 | 249 | | var itemsQuery = _context.LiquidacionItems |
| | 0 | 250 | | .AsNoTracking() |
| | 0 | 251 | | .Where(i => i.PeriodoId == periodoId && i.Version == version); |
| | | 252 | | |
| | 0 | 253 | | var items = await itemsQuery.ToListAsync(); |
| | 0 | 254 | | var catalogoDict = await CargarCatalogoAsync(); |
| | | 255 | | items = items.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) != "DtoPerGrab").ToList |
| | | 256 | | |
| | 0 | 257 | | var cedulas = items.Select(i => i.Cedula).Distinct().ToList(); |
| | | 258 | | |
| | 0 | 259 | | var personasDict = await _context.RelacionesLaborales |
| | 0 | 260 | | .AsNoTracking() |
| | 0 | 261 | | .Where(r => cedulas.Contains(r.Persona.Cedula)) |
| | 0 | 262 | | .Select(r => new |
| | 0 | 263 | | { |
| | 0 | 264 | | r.Persona.Cedula, |
| | 0 | 265 | | Nombre = $"{r.Persona.PrimerApellido} {r.Persona.SegundoApellido}, {r.Persona.PrimerNombre}", |
| | 0 | 266 | | Grado = r.Grado.Denominacion, |
| | 0 | 267 | | Unidad = r.Unidad.Denominacion |
| | 0 | 268 | | }) |
| | 0 | 269 | | .ToDictionaryAsync(x => x.Cedula); |
| | | 270 | | |
| | 0 | 271 | | var filas = new List<ControlPorcentualMdnFilaDto>(); |
| | | 272 | | |
| | 0 | 273 | | foreach (var g in items.GroupBy(i => i.Cedula)) |
| | | 274 | | { |
| | 0 | 275 | | var persona = personasDict.GetValueOrDefault(g.Key); |
| | 0 | 276 | | var haberesGrav = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) is "HabNorGra |
| | 0 | 277 | | var haberesNoGrav = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) is "HabsNoG |
| | 0 | 278 | | var beneficios = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) is "BenSocGrab |
| | 0 | 279 | | var descuentos = g.Where(i => i.Importe < 0).Sum(i => i.Importe); |
| | 0 | 280 | | var liquido = g.Sum(i => i.Importe); |
| | | 281 | | // Legacy: liquido_30 = (((tot_hab + tot_habng) - tot_desl) * 30 / 100) + tot_ben |
| | 0 | 282 | | var ingresosNetos = haberesGrav + haberesNoGrav + descuentos; // descuentos es negativo |
| | 0 | 283 | | var calculo30 = ingresosNetos * 0.30m + beneficios; |
| | 0 | 284 | | var porcentajeReal = calculo30 > 0 ? (liquido * 30m) / calculo30 : 0m; |
| | | 285 | | |
| | 0 | 286 | | filas.Add(new ControlPorcentualMdnFilaDto |
| | 0 | 287 | | { |
| | 0 | 288 | | Cedula = g.Key, |
| | 0 | 289 | | Nombre = persona?.Nombre ?? g.Key, |
| | 0 | 290 | | Grado = persona?.Grado ?? "", |
| | 0 | 291 | | Unidad = persona?.Unidad ?? "", |
| | 0 | 292 | | HaberesGravados = haberesGrav, |
| | 0 | 293 | | HaberesNoGravados = haberesNoGrav, |
| | 0 | 294 | | BeneficiosSociales = beneficios, |
| | 0 | 295 | | DescuentosLegales = Math.Abs(descuentos), |
| | 0 | 296 | | LiquidoMDN = liquido, |
| | 0 | 297 | | Calculo30Porciento = calculo30, |
| | 0 | 298 | | PorcentajeReal = porcentajeReal |
| | 0 | 299 | | }); |
| | | 300 | | } |
| | | 301 | | |
| | 0 | 302 | | var resumen = new ControlPorcentualMdnResumenDto(); |
| | | 303 | | |
| | 0 | 304 | | foreach (var f in filas) |
| | | 305 | | { |
| | 0 | 306 | | var porc = f.PorcentajeReal; |
| | 0 | 307 | | if (porc > 50m) |
| | | 308 | | { |
| | 0 | 309 | | resumen.CantidadSuperior50++; |
| | 0 | 310 | | resumen.ImporteSuperior50 += f.LiquidoMDN; |
| | | 311 | | } |
| | 0 | 312 | | else if (porc >= 40m) |
| | | 313 | | { |
| | 0 | 314 | | resumen.CantidadEntre40Y50++; |
| | 0 | 315 | | resumen.ImporteEntre40Y50 += f.LiquidoMDN; |
| | | 316 | | } |
| | 0 | 317 | | else if (porc >= 30m) |
| | | 318 | | { |
| | 0 | 319 | | resumen.CantidadEntre30Y40++; |
| | 0 | 320 | | resumen.ImporteEntre30Y40 += f.LiquidoMDN; |
| | | 321 | | } |
| | | 322 | | else |
| | | 323 | | { |
| | 0 | 324 | | resumen.CantidadInferior30++; |
| | 0 | 325 | | resumen.ImporteInferior30 += f.LiquidoMDN; |
| | 0 | 326 | | resumen.TotalDeudasNoAtendidas += (f.Calculo30Porciento - f.LiquidoMDN); |
| | | 327 | | } |
| | | 328 | | } |
| | | 329 | | |
| | 0 | 330 | | return new ControlPorcentualMdnDto { Filas = filas, Resumen = resumen }; |
| | 0 | 331 | | } |
| | | 332 | | |
| | | 333 | | public async Task<byte[]> GenerarCsvControlPorcentualAsync(long periodoId, long? regimenId = null) |
| | | 334 | | { |
| | 0 | 335 | | var dto = await ObtenerControlPorcentualAsync(periodoId, regimenId); |
| | 0 | 336 | | var sb = new StringBuilder(); |
| | | 337 | | |
| | 0 | 338 | | sb.AppendLine("Cédula;Nombre;Grado;Unidad;Haberes Gravados;Haberes No Gravados;Beneficios Sociales;Descuentos Le |
| | 0 | 339 | | foreach (var f in dto.Filas) |
| | 0 | 340 | | sb.AppendLine($"{f.Cedula};{f.Nombre};{f.Grado};{f.Unidad};{F(f.HaberesGravados)};{F(f.HaberesNoGravados)};{ |
| | | 341 | | |
| | 0 | 342 | | sb.AppendLine(); |
| | 0 | 343 | | sb.AppendLine("RANGO;CANTIDAD;IMPORTE NOMINAL"); |
| | 0 | 344 | | sb.AppendLine($"> 50%;{dto.Resumen.CantidadSuperior50};{F(dto.Resumen.ImporteSuperior50)}"); |
| | 0 | 345 | | sb.AppendLine($"40% - 50%;{dto.Resumen.CantidadEntre40Y50};{F(dto.Resumen.ImporteEntre40Y50)}"); |
| | 0 | 346 | | sb.AppendLine($"30% - 40%;{dto.Resumen.CantidadEntre30Y40};{F(dto.Resumen.ImporteEntre30Y40)}"); |
| | 0 | 347 | | sb.AppendLine($"< 30% (insuficiente);{dto.Resumen.CantidadInferior30};{F(dto.Resumen.ImporteInferior30)}"); |
| | 0 | 348 | | sb.AppendLine($"Total deudas no atendidas;;;{F(dto.Resumen.TotalDeudasNoAtendidas)}"); |
| | | 349 | | |
| | 0 | 350 | | return Encoding.UTF8.GetBytes(sb.ToString()); |
| | 0 | 351 | | } |
| | | 352 | | |
| | | 353 | | // ─── RPT-MDN-4: Haberes Gravables / No Gravables ────────────────────────── |
| | | 354 | | |
| | | 355 | | public async Task<List<HaberesGravablesMdnFilaDto>> ObtenerHaberesGravablesAsync(long periodoId, long? regimenId = n |
| | | 356 | | { |
| | 0 | 357 | | var version = await ObtenerVersionMaximaAsync(periodoId); |
| | | 358 | | |
| | 0 | 359 | | var itemsQuery = _context.LiquidacionItems |
| | 0 | 360 | | .AsNoTracking() |
| | 0 | 361 | | .Where(i => i.PeriodoId == periodoId && i.Version == version); |
| | | 362 | | |
| | 0 | 363 | | var items = await itemsQuery.ToListAsync(); |
| | 0 | 364 | | var catalogoDict = await CargarCatalogoAsync(); |
| | | 365 | | items = items.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) != "DtoPerGrab").ToList |
| | | 366 | | |
| | 0 | 367 | | var cedulas = items.Select(i => i.Cedula).Distinct().ToList(); |
| | | 368 | | |
| | 0 | 369 | | var personasDict = await _context.RelacionesLaborales |
| | 0 | 370 | | .AsNoTracking() |
| | 0 | 371 | | .Where(r => cedulas.Contains(r.Persona.Cedula)) |
| | 0 | 372 | | .Select(r => new |
| | 0 | 373 | | { |
| | 0 | 374 | | r.Persona.Cedula, |
| | 0 | 375 | | Nombre = $"{r.Persona.PrimerApellido} {r.Persona.SegundoApellido}, {r.Persona.PrimerNombre}", |
| | 0 | 376 | | r.FechaInicio, |
| | 0 | 377 | | Situacion = r.Situacion.Denominacion, |
| | 0 | 378 | | Grado = r.Grado.Denominacion, |
| | 0 | 379 | | Escalafon = r.Escalafon.Denominacion |
| | 0 | 380 | | }) |
| | 0 | 381 | | .ToDictionaryAsync(x => x.Cedula); |
| | | 382 | | |
| | 0 | 383 | | return items |
| | 0 | 384 | | .GroupBy(i => i.Cedula) |
| | 0 | 385 | | .Select(g => |
| | 0 | 386 | | { |
| | | 387 | | var p = personasDict.GetValueOrDefault(g.Key); |
| | | 388 | | return new HaberesGravablesMdnFilaDto |
| | | 389 | | { |
| | | 390 | | Cedula = g.Key, |
| | | 391 | | Nombre = p?.Nombre ?? g.Key, |
| | | 392 | | FechaIngreso = p?.FechaInicio, |
| | | 393 | | Situacion = p?.Situacion ?? "", |
| | | 394 | | Grado = p?.Grado ?? "", |
| | | 395 | | Escalafon = p?.Escalafon ?? "", |
| | 0 | 396 | | HaberesGravados = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) is "H |
| | 0 | 397 | | HaberesNoGravados = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) is |
| | 0 | 398 | | BeneficiosGravados = g.Where(i => ClasificarMdn(catalogoDict.GetValueOrDefault(i.CodigoConcepto)) == |
| | | 399 | | }; |
| | 0 | 400 | | }) |
| | 0 | 401 | | .OrderBy(f => f.Nombre) |
| | 0 | 402 | | .ToList(); |
| | 0 | 403 | | } |
| | | 404 | | |
| | | 405 | | public async Task<byte[]> GenerarCsvHaberesGravablesAsync(long periodoId, long? regimenId = null) |
| | | 406 | | { |
| | 0 | 407 | | var data = await ObtenerHaberesGravablesAsync(periodoId, regimenId); |
| | 0 | 408 | | var sb = new StringBuilder(); |
| | 0 | 409 | | sb.AppendLine("Cédula;Nombre;Fecha Ingreso;Situación;Grado;Escalafón;Haberes Gravados;Haberes No Gravados;Benefi |
| | | 410 | | |
| | 0 | 411 | | foreach (var f in data) |
| | 0 | 412 | | sb.AppendLine($"{f.Cedula};{f.Nombre};{f.FechaIngreso:dd/MM/yyyy};{f.Situacion};{f.Grado};{f.Escalafon};{F(f |
| | | 413 | | |
| | 0 | 414 | | return Encoding.UTF8.GetBytes(sb.ToString()); |
| | 0 | 415 | | } |
| | | 416 | | } |