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); }
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); }