< Summary

Information
Class: FAU.Logica.Calculadores.CalculadorHaberesBase
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Calculadores/CalculadorHaberesBase.cs
Line coverage
91%
Covered lines: 142
Uncovered lines: 13
Coverable lines: 155
Total lines: 421
Line coverage: 91.6%
Branch coverage
88%
Covered branches: 71
Total branches: 80
Branch coverage: 88.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Calculadores/CalculadorHaberesBase.cs

#LineLine coverage
 1using FAU.Entidades;
 2using FAU.Logica.DTOs;
 3
 4namespace FAU.Logica.Calculadores;
 5
 6/// <summary>
 7/// Clase base de todas las calculadoras de haberes.
 8///
 9/// Flujo de cálculo (basado en SUM33100.PRG FoxPro):
 10///   1. CalcularItemsBase     → ítems propios de cada situación, retorna wpara53 (SIN SDL)
 11///   2. AgregarItemsDecreto   → ítems fijos por grado (decretos + recuperaciones + etc.),
 12///                              actualiza wpara53 si el ítem entra en la base SDL
 13///   3. CalcularItemsCondicionales → Riesgo de Vuelo, Progresivo, etc.
 14///   4. CalcularSDL           → 048.012 = wpara53 × 5,3%  (DESPUÉS de todos los ítems base)
 15///   5. CalcularDI            → 043.004 = wPara10 × porcentaje  (virtual, override por situación)
 16///   6. CalcularModAportes19695 → 042.413 (solo Ley Nueva)
 17///   7. CalcularReintegroAportes → 042.414 (solo Ley Nueva)
 18/// </summary>
 19public abstract class CalculadorHaberesBase : ICalculadorHaberes
 20{
 21    protected static class Codigos
 22    {
 23        internal const int SueldoBase          = 11000;
 24        internal const int SueldoReservista    = 11001;
 25        internal const int SueldoReservaJornal = 20;
 26        internal const int GastosRepresentacion = 15000;
 27        internal const int Permanencia         = 41003;
 28        internal const int CompCargo           = 42012;
 29        internal const int PermanenciaOrden    = 42014;
 30        internal const int RiesgoVuelo         = 42019;
 31        internal const int CompSuboficiales    = 42022;
 32        internal const int PrimaTecnicaPerm    = 42025;
 33        internal const int EquipoOficiales     = 42067;
 34        internal const int PrimaTecnicaPTI     = 42092;
 35        internal const int CompPersonal        = 210;   // 048.018 "COMP PERS #400 Y 250"
 36        internal const int PrimaIdoneidad      = 42093;
 37        internal const int CompCombatientes    = 42103;
 38        internal const int CompLey18834        = 42536;
 39        internal const int Ley20075Art80       = 42403;
 40        internal const int Ley20075Art80Sub    = 42623;  // versión subalternos (Art.80 Ley 20.075)
 41        internal const int ModAportes          = 42413;
 42        internal const int ReintegroAportes    = 42414;
 43        internal const int CompDI              = 43002;
 44        internal const int DedicacionIntegral  = 43004;
 45        internal const int Progresivo          = 44001;
 46        internal const int AumEsp85Mil         = 48004;
 47        internal const int AumEsp92            = 48009;
 48        internal const int Sdl                 = 48012;
 49        internal const int Ley17269            = 48015;
 50        internal const int AumDec191_003       = 48017;
 51        internal const int RecSalarial2007     = 48023;
 52        internal const int RecSalarial466      = 48026;
 53        internal const int PartEspLey18719     = 48038;
 54        internal const int Ley19355            = 48040;
 55        internal const int IncrSubEscK         = 48042;
 56        internal const int CompPAN             = 42571;
 57        internal const int CompSAR             = 42572;
 58        internal const int PermanenciaOrdenSup = 60;
 59        internal const int CompDiOficial       = 299;
 60        internal const int CompDiSubalterno    = 315;
 61        internal const int DifEquipoSinAportes = 69005;
 62        internal const int DifEquipoConAportes = 69006;
 63        internal const int ViaticoAlimentacion = 69008;
 64        internal const int ViaticossinAportes  = 69009;
 65        internal const int ViaticosConAportes  = 69010;
 66    }
 67
 168    private static readonly IReadOnlySet<int> EmptySet = new HashSet<int>();
 69
 70    /// <summary>Ítems excluidos completamente de AgregarItemsDecreto. Override por subclase.</summary>
 103271    protected virtual IReadOnlySet<int> CodigosExcluidosDecreto => EmptySet;
 72
 73    /// <summary>Ítems emitidos pero que NO contribuyen a la base SDL. Override por subclase.</summary>
 47374    protected virtual IReadOnlySet<int> CodigosExcluidosSDL => EmptySet;
 75
 76    /// <summary>Porcentaje de Dedicación Integral. Override por subclase.</summary>
 677    protected virtual decimal PorcentajeDedicacionIntegral => 0.10m;
 78
 79    /// <summary>
 80    /// Controla si se calcula el SDL (048.012 = 5.3%) para este funcionario.
 81    /// Por defecto true. Sit30Calculator lo sobreescribe para excluir grados de orden < 2.
 82    /// </summary>
 6783    protected virtual bool DebeCalcularSDL(RelacionLaboral funcionario, InsumosPeriodo insumos) => true;
 84
 85    public Task<ResultadoCalculo> CalcularAsync(
 86        RelacionLaboral funcionario, InsumosPeriodo insumos, Acumuladores acumuladores)
 87    {
 9988        var resultado = new ResultadoCalculo();
 89        try
 90        {
 9991            var wpara53 = CalcularItemsBase(funcionario, insumos, acumuladores, resultado);
 9292            wpara53 += AgregarItemsDecreto(funcionario, insumos, acumuladores, resultado);
 9293            wpara53 += AgregarItemsCondicionales(funcionario, insumos, acumuladores, resultado);
 94
 9295            if (wpara53 > 0)
 96            {
 97                decimal wPara10;
 8998                if (DebeCalcularSDL(funcionario, insumos))
 99                {
 75100                    var sdl = Math.Round(wpara53 * 0.053m, 2);
 75101                    AgregarItem(Codigos.Sdl, sdl, insumos, acumuladores, resultado);
 75102                    wPara10 = wpara53 + sdl;
 103                }
 104                else
 105                {
 14106                    wPara10 = wpara53;
 107                }
 89108                CalcularDedicacionIntegral(wPara10, funcionario, insumos, acumuladores, resultado);
 109            }
 110
 111            // 042.414 — Reintegro de Aportes: aplica a TODOS los regímenes.
 112            // FoxPro SUM33316.PRG no verifica Ley Vieja/Nueva — confirmado por recibos
 113            // legacy donde aparece 042.414 sin 042.413 (que sí es exclusivo de Ley Nueva).
 92114            var esOficial = insumos.OrdenPorGrado.TryGetValue(funcionario.GradoId, out var gradoOrden)
 92115                ? gradoOrden >= 7
 92116                : (funcionario.Grado?.EsOficial ?? false);
 92117            CalcularReintegroAportes(esOficial, acumuladores, insumos, resultado);
 118
 119            // 042.413 (Mod.Aportes) se calcula en LiquidacionService DESPUÉS del paso de
 120            // compensaciones para que entren en WNominal. No calcular aquí (evita duplicado).
 121            // Solo Ley Nueva (19.695) — FoxPro SUM33315.PRG confirma condición de régimen.
 122
 92123            if (!funcionario.Situacion.AfectaCobro)
 10124                foreach (var item in resultado.Items)
 4125                    item.EsReferencia = true;
 126
 92127            resultado.Estado = resultado.Incidencias.Count > 0
 92128                ? EstadoCalculo.Revisar
 92129                : EstadoCalculo.Calculado;
 92130        }
 7131        catch (Exception ex)
 132        {
 7133            resultado.Estado = EstadoCalculo.Error;
 7134            resultado.MensajeError = ex.Message;
 7135        }
 136
 99137        return Task.FromResult(resultado);
 138    }
 139
 140    // ── Métodos abstractos/virtuales que cada calculadora puede sobreescribir ──────
 141
 142    /// <summary>
 143    /// Calcula los ítems propios de la situación.
 144    /// NO incluye SDL (048.012) ni DI (043.004) — los maneja la clase base.
 145    /// Retorna wpara53: suma de los ítems que entran en la base del SDL.
 146    /// </summary>
 147    protected abstract decimal CalcularItemsBase(
 148        RelacionLaboral funcionario, InsumosPeriodo insumos,
 149        Acumuladores acumuladores, ResultadoCalculo resultado);
 150
 151    /// <summary>
 152    /// Agrega decretos y recuperaciones fijas por grado (lookup en remuneraciones_grado).
 153    /// Subclases pueden excluir ítems via CodigosExcluidosDecreto / CodigosExcluidosSDL.
 154    /// Retorna el extra a sumar a wpara53 (solo ítems que entran en SDL).
 155    /// </summary>
 156    protected virtual decimal AgregarItemsDecreto(
 157        RelacionLaboral funcionario, InsumosPeriodo insumos,
 158        Acumuladores acumuladores, ResultadoCalculo resultado)
 159    {
 92160        decimal extraWPara53 = 0m;
 161
 162        // Entran en base SDL (confirmado por fórmula PDF 048.012)
 92163        extraWPara53 += AgregarDecretoSdl(Codigos.CompCargo, funcionario, insumos, acumuladores, resultado);       // 04
 92164        extraWPara53 += AgregarDecretoSdl(Codigos.AumEsp85Mil, funcionario, insumos, acumuladores, resultado);
 92165        extraWPara53 += AgregarDecretoSdl(Codigos.RecSalarial2007, funcionario, insumos, acumuladores, resultado);
 92166        extraWPara53 += AgregarDecretoSdl(Codigos.RecSalarial466, funcionario, insumos, acumuladores, resultado);
 92167        extraWPara53 += AgregarDecretoSdl(Codigos.CompCombatientes, funcionario, insumos, acumuladores, resultado);
 92168        extraWPara53 += AgregarDecretoSdl(Codigos.EquipoOficiales, funcionario, insumos, acumuladores, resultado);
 169
 170        // NO entran en base SDL (Calc_Hab.prg confirmado)
 92171        AgregarDecretoNoSdl(Codigos.AumEsp92, funcionario, insumos, acumuladores, resultado);
 92172        AgregarDecretoNoSdl(Codigos.Ley17269, funcionario, insumos, acumuladores, resultado);
 92173        AgregarDecretoNoSdl(Codigos.AumDec191_003, funcionario, insumos, acumuladores, resultado);
 92174        AgregarDecretoNoSdl(Codigos.Ley19355, funcionario, insumos, acumuladores, resultado);
 92175        AgregarDecretoNoSdl(Codigos.IncrSubEscK, funcionario, insumos, acumuladores, resultado);    // 048.042 — "No va?
 92176        AgregarDecretoNoSdl(Codigos.PartEspLey18719, funcionario, insumos, acumuladores, resultado); // 048.038 — NO ent
 92177        AgregarDecretoNoSdl(Codigos.CompLey18834, funcionario, insumos, acumuladores, resultado);
 92178        AgregarDecretoNoSdl(Codigos.Ley20075Art80, funcionario, insumos, acumuladores, resultado);    // 042.403 Oficial
 92179        AgregarDecretoNoSdl(Codigos.Ley20075Art80Sub, funcionario, insumos, acumuladores, resultado); // 042.623 Subalte
 92180        AgregarDecretoNoSdl(Codigos.DifEquipoSinAportes, funcionario, insumos, acumuladores, resultado);
 92181        AgregarDecretoNoSdl(Codigos.DifEquipoConAportes, funcionario, insumos, acumuladores, resultado);
 92182        AgregarDecretoNoSdl(Codigos.ViaticossinAportes, funcionario, insumos, acumuladores, resultado);
 92183        AgregarDecretoNoSdl(Codigos.ViaticosConAportes, funcionario, insumos, acumuladores, resultado);
 92184        AgregarDecretoNoSdl(Codigos.CompPAN, funcionario, insumos, acumuladores, resultado);
 92185        AgregarDecretoNoSdl(Codigos.CompSAR, funcionario, insumos, acumuladores, resultado);
 92186        AgregarDecretoNoSdl(Codigos.CompDI, funcionario, insumos, acumuladores, resultado);         // 043.002 Compl. DI
 92187        AgregarDecretoNoSdl(Codigos.CompDiOficial, funcionario, insumos, acumuladores, resultado);  // 299 043.003 Ofici
 92188        AgregarDecretoNoSdl(Codigos.CompDiSubalterno, funcionario, insumos, acumuladores, resultado); // 315 043.003 Sub
 189
 92190        return extraWPara53;
 191    }
 192
 193    /// <summary>
 194    /// Ítems condicionales: Riesgo de Vuelo, Progresivo, Prima Técnica, etc.
 195    /// Override por subclase si la situación los tiene.
 196    /// Retorna el extra a sumar a wpara53 (solo ítems en base SDL).
 197    /// </summary>
 198    protected virtual decimal AgregarItemsCondicionales(
 199        RelacionLaboral funcionario, InsumosPeriodo insumos,
 200        Acumuladores acumuladores, ResultadoCalculo resultado)
 201    {
 92202        decimal extraWPara53 = 0m;
 203
 204        // 042.092 — Prima Técnica (categorías A/B/C designadas por Orden del Comando)
 205        // El monto depende de la CATEGORÍA del funcionario (A/B/C), no del grado — confirmado
 206        // contra recibo real: A=3040.33, B=1520.16, C=912.10 (tarifas_por_categoria).
 207        // Solo aplica de Sdo.1ra a S.O.M. (orden 1-6); oficiales no la cobran.
 92208        if (!string.IsNullOrEmpty(funcionario.PrimaTecnica) && funcionario.PrimaTecnica != "VACIO")
 209        {
 11210            var ordenPT = insumos.OrdenPorGrado.TryGetValue(funcionario.GradoId, out var oPT) ? oPT : (short)0;
 11211            if (ordenPT is >= 1 and <= 6)
 212            {
 6213                var tarifaPT = insumos.ObtenerTarifaCategoria(funcionario.PrimaTecnica, Codigos.PrimaTecnicaPTI);
 6214                if (tarifaPT is not null)
 5215                    AgregarItem(Codigos.PrimaTecnicaPTI, tarifaPT.Monto, insumos, acumuladores, resultado);
 216            }
 217        }
 218
 219        // 048.018 — Compensación Personal ("COMP PERS #400 Y 250", cód. legacy 210).
 220        // Importe individual por persona (tabla comp_personal_048018), cargado a mano,
 221        // NO se calcula por grado ni por fórmula. Común a todas las situaciones — confirmado
 222        // en Calc_Hab.prg (compartido) y SUM33101.PRG.
 223        // NO entra en wpara53/DI: el bloque "do grabo_codigo" de este ítem en Calc_Hab.prg
 224        // no incrementa m.para_5_3/m.para_10 (a diferencia de AumEsp85Mil/RecSalarial, que sí
 225        // lo hacen explícitamente). El "sdl_lq = .t." de ACUM_400.PRG es solo una clasificación
 226        // de reporte en un script offline aparte, no alimenta la fórmula de 048.012/043.004.
 227        // Verificado contra recibo real: incluirlo en wpara53 infla la Dedicación Integral
 228        // (35% de más) por encima del valor real.
 92229        var compPersonal = insumos.ObtenerCompPersonal048018(funcionario.PersonaId);
 92230        if (compPersonal is not null)
 2231            AgregarItem(Codigos.CompPersonal, compPersonal.Importe, insumos, acumuladores, resultado);
 232
 233        // 042.093 — Prima Idoneidad (sin aporte), si el funcionario tiene superprima.
 92234        if (funcionario.Superprima)
 235        {
 1236            var remIdoneidad = insumos.ObtenerRemuneracion(funcionario.GradoId, Codigos.PrimaIdoneidad);
 1237            if (remIdoneidad is not null)
 1238                AgregarItem(Codigos.PrimaIdoneidad, remIdoneidad.Monto, insumos, acumuladores, resultado);
 239        }
 240
 241        // 042.025 — Prima Técnica Permanente (entra en base SDL/DI — confirmado Calc_Hab.prg)
 92242        var remPrimaTec = insumos.ObtenerRemuneracion(funcionario.GradoId, Codigos.PrimaTecnicaPerm);
 92243        if (remPrimaTec is not null)
 244        {
 0245            AgregarItem(Codigos.PrimaTecnicaPerm, remPrimaTec.Monto, insumos, acumuladores, resultado);
 0246            extraWPara53 += remPrimaTec.Monto;
 247        }
 248
 249        // 042.019 — Riesgo de Vuelo (si relacion_laboral.riesgo_vuelo > 0); PDF: SÍ entra en SDL y DI
 92250        if (funcionario.RiesgoVuelo.HasValue && funcionario.RiesgoVuelo.Value > 0)
 251        {
 0252            var remVuelo = insumos.ObtenerRemuneracion(funcionario.GradoId, Codigos.RiesgoVuelo);
 0253            if (remVuelo is not null)
 254            {
 0255                AgregarItem(Codigos.RiesgoVuelo, remVuelo.Monto, insumos, acumuladores, resultado);
 0256                extraWPara53 += remVuelo.Monto;
 257            }
 258        }
 259
 260        // 044.001 — Progresivo / Prima por Antigüedad
 261        // Se cuenta la antigüedad total desde FechaInicio con un único floor sobre el total de
 262        // días. Antes se partía en dos tramos (Inicio→UltAsc y UltAsc→Período) y se sumaban los
 263        // floors de cada tramo por separado; como floor(a)+floor(b) <= floor(a+b), eso pierde un
 264        // año completo cada vez que las partes fraccionarias de ambos tramos suman >= 1 (el caso
 265        // común, no la excepción) — confirmado contra recibo real (cédula 4102253-0: el sistema
 266        // daba 27 años/$3.078,27 cuando correspondían 28 años/$3.192,28).
 267        // Para oficiales, la antigüedad se cuenta igual desde FechaAscensoOficial si existe.
 92268        var fechaPeriodo = new DateTime(insumos.ParametroPeriodo.Anio, insumos.ParametroPeriodo.Mes, 1);
 92269        var fechaBaseAntiguedad = funcionario.FechaAscensoOficial ?? funcionario.FechaInicio;
 92270        var aniosBrutos = Math.Max(0, (int)((fechaPeriodo - fechaBaseAntiguedad).TotalDays / 365.25));
 92271        var anios = Math.Max(0, aniosBrutos - (funcionario.AniosInactivos ?? 0));
 92272        if (anios > 0)
 273        {
 92274            var remProg = insumos.ObtenerRemuneracion(funcionario.GradoId, Codigos.Progresivo);
 92275            if (remProg is not null)
 276            {
 3277                var montoProg = remProg.Monto * Math.Min(anios, 30);
 3278                AgregarItem(Codigos.Progresivo, montoProg, insumos, acumuladores, resultado);
 3279                extraWPara53 += montoProg;
 280            }
 281        }
 282
 283        // PROGRE.TROPA: tramo subalterno para oficiales que ascendieron desde tropa.
 284        // FoxPro: m.anios = Anios_Trop (= fecha_asc_oficial - fecha_sub en años).
 285        // Tasa: la del grado subalterno de menor orden (SDO_1RA = $114.01/año en 2026).
 92286        if (funcionario.FechaAscensoOficial.HasValue &&
 92287            funcionario.FechaAscensoOficial.Value > funcionario.FechaInicio)
 288        {
 1289            var aniosTropa = Math.Max(0,
 1290                (int)((funcionario.FechaAscensoOficial.Value - funcionario.FechaInicio).TotalDays / 365.25));
 1291            aniosTropa = Math.Min(aniosTropa + funcionario.AniosServicioAnterior, 30);
 1292            if (aniosTropa > 0)
 293            {
 294                // Tasa subalterno: progresivo del grado con menor orden (SDO_1RA, orden=1)
 1295                var gradoId = insumos.OrdenPorGrado
 0296                    .Where(kv => kv.Value == 1)
 0297                    .Select(kv => (long?)kv.Key)
 1298                    .FirstOrDefault();
 1299                var remTropa = gradoId.HasValue
 1300                    ? insumos.ObtenerRemuneracion(gradoId.Value, Codigos.Progresivo)
 1301                    : null;
 1302                if (remTropa is not null)
 303                {
 0304                    var montoTropa = remTropa.Monto * aniosTropa;
 0305                    AgregarItem(Codigos.Progresivo, montoTropa, insumos, acumuladores, resultado);
 0306                    extraWPara53 += montoTropa;
 307                }
 308            }
 309        }
 310
 92311        return extraWPara53;
 312    }
 313
 314    /// <summary>
 315    /// Calcula Dedicación Integral (043.004).
 316    /// Override en subclases que usan porcentaje distinto o ítem diferente (p.ej. PAO).
 317    /// </summary>
 318    protected virtual void CalcularDedicacionIntegral(
 319        decimal wPara10, RelacionLaboral funcionario,
 320        InsumosPeriodo insumos, Acumuladores acumuladores, ResultadoCalculo resultado)
 321    {
 46322        if (wPara10 <= 0) return;
 46323        var di = Math.Round(wPara10 * PorcentajeDedicacionIntegral, 2);
 46324        AgregarItem(Codigos.DedicacionIntegral, di, insumos, acumuladores, resultado);
 46325    }
 326
 327    // ── Helpers internos ──────────────────────────────────────────────────────────
 328
 329    /// <summary>Agrega el ítem si existe en remuneraciones. Retorna el monto agregado (o 0).</summary>
 330    protected static decimal AgregarSiExiste(
 331        RelacionLaboral funcionario, InsumosPeriodo insumos,
 332        Acumuladores acumuladores, ResultadoCalculo resultado, int codigo)
 333    {
 2141334        var grupo = insumos.GrupoPorEscalafon.GetValueOrDefault(funcionario.EscalafonId);
 2141335        var rem = insumos.ObtenerRemuneracion(funcionario.GradoId, codigo, grupo);
 4236336        if (rem is null) return 0m;
 46337        AgregarItem(codigo, rem.Monto, insumos, acumuladores, resultado);
 46338        return rem.Monto;
 339    }
 340
 341    protected static void AgregarItem(
 342        int codigo, decimal monto, InsumosPeriodo insumos,
 343        Acumuladores acumuladores, ResultadoCalculo resultado)
 344    {
 3820345        var catalogoItem = insumos.CatalogoItems.FirstOrDefault(c => c.Codigo == codigo);
 400346        resultado.Items.Add(new ItemCalculado
 400347        {
 400348            CodigoConcepto = codigo,
 400349            NombreConcepto = catalogoItem?.Nombre ?? $"Concepto {codigo}",
 400350            Importe = monto
 400351        });
 400352        if (catalogoItem is not null)
 392353            acumuladores.AgregarItem(monto, catalogoItem);
 400354    }
 355
 356    protected static int CalcularAniosServicio(RelacionLaboral funcionario, InsumosPeriodo insumos)
 357    {
 0358        var fechaPeriodo = new DateTime(insumos.ParametroPeriodo.Anio, insumos.ParametroPeriodo.Mes, 1);
 0359        return Math.Max(0, (int)((fechaPeriodo - funcionario.FechaInicio).TotalDays / 365.25));
 360    }
 361
 362    protected static int CalcularMesesPermanencia(RelacionLaboral funcionario, InsumosPeriodo insumos)
 363    {
 364        // 041.003 mide tiempo en el grado actual, no tiempo total de servicio.
 83365        var fechaBase = funcionario.FechaUltimoAscenso ?? funcionario.FechaInicio;
 83366        var fechaPeriodo = new DateTime(insumos.ParametroPeriodo.Anio, insumos.ParametroPeriodo.Mes, 1);
 83367        var meses = (fechaPeriodo.Year - fechaBase.Year) * 12
 83368                    + fechaPeriodo.Month - fechaBase.Month;
 83369        return Math.Max(0, meses);
 370    }
 371
 372    // Emite el ítem y acumula a la base SDL, respetando CodigosExcluidosDecreto/CodigosExcluidosSDL.
 373    private decimal AgregarDecretoSdl(
 374        int codigo, RelacionLaboral funcionario, InsumosPeriodo insumos,
 375        Acumuladores acumuladores, ResultadoCalculo resultado)
 376    {
 607377        if (CodigosExcluidosDecreto.Contains(codigo)) return 0m;
 497378        var monto = AgregarSiExiste(funcionario, insumos, acumuladores, resultado, codigo);
 497379        return CodigosExcluidosSDL.Contains(codigo) ? 0m : monto;
 380    }
 381
 382    // Emite el ítem sin acumularlo a la base SDL, respetando CodigosExcluidosDecreto.
 383    private void AgregarDecretoNoSdl(
 384        int codigo, RelacionLaboral funcionario, InsumosPeriodo insumos,
 385        Acumuladores acumuladores, ResultadoCalculo resultado)
 386    {
 1656387        if (!CodigosExcluidosDecreto.Contains(codigo))
 1644388            AgregarSiExiste(funcionario, insumos, acumuladores, resultado, codigo);
 1656389    }
 390
 391    /// <summary>
 392    /// 042.414 — Reintegro de Aportes por Cambio de Régimen de Aportación.
 393    /// Fórmula PDF: Σ(069.006 + 069.008 + 069.010 + 042.092×2 + 043.002 + 042.571 + 042.572) / 0.87 × 13%
 394    /// 042.092 cuenta doble porque el régimen nuevo aplica aporte doble sobre esa compensación.
 395    /// Solo aplica en régimen Ley Nueva (llamado desde CalcularAsync junto con 042.413).
 396    /// </summary>
 397    private static void CalcularReintegroAportes(
 398        bool esOficial, Acumuladores acumuladores, InsumosPeriodo insumos, ResultadoCalculo resultado)
 399    {
 2926400        decimal Suma(int codigo) => resultado.Items.Where(i => i.CodigoConcepto == codigo).Sum(i => i.Importe);
 401
 402        // Fórmula SUM33316.PRG: acumula (item/0.87) para códigos específicos, × 13%.
 403        // 069.008 (subalterno c/aportes) o 069.006 (oficial c/aportes) — excluyentes.
 404        // Subalternos sin CAT_VIAT (cadetes, aprendices, SDO sin viático): $0 para 069.x.
 405        // 042.092 se agrega UNA vez (verificado en legacy con dos personas).
 92406        var suma69 = Suma(Codigos.ViaticoAlimentacion) > 0m ? Suma(Codigos.ViaticoAlimentacion)
 92407                   : (esOficial ? Suma(Codigos.DifEquipoConAportes) : 0m);
 408
 92409        var base042414 =
 92410            suma69                    +
 92411            Suma(Codigos.ViaticosConAportes) +
 92412            Suma(Codigos.PrimaTecnicaPTI)    +    // × 1 (no ×2, verificado legacy)
 92413            Suma(Codigos.CompDI)             +
 92414            Suma(Codigos.CompPAN)            +    // solo vía lote
 92415            Suma(Codigos.CompSAR);                // solo vía lote
 416
 175417        if (base042414 <= 0m) return;
 9418        var monto = Math.Round(base042414 / 0.87m * 0.13m, 2);
 9419        AgregarItem(Codigos.ReintegroAportes, monto, insumos, acumuladores, resultado);
 9420    }
 421}

Methods/Properties

.cctor()
get_CodigosExcluidosDecreto()
get_CodigosExcluidosSDL()
get_PorcentajeDedicacionIntegral()
DebeCalcularSDL(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo)
CalcularAsync(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores)
AgregarItemsDecreto(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
AgregarItemsCondicionales(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
CalcularDedicacionIntegral(System.Decimal,FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
AgregarSiExiste(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo,System.Int32)
AgregarItem(System.Int32,System.Decimal,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
CalcularAniosServicio(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo)
CalcularMesesPermanencia(FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo)
AgregarDecretoSdl(System.Int32,FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
AgregarDecretoNoSdl(System.Int32,FAU.Entidades.RelacionLaboral,FAU.Logica.DTOs.InsumosPeriodo,FAU.Entidades.Acumuladores,FAU.Logica.Calculadores.ResultadoCalculo)
Suma()
CalcularReintegroAportes(System.Boolean,FAU.Entidades.Acumuladores,FAU.Logica.DTOs.InsumosPeriodo,FAU.Logica.Calculadores.ResultadoCalculo)