public async Task PerformCalculationAsync_PerformsAPAndPACalculationsWithOnlyPAInput()
        {
            // Arrange
            var shiftPattern = new List <string> {
                "1", "2", "3", "4", "5"
            };

            var paRequest = new ProtectiveAwardCalculationRequestModel()
            {
                InsolvencyDate           = new DateTime(2018, 10, 20),
                EmploymentStartDate      = new DateTime(2016, 4, 6),
                DismissalDate            = new DateTime(2018, 10, 20),
                TribunalAwardDate        = new DateTime(2018, 10, 21),
                ProtectiveAwardStartDate = new DateTime(2018, 10, 22),
                ProtectiveAwardDays      = 90,
                PayDay       = 6,
                WeeklyWage   = 400M,
                ShiftPattern = shiftPattern,
            };

            var paResponse = new ProtectiveAwardResponseDTO()
            {
                IsTaxable    = true,
                StatutoryMax = 508m,
                PayLines     = new List <ProtectiveAwardPayLine>()
                {
                    new ProtectiveAwardPayLine(1, new DateTime(2018, 10, 27), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(2, new DateTime(2018, 11, 3), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(3, new DateTime(2018, 11, 10), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(4, new DateTime(2018, 11, 17), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(5, new DateTime(2018, 11, 24), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(6, new DateTime(2018, 12, 1), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(7, new DateTime(2018, 12, 8), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(8, new DateTime(2018, 12, 15), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(9, new DateTime(2018, 12, 22), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(10, new DateTime(2018, 12, 29), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(11, new DateTime(2019, 1, 5), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(12, new DateTime(2019, 1, 12), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(13, new DateTime(2019, 1, 12), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M)
                }
            };

            var request = new APPACalculationRequestModel()
            {
                Ap = null,
                Pa = paRequest
            };

            _paService.Setup(m => m.PerformProtectiveAwardCalculationAsync(paRequest, _options)).ReturnsAsync(paResponse);

            // Act
            var results = await _service.PerformCalculationAsync(request, _options);

            // Assert
            results.Ap.Should().BeNull();
            results.Pa.Should().NotBeNull();
            results.Pa.PayLines.Count(x => x.IsSelected).Should().Be(8);
        }
Exemplo n.º 2
0
        public async Task <ProtectiveAwardResponseDTO> PerformProtectiveAwardCalculationAsync(
            ProtectiveAwardCalculationRequestModel data, IOptions <ConfigLookupRoot> options)
        {
            var statMaxDate = data.DismissalDate;

            if (data.InsolvencyDate.Date > statMaxDate)
            {
                statMaxDate = data.InsolvencyDate.Date;
            }
            if (data.TribunalAwardDate.Date > statMaxDate)
            {
                statMaxDate = data.TribunalAwardDate.Date;
            }


            var statutoryMax = ConfigValueLookupHelper.GetStatutoryMax(options, statMaxDate);
            var taxRate      = ConfigValueLookupHelper.GetTaxRate(options, data.DismissalDate);
            var niThreshold  = ConfigValueLookupHelper.GetNIThreshold(options, DateTime.Now);
            var niRate       = ConfigValueLookupHelper.GetNIRate(options, DateTime.Now);

            DayOfWeek payDay = (DayOfWeek)data.PayDay;

            bool isTaxable = (await data.DismissalDate.GetTaxYear() == await data.TribunalAwardDate.GetTaxYear());

            //calculate paAwardEndDate e.g. paAwardStartDate + 30 days
            var protectiveAwardEndDate = data.ProtectiveAwardStartDate.Date.AddDays(data.ProtectiveAwardDays.Value - 1);

            var paBenefitsEndDate = protectiveAwardEndDate;

            // get pay weeks in PA Award
            var endDate = protectiveAwardEndDate;

            if (endDate.DayOfWeek != payDay)
            {
                endDate = endDate.AddDays(7);
            }

            // set pref period start date
            DateTime prefPeriodStartDate = data.InsolvencyDate.Date.AddMonths(-4);

            var payDays = await data.ProtectiveAwardStartDate.Date.GetDaysInRange(endDate, payDay);

            //calculate daily benefit rate if benefit amount is provided
            decimal benefitDailyRate = decimal.Zero;

            if (data.paBenefitAmount > decimal.Zero)
            {
                benefitDailyRate = await data.paBenefitAmount.GetDailyAmount(
                    data.paBenefitStartDate.Date,
                    paBenefitsEndDate.Date);
            }


            //step through payWeek
            var counter  = 1;
            var payLines = new List <ProtectiveAwardPayLine>();

            foreach (var payWeekEnd in payDays)
            {
                var employmentDays             = 0;
                var maximumDays                = 0;
                var benefitClaimedAmount       = 0.00m;
                var employmentDaysInPrefPeriod = 0;
                var maximumDaysInPrefPeriod    = 0;


                for (int j = 6; j >= 0; j--)
                {
                    DateTime day = payWeekEnd.AddDays(-j);

                    if (day >= data.ProtectiveAwardStartDate.Date && day <= protectiveAwardEndDate.Date)
                    {
                        //is this day in shift paattern (a working day)?
                        if (await data.ShiftPattern.ContainsDayWeek(day.DayOfWeek))
                        {
                            employmentDays++;

                            if (day >= prefPeriodStartDate && day <= data.InsolvencyDate)
                            {
                                employmentDaysInPrefPeriod++;
                            }
                        }

                        maximumDays++;

                        if (day >= prefPeriodStartDate && day <= data.InsolvencyDate)
                        {
                            maximumDaysInPrefPeriod++;
                        }
                    }

                    if (day >= data.paBenefitStartDate.Date && day <= paBenefitsEndDate.Date)
                    {
                        benefitClaimedAmount += benefitDailyRate;
                    }
                }

                // calculate Employer Liability for week
                decimal empLiability = data.WeeklyWage / data.ShiftPattern.Count * employmentDays;
                decimal employerEntitlementInPrefPeriod = data.WeeklyWage / data.ShiftPattern.Count * employmentDaysInPrefPeriod;

                //get Maximum Liability
                decimal maxLiability = statutoryMax;
                decimal maximumEntitlementInPrefPeriod = statutoryMax / 7 * maximumDaysInPrefPeriod;

                //if first week
                if (payWeekEnd == payDays.First())
                {
                    //if there is only one week OR claimant did start employment in the first week of claim
                    if ((payDays.Count() == 1) || data.EmploymentStartDate.Date >= payDays.First().AddDays(-7))
                    {
                        maxLiability = statutoryMax / 7M * maximumDays;
                    }
                }
                // if it is the last week
                else if (payWeekEnd == payDays.Last())
                {
                    if (payWeekEnd > protectiveAwardEndDate)
                    {
                        maxLiability = statutoryMax / 7 * maximumDays;
                    }
                }

                decimal grossEntitlement = Math.Min(empLiability, maxLiability) - benefitClaimedAmount;
                grossEntitlement = Math.Max(grossEntitlement, 0m);
                decimal taxDeducted = Math.Round(await grossEntitlement.GetTaxDeducted(taxRate, isTaxable), 2);
                decimal niDeducted  = Math.Round(await grossEntitlement.GetNIDeducted(niThreshold, niRate, true), 2);

                grossEntitlement = Math.Round(grossEntitlement, 2);
                decimal netEntitlement = grossEntitlement - taxDeducted - niDeducted;

                payLines.Add(new ProtectiveAwardPayLine()
                {
                    WeekNumber       = counter++,
                    PayDate          = payWeekEnd,
                    BenefitsClaimed  = Math.Round(benefitClaimedAmount, 2),
                    GrossEntitlement = grossEntitlement,
                    TaxDeducted      = taxDeducted,
                    NIDeducted       = niDeducted,
                    NetEntitlement   = netEntitlement,
                    IsSelected       = false,
                    MaximumEntitlementIn4MonthPeriod  = Math.Round(maximumEntitlementInPrefPeriod, 2),
                    EmployerEntitlementIn4MonthPeriod = Math.Round(employerEntitlementInPrefPeriod, 2),
                    GrossEntitlementIn4Months         = Math.Round(Math.Min(maximumEntitlementInPrefPeriod, employerEntitlementInPrefPeriod), 2)
                });
            }
            ;

            var result = new ProtectiveAwardResponseDTO()
            {
                IsTaxable    = isTaxable,
                StatutoryMax = statutoryMax,
                PayLines     = payLines
            };

            return(await Task.FromResult(result));
        }
        public async Task PerformCalculationAsync_PerformsAPAndPACalculationsWithRp1Selected()
        {
            // Arrange
            var shiftPattern = new List <string> {
                "1", "2", "3", "4", "5"
            };

            var apRequests = new List <ArrearsOfPayCalculationRequestModel>()
            {
                new ArrearsOfPayCalculationRequestModel()
                {
                    InputSource         = InputSource.Rp1,
                    InsolvencyDate      = new DateTime(2018, 10, 20),
                    EmploymentStartDate = new DateTime(2016, 04, 06),
                    DismissalDate       = new DateTime(2018, 10, 20),
                    DateNoticeGiven     = new DateTime(2018, 10, 6),
                    UnpaidPeriodFrom    = new DateTime(2018, 10, 1),
                    UnpaidPeriodTo      = new DateTime(2018, 10, 9),
                    ApClaimAmount       = 350M,
                    IsTaxable           = true,
                    PayDay       = 6,
                    ShiftPattern = shiftPattern,
                    WeeklyWage   = 200m
                },
                new ArrearsOfPayCalculationRequestModel()
                {
                    InputSource         = InputSource.Rp14a,
                    InsolvencyDate      = new DateTime(2018, 10, 20),
                    EmploymentStartDate = new DateTime(2016, 04, 06),
                    DismissalDate       = new DateTime(2018, 10, 20),
                    DateNoticeGiven     = new DateTime(2018, 10, 14),
                    UnpaidPeriodFrom    = new DateTime(2018, 10, 10),
                    UnpaidPeriodTo      = new DateTime(2018, 10, 18),
                    ApClaimAmount       = 600M,
                    IsTaxable           = true,
                    PayDay       = 6,
                    ShiftPattern = shiftPattern,
                    WeeklyWage   = 400m
                }
            };

            var apResponseRP1 = new ArrearsOfPayResponseDTO()
            {
                StatutoryMax = 508m,
                InputSource  = InputSource.Rp1,
                DngApplied   = true,
                RunNWNP      = false,
                WeeklyResult = new List <ArrearsOfPayWeeklyResult>()
                {
                    new ArrearsOfPayWeeklyResult(1, new DateTime(2018, 10, 6), 250m, 508M, 350, 350M, true, 50M, 30M, 300M, 7, 5, 508M, 300M, 300M),
                    new ArrearsOfPayWeeklyResult(2, new DateTime(2018, 10, 13), 250m, 508M, 20M, 20M, true, 4M, 0M, 16M, 7, 2, 508M, 20M, 20M),
                }
            };

            var apResponseRP14a = new ArrearsOfPayResponseDTO()
            {
                StatutoryMax = 508m,
                InputSource  = InputSource.Rp14a,
                DngApplied   = true,
                RunNWNP      = true,
                WeeklyResult = new List <ArrearsOfPayWeeklyResult>()
                {
                    new ArrearsOfPayWeeklyResult(1, new DateTime(2018, 10, 13), 428.57M, 508M, 257.14M, 357.14M, true, 51.43M, 11.42M, 294.29M, 7, 3, 508M, 357.14M, 357.14M),
                    new ArrearsOfPayWeeklyResult(2, new DateTime(2018, 10, 20), 428.57M, 508M, 22.86M, 22.86M, true, 4.57M, 0M, 28.29M, 7, 4, 508M, 22.86M, 22.86M),
                }
            };

            var paRequest = new ProtectiveAwardCalculationRequestModel()
            {
                InsolvencyDate           = new DateTime(2018, 10, 20),
                EmploymentStartDate      = new DateTime(2016, 4, 6),
                DismissalDate            = new DateTime(2018, 10, 20),
                TribunalAwardDate        = new DateTime(2018, 10, 21),
                ProtectiveAwardStartDate = new DateTime(2018, 10, 22),
                ProtectiveAwardDays      = 90,
                PayDay       = 6,
                WeeklyWage   = 400M,
                ShiftPattern = shiftPattern,
            };

            var paResponse = new ProtectiveAwardResponseDTO()
            {
                IsTaxable    = true,
                StatutoryMax = 508m,
                PayLines     = new List <ProtectiveAwardPayLine>()
                {
                    new ProtectiveAwardPayLine(1, new DateTime(2018, 10, 27), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(2, new DateTime(2018, 11, 3), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(3, new DateTime(2018, 11, 10), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(4, new DateTime(2018, 11, 17), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(5, new DateTime(2018, 11, 24), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(6, new DateTime(2018, 12, 1), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(7, new DateTime(2018, 12, 8), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(8, new DateTime(2018, 12, 15), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(9, new DateTime(2018, 12, 22), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(10, new DateTime(2018, 12, 29), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(11, new DateTime(2019, 1, 5), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(12, new DateTime(2019, 1, 12), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M),
                    new ProtectiveAwardPayLine(13, new DateTime(2019, 1, 12), 0M, 400M, 80M, 28.56M, 291.44M, 0M, 0M, 0M)
                }
            };

            var request = new APPACalculationRequestModel()
            {
                Ap = apRequests,
                Pa = paRequest
            };

            _apService.Setup(m => m.PerformCalculationAsync(apRequests, InputSource.Rp1, _options, It.IsAny <TraceInfo>())).ReturnsAsync(apResponseRP1);
            _apService.Setup(m => m.PerformCalculationAsync(apRequests, InputSource.Rp14a, _options, It.IsAny <TraceInfo>())).ReturnsAsync(apResponseRP14a);
            _paService.Setup(m => m.PerformProtectiveAwardCalculationAsync(paRequest, _options)).ReturnsAsync(paResponse);

            // Act
            var results = await _service.PerformCalculationAsync(request, _options);

            // Assert
            results.Ap.Should().NotBeNull();
            results.Pa.Should().NotBeNull();

            results.Ap.SelectedInputSource.Should().Be(InputSource.Rp1);
            results.Ap.RP1ResultsList.WeeklyResult.Count(x => x.IsSelected).Should().Be(1);
            results.Ap.RP14aResultsList.WeeklyResult.Count(x => x.IsSelected).Should().Be(0);
            results.Pa.PayLines.Count(x => x.IsSelected).Should().Be(7);
        }