< Summary

Information
Class: FAU.Logica.Calculators.DeficitCalculator
Assembly: FAU.Logica
File(s): /home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Calculators/DeficitCalculator.cs
Line coverage
95%
Covered lines: 45
Uncovered lines: 2
Coverable lines: 47
Total lines: 99
Line coverage: 95.7%
Branch coverage
90%
Covered branches: 20
Total branches: 22
Branch coverage: 90.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
AplicarAsync(...)94.44%181897.5%
OrdenarDescuentos(...)100%22100%
NormalizarOrdenLegal(...)50%22100%

File(s)

/home/runner/work/Sistema.Liquidacion.BE/Sistema.Liquidacion.BE/FAU.Logica/Calculators/DeficitCalculator.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using FAU.Entidades;
 7using FAU.Logica.DTOs;
 8
 9namespace FAU.Logica.Calculators
 10{
 11    /// <summary>
 12    /// Calculador de deficit que aplica descuentos personales respetando el minimo legal.
 13    /// Ordena por categoria legal, fecha de comunicacion y desempate estable por id.
 14    /// </summary>
 15    public class DeficitCalculator : IDeficitCalculator
 16    {
 017        private const decimal PorcentajeRetencionMinima = 0.35M;
 18
 19        public Task<IEnumerable<DescuentoAplicacionResult>> AplicarAsync(
 20            decimal nominalBruto,
 21            decimal descuentosLegales,
 22            IEnumerable<DescuentoPersonalInput> descuentosConfirmados,
 23            CancellationToken ct = default)
 24        {
 2025            if (descuentosConfirmados == null)
 026                return Task.FromResult(Enumerable.Empty<DescuentoAplicacionResult>());
 27
 2028            var minimo = Math.Round(nominalBruto * PorcentajeRetencionMinima, 2);
 2029            var disponibleTotal = Math.Round(nominalBruto - descuentosLegales - minimo, 2);
 2030            var resultados = new List<DescuentoAplicacionResult>();
 31
 2032            if (disponibleTotal <= 0)
 33            {
 1034                foreach (var descuento in OrdenarDescuentos(descuentosConfirmados))
 35                {
 336                    resultados.Add(new DescuentoAplicacionResult(
 337                        descuento.DescuentoPeriodoId,
 338                        descuento.PersonaId,
 339                        descuento.AcreedorId,
 340                        descuento.MontoSolicitado,
 341                        0m,
 342                        descuento.MontoSolicitado,
 343                        "deficit",
 344                        "No hay disponible segun minima retencion (35%)"
 345                    ));
 46                }
 47
 248                return Task.FromResult<IEnumerable<DescuentoAplicacionResult>>(resultados);
 49            }
 50
 1851            decimal restante = disponibleTotal;
 52
 14153            foreach (var descuento in OrdenarDescuentos(descuentosConfirmados))
 54            {
 5355                if (ct.IsCancellationRequested)
 156                    break;
 57
 5258                var aplicar = Math.Min(descuento.MontoSolicitado, Math.Round(Math.Max(0, restante), 2));
 59
 5260                var estado = aplicar == descuento.MontoSolicitado ? "aplicado"
 5261                    : aplicar > 0 ? "parcial" : "deficit";
 62
 5263                var motivo = aplicar == 0 ? "deficit" : null;
 64
 5265                resultados.Add(new DescuentoAplicacionResult(
 5266                    descuento.DescuentoPeriodoId,
 5267                    descuento.PersonaId,
 5268                    descuento.AcreedorId,
 5269                    descuento.MontoSolicitado,
 5270                    aplicar,
 5271                    descuento.MontoSolicitado - aplicar,
 5272                    estado,
 5273                    motivo
 5274                ));
 75
 5276                restante -= aplicar;
 5277                if (restante <= 0)
 2878                    restante = 0;
 79            }
 80
 1881            return Task.FromResult<IEnumerable<DescuentoAplicacionResult>>(resultados);
 82        }
 83
 84        private static IOrderedEnumerable<DescuentoPersonalInput> OrdenarDescuentos(
 85            IEnumerable<DescuentoPersonalInput> descuentos)
 86        {
 2087            return descuentos
 10588                .OrderBy(descuento => NormalizarOrdenLegal(descuento.OrdenLegalDeficit))
 10589                .ThenBy(descuento => descuento.FechaComunicacion ?? DateTime.MaxValue)
 10590                .ThenBy(descuento => descuento.DescuentoPeriodoId ?? long.MaxValue)
 12591                .ThenBy(descuento => descuento.CodigoConcepto);
 92        }
 93
 94        private static int NormalizarOrdenLegal(int ordenLegal)
 95        {
 10596            return ordenLegal > 0 ? ordenLegal : OrdenLegalDeficitDescuento.OtrasRetenciones;
 97        }
 98    }
 99}