| | | 1 | | namespace FAU.Logica.Services; |
| | | 2 | | |
| | | 3 | | public class CalcularDiferencia615Service : ICalcularDiferencia615Service |
| | | 4 | | { |
| | 1 | 5 | | private static readonly DateTime FechaMinAscenso = new DateTime(2018, 1, 1); |
| | | 6 | | |
| | | 7 | | // Catalog codes that accumulate into Σhaberes for Cbo.2da case |
| | 1 | 8 | | private static readonly HashSet<int> CodigosHaberesCbo = new() { 30, 37, 58, 15, 165, 40, 170, 172, 225, 38, 39, 41, |
| | | 9 | | // Catalog codes that accumulate into Σhaberes for Sgto case (adds 33) |
| | 1 | 10 | | private static readonly HashSet<int> CodigosHaberesSgto = new() { 30, 33, 37, 58, 15, 165, 170, 40, 172, 225, 38, 39 |
| | | 11 | | // Codes handled separately with /0.835 divisor |
| | | 12 | | // 299 = 043.003 (Comp. DI Oficial/Subalterno), 43002 = 043.002 (Complemento DI), |
| | | 13 | | // 230 = 045.002, 315 = 043.003 Subalterno |
| | 1 | 14 | | private static readonly int[] CodigosSeparados = { 299, 43002, 230, 315 }; |
| | | 15 | | // Additional codes only for Cbo.2da |
| | 1 | 16 | | private static readonly int[] CodigosSeparadosCboExtra = { 280, 276, 308 }; |
| | | 17 | | // Code for 041.003 (permanencia) — deducted in "con permanencia" sub-case |
| | | 18 | | private const int CodigoPermanencia = 40; |
| | | 19 | | |
| | | 20 | | public Task<decimal?> CalcularAsync( |
| | | 21 | | long personaId, |
| | | 22 | | long gradoNuevoId, |
| | | 23 | | string gradoNuevoCodigo, |
| | | 24 | | DateTime fechaUltimoAscenso, |
| | | 25 | | DateTime fechaPeriodo, |
| | | 26 | | IReadOnlyList<LiquidacionItemAnterior> itemsPeriodoActual, |
| | | 27 | | IReadOnlyList<LiquidacionItemAnterior> itemsPeriodoAnterior) |
| | | 28 | | { |
| | | 29 | | // Filter: only ascensos from 01/01/2018 |
| | 7 | 30 | | if (fechaUltimoAscenso < FechaMinAscenso) |
| | 1 | 31 | | return Task.FromResult<decimal?>(null); |
| | | 32 | | |
| | 6 | 33 | | var diasDesdeAscenso = (int)(fechaPeriodo - fechaUltimoAscenso).TotalDays; |
| | 6 | 34 | | bool esCbo2da = gradoNuevoCodigo == "CBO_2DA"; |
| | 6 | 35 | | bool esSgto = gradoNuevoCodigo == "SGTO"; |
| | | 36 | | |
| | 6 | 37 | | if (!esCbo2da && !esSgto) |
| | 1 | 38 | | return Task.FromResult<decimal?>(null); |
| | | 39 | | |
| | | 40 | | // Sub-case determination |
| | | 41 | | bool tienePermanencia; |
| | 5 | 42 | | if (esCbo2da) |
| | | 43 | | { |
| | 6 | 44 | | if (diasDesdeAscenso < 365) tienePermanencia = false; |
| | 3 | 45 | | else if (diasDesdeAscenso < 730) tienePermanencia = true; |
| | 1 | 46 | | else return Task.FromResult<decimal?>(null); // out of range |
| | | 47 | | } |
| | | 48 | | else // esSgto |
| | | 49 | | { |
| | 2 | 50 | | if (diasDesdeAscenso < 730) tienePermanencia = false; |
| | 0 | 51 | | else if (diasDesdeAscenso < 1095) tienePermanencia = true; |
| | 0 | 52 | | else return Task.FromResult<decimal?>(null); |
| | | 53 | | } |
| | | 54 | | |
| | 4 | 55 | | var codigosHaberes = esCbo2da ? CodigosHaberesCbo : CodigosHaberesSgto; |
| | | 56 | | |
| | | 57 | | // Σhaberes: sum of normal codes (viejo - nuevo) |
| | 4 | 58 | | decimal sumHaberesViejo = itemsPeriodoAnterior |
| | 7 | 59 | | .Where(i => codigosHaberes.Contains(i.CodigoConcepto)) |
| | 11 | 60 | | .Sum(i => i.Importe); |
| | 4 | 61 | | decimal sumHaberesNuevo = itemsPeriodoActual |
| | 7 | 62 | | .Where(i => codigosHaberes.Contains(i.CodigoConcepto)) |
| | 11 | 63 | | .Sum(i => i.Importe); |
| | 4 | 64 | | decimal diferencia = sumHaberesViejo - sumHaberesNuevo; |
| | | 65 | | |
| | | 66 | | // Codes separated with /0.835 |
| | 4 | 67 | | var todosCodsSep = esCbo2da |
| | 4 | 68 | | ? CodigosSeparados.Concat(CodigosSeparadosCboExtra) |
| | 4 | 69 | | : CodigosSeparados; |
| | | 70 | | |
| | 58 | 71 | | foreach (var cod in todosCodsSep) |
| | | 72 | | { |
| | 68 | 73 | | var viejo = itemsPeriodoAnterior.FirstOrDefault(i => i.CodigoConcepto == cod)?.Importe ?? 0m; |
| | 68 | 74 | | var nuevo = itemsPeriodoActual.FirstOrDefault(i => i.CodigoConcepto == cod)?.Importe ?? 0m; |
| | 25 | 75 | | diferencia += (viejo - nuevo) / 0.835m; |
| | | 76 | | } |
| | | 77 | | |
| | | 78 | | // Permanencia deduction |
| | 4 | 79 | | if (tienePermanencia) |
| | | 80 | | { |
| | 1 | 81 | | var permNuevo = itemsPeriodoActual |
| | 3 | 82 | | .FirstOrDefault(i => i.CodigoConcepto == CodigoPermanencia)?.Importe ?? 0m; |
| | 1 | 83 | | diferencia -= permNuevo; |
| | | 84 | | } |
| | | 85 | | |
| | 4 | 86 | | diferencia = Math.Round(diferencia, 2); |
| | | 87 | | |
| | 4 | 88 | | return Task.FromResult(diferencia > 0 ? (decimal?)diferencia : null); |
| | | 89 | | } |
| | | 90 | | } |