| | | 1 | | using FAU.DataAccess; |
| | | 2 | | using FAU.Entidades; |
| | | 3 | | using FAU.Logica.DTOs; |
| | | 4 | | using Microsoft.EntityFrameworkCore; |
| | | 5 | | |
| | | 6 | | namespace FAU.Logica.Services; |
| | | 7 | | |
| | | 8 | | public class LiquidacionService : ILiquidacionService |
| | | 9 | | { |
| | | 10 | | private readonly ApplicationDbContext _context; |
| | | 11 | | private readonly IAuditoriaService _auditoriaService; |
| | | 12 | | private readonly ICurrentUserContext _currentUser; |
| | | 13 | | |
| | 0 | 14 | | public LiquidacionService( |
| | 0 | 15 | | ApplicationDbContext context, |
| | 0 | 16 | | IAuditoriaService auditoriaService, |
| | 0 | 17 | | ICurrentUserContext currentUser) |
| | | 18 | | { |
| | 0 | 19 | | _context = context; |
| | 0 | 20 | | _auditoriaService = auditoriaService; |
| | 0 | 21 | | _currentUser = currentUser; |
| | 0 | 22 | | } |
| | | 23 | | |
| | | 24 | | public async Task<(bool Exito, string? Error)> GenerarLiquidacionAsync(long periodoId, int version) |
| | | 25 | | { |
| | 0 | 26 | | var periodo = await _context.PeriodosLiquidacion |
| | 0 | 27 | | .AsNoTracking() |
| | 0 | 28 | | .FirstOrDefaultAsync(p => p.Id == periodoId && p.Activo); |
| | | 29 | | |
| | 0 | 30 | | if (periodo is null) |
| | | 31 | | { |
| | 0 | 32 | | return (false, "Período de liquidación no encontrado o no está activo"); |
| | | 33 | | } |
| | | 34 | | |
| | 0 | 35 | | if (version <= 0) |
| | | 36 | | { |
| | 0 | 37 | | return (false, "La versión debe ser mayor a cero"); |
| | | 38 | | } |
| | | 39 | | |
| | 0 | 40 | | var relacionesActivas = await _context.RelacionesLaborales |
| | 0 | 41 | | .AsNoTracking() |
| | 0 | 42 | | .Where(r => r.Estado == EstadoRelacion.Activo) |
| | 0 | 43 | | .Join( |
| | 0 | 44 | | _context.Personas.AsNoTracking(), |
| | 0 | 45 | | r => r.PersonaId, |
| | 0 | 46 | | p => p.Id, |
| | 0 | 47 | | (r, p) => new { p.Cedula } |
| | 0 | 48 | | ) |
| | 0 | 49 | | .Distinct() |
| | 0 | 50 | | .ToListAsync(); |
| | | 51 | | |
| | 0 | 52 | | if (!relacionesActivas.Any()) |
| | | 53 | | { |
| | 0 | 54 | | return (false, "No se encontraron relaciones laborales activas para generar la liquidación"); |
| | | 55 | | } |
| | | 56 | | |
| | 0 | 57 | | var existItems = await _context.LiquidacionItems |
| | 0 | 58 | | .AnyAsync(li => li.PeriodoId == periodoId && li.Version == version); |
| | | 59 | | |
| | 0 | 60 | | if (existItems) |
| | | 61 | | { |
| | 0 | 62 | | return (false, "Ya existe una liquidación generada para ese período y versión"); |
| | | 63 | | } |
| | | 64 | | |
| | 0 | 65 | | var estados = relacionesActivas.Select(r => new LiquidacionEstadoPersonal |
| | 0 | 66 | | { |
| | 0 | 67 | | PeriodoId = periodoId, |
| | 0 | 68 | | Cedula = r.Cedula, |
| | 0 | 69 | | Version = version, |
| | 0 | 70 | | Estado = "PENDIENTE", |
| | 0 | 71 | | FechaActualizacion = DateTime.UtcNow |
| | 0 | 72 | | }).ToList(); |
| | | 73 | | |
| | 0 | 74 | | await _context.LiquidacionEstadosPersonal.AddRangeAsync(estados); |
| | | 75 | | |
| | 0 | 76 | | var resumen = new LiquidacionResumen |
| | 0 | 77 | | { |
| | 0 | 78 | | PeriodoId = periodoId, |
| | 0 | 79 | | Version = version, |
| | 0 | 80 | | TotalImporte = 0m, |
| | 0 | 81 | | Rubro083 = false, |
| | 0 | 82 | | Descripcion = "Resumen inicial de liquidación" |
| | 0 | 83 | | }; |
| | | 84 | | |
| | 0 | 85 | | await _context.LiquidacionResumenes.AddAsync(resumen); |
| | 0 | 86 | | await _context.SaveChangesAsync(); |
| | | 87 | | |
| | 0 | 88 | | await _auditoriaService.LogAuditoriaAsync( |
| | 0 | 89 | | _currentUser.UserId ?? 0, |
| | 0 | 90 | | AccionEnum.GenerarLiquidacion, |
| | 0 | 91 | | ContextoEnum.Liquidaciones, |
| | 0 | 92 | | _currentUser.Host, |
| | 0 | 93 | | entidad: nameof(LiquidacionEstadoPersonal), |
| | 0 | 94 | | entidadId: periodoId, |
| | 0 | 95 | | detalle: new { periodoId, version, registros = estados.Count }); |
| | | 96 | | |
| | 0 | 97 | | return (true, null); |
| | 0 | 98 | | } |
| | | 99 | | |
| | | 100 | | public async Task<IEnumerable<CalculoEstadoDto>> ObtenerEstadosAsync(long periodoId, int version) |
| | | 101 | | { |
| | 0 | 102 | | return await _context.LiquidacionEstadosPersonal |
| | 0 | 103 | | .AsNoTracking() |
| | 0 | 104 | | .Where(e => e.PeriodoId == periodoId && e.Version == version) |
| | 0 | 105 | | .Select(e => new CalculoEstadoDto |
| | 0 | 106 | | { |
| | 0 | 107 | | Cedula = e.Cedula, |
| | 0 | 108 | | Version = e.Version, |
| | 0 | 109 | | Estado = e.Estado, |
| | 0 | 110 | | MensajeError = e.MensajeError |
| | 0 | 111 | | }) |
| | 0 | 112 | | .ToListAsync(); |
| | 0 | 113 | | } |
| | | 114 | | |
| | | 115 | | public async Task<IEnumerable<CalculoItemDto>> ObtenerItemsAsync(long periodoId, int version) |
| | | 116 | | { |
| | 0 | 117 | | return await _context.LiquidacionItems |
| | 0 | 118 | | .AsNoTracking() |
| | 0 | 119 | | .Where(i => i.PeriodoId == periodoId && i.Version == version) |
| | 0 | 120 | | .Select(i => new CalculoItemDto |
| | 0 | 121 | | { |
| | 0 | 122 | | Cedula = i.Cedula, |
| | 0 | 123 | | Version = i.Version, |
| | 0 | 124 | | CodigoConcepto = i.CodigoConcepto, |
| | 0 | 125 | | NombreConcepto = i.NombreConcepto, |
| | 0 | 126 | | Importe = i.Importe, |
| | 0 | 127 | | RubroContable = i.RubroContable, |
| | 0 | 128 | | ObjetoGasto = i.ObjetoGasto |
| | 0 | 129 | | }) |
| | 0 | 130 | | .ToListAsync(); |
| | 0 | 131 | | } |
| | | 132 | | |
| | | 133 | | public async Task<IEnumerable<LiquidacionResumenDto>> ObtenerResumenAsync(long periodoId, int version) |
| | | 134 | | { |
| | 0 | 135 | | return await _context.LiquidacionResumenes |
| | 0 | 136 | | .AsNoTracking() |
| | 0 | 137 | | .Where(r => r.PeriodoId == periodoId && r.Version == version) |
| | 0 | 138 | | .Select(r => new LiquidacionResumenDto |
| | 0 | 139 | | { |
| | 0 | 140 | | Version = r.Version, |
| | 0 | 141 | | ProgramaId = r.ProgramaId, |
| | 0 | 142 | | RegimenId = r.RegimenId, |
| | 0 | 143 | | Rubro083 = r.Rubro083, |
| | 0 | 144 | | TotalImporte = r.TotalImporte, |
| | 0 | 145 | | Descripcion = r.Descripcion |
| | 0 | 146 | | }) |
| | 0 | 147 | | .ToListAsync(); |
| | 0 | 148 | | } |
| | | 149 | | } |