public async Task PerformHolidayCalculationAsync_PerformsHpaAndHtnpCalculationsWithRp14aSelected() { // Arrange var shiftPattern = new List <string> { "1", "2", "3", "4", "5" }; var hpaRequest = new HolidayPayAccruedCalculationRequestModel { InsolvencyDate = new DateTime(2018, 10, 1), EmpStartDate = new DateTime(2016, 1, 1), DismissalDate = new DateTime(2018, 10, 1), ContractedHolEntitlement = 25, HolidayYearStart = new DateTime(2018, 1, 1), IsTaxable = true, PayDay = (int)DayOfWeek.Saturday, ShiftPattern = shiftPattern, WeeklyWage = 320m, DaysCFwd = 0m, DaysTaken = 8m, }; var hpaResponse = new HolidayPayAccruedResponseDTO() { StatutoryMax = 508, HolidaysOwed = 28, BusinessDaysInClaim = 261, WorkingDaysInClaim = 196, ProRataAccruedDays = 13.0268m, WeeklyResults = new List <HolidayPayAccruedWeeklyResult>() { new HolidayPayAccruedWeeklyResult(1, 508m, 320m, 320m, true, 64m, 18.96m, 237.04m, 320m, 0m), new HolidayPayAccruedWeeklyResult(2, 508m, 320m, 320m, true, 64m, 18.96m, 237.04m, 320m, 0m), new HolidayPayAccruedWeeklyResult(3, 292.23m, 193.72m, 193.72m, true, 38.74m, 3.81m, 151.17m, 193.72m, 0m), } }; var htnpRequest = new List <HolidayTakenNotPaidCalculationRequestModel>() { new HolidayTakenNotPaidCalculationRequestModel(InputSource.Rp1, new DateTime(2018, 10, 1), new DateTime(2018, 10, 1), new DateTime(2018, 8, 1), new DateTime(2018, 8, 12), 320, shiftPattern, 6, true), new HolidayTakenNotPaidCalculationRequestModel(InputSource.Rp14a, new DateTime(2018, 10, 1), new DateTime(2018, 10, 1), new DateTime(2018, 8, 2), new DateTime(2018, 8, 14), 320, shiftPattern, 6, true) }; var htnpResponseRp1 = new HolidayTakenNotPaidResponseDTO() { InputSource = InputSource.Rp1, WeeklyResult = new List <HolidayTakenNotPaidWeeklyResult>() { new HolidayTakenNotPaidWeeklyResult(1, new DateTime(2018, 8, 4), 508, 192, 192, true, 38.4m, 3.6m, 150m, 7, 3, 508, 192, 192, true), new HolidayTakenNotPaidWeeklyResult(2, new DateTime(2018, 8, 11), 508, 320, 320, true, 64m, 18.96m, 237.04m, 7, 5, 508, 320, 320, true), } }; var htnpResponseRp14a = new HolidayTakenNotPaidResponseDTO() { InputSource = InputSource.Rp14a, WeeklyResult = new List <HolidayTakenNotPaidWeeklyResult>() { new HolidayTakenNotPaidWeeklyResult(1, new DateTime(2018, 8, 4), 508, 128, 128, true, 25.6m, 0m, 102.4m, 7, 2, 508, 128, 128, false), new HolidayTakenNotPaidWeeklyResult(2, new DateTime(2018, 8, 11), 508, 320, 320, true, 64m, 18.96m, 237.04m, 7, 5, 508, 320, 320, false), new HolidayTakenNotPaidWeeklyResult(3, new DateTime(2018, 8, 18), 508, 128, 128, true, 25.6m, 0m, 102.4m, 7, 2, 508, 128, 128, false) } }; _hpaService.Setup(x => x.PerformHolidayPayAccruedCalculationAsync(hpaRequest, _options)).ReturnsAsync(hpaResponse); _htnpService.Setup(x => x.PerformCalculationAsync(htnpRequest, InputSource.Rp1, It.IsAny <decimal>(), It.IsAny <decimal>(), It.IsAny <DateTime?>(), _options, It.IsAny <TraceInfo>())).ReturnsAsync(htnpResponseRp1); _htnpService.Setup(x => x.PerformCalculationAsync(htnpRequest, InputSource.Rp14a, It.IsAny <decimal>(), It.IsAny <decimal>(), It.IsAny <DateTime?>(), _options, It.IsAny <TraceInfo>())).ReturnsAsync(htnpResponseRp14a); var request = new HolidayCalculationRequestModel() { Hpa = hpaRequest, Htnp = htnpRequest }; // Act var results = await _service.PerformHolidayCalculationAsync(request, _options); // Assert results.Hpa.Should().NotBeNull(); results.Htnp.Should().NotBeNull(); results.Htnp.SelectedInputSource.Should().Be(InputSource.Rp1); _hpaService.Verify(m => m.PerformHolidayPayAccruedCalculationAsync( hpaRequest, It.IsAny <IOptions <ConfigLookupRoot> >()), Times.Once); _htnpService.Verify(m => m.PerformCalculationAsync( It.IsAny <List <HolidayTakenNotPaidCalculationRequestModel> >(), InputSource.Rp1, 14.9732m, 16.9732m, hpaRequest.HolidayYearStart, It.IsAny <IOptions <ConfigLookupRoot> >(), It.IsAny <TraceInfo>()), Times.Once); _htnpService.Verify(m => m.PerformCalculationAsync( htnpRequest, InputSource.Rp14a, 0m, 0m, hpaRequest.HolidayYearStart, It.IsAny <IOptions <ConfigLookupRoot> >(), It.IsAny <TraceInfo>()), Times.Once); }
public async Task <HolidayPayAccruedResponseDTO> PerformHolidayPayAccruedCalculationAsync( HolidayPayAccruedCalculationRequestModel data, IOptions <ConfigLookupRoot> options) { var response = new ResponseDto <HolidayPayAccruedResponseDTO>(); var calculationResult = new HolidayPayAccruedResponseDTO(); var shiftPattern = data.ShiftPattern; var twelveMonthsPrior = data.InsolvencyDate.Date.AddMonths(-12).AddDays(1); var adjHolYearStart = await data.GetHolidayYearStart(); if (adjHolYearStart < twelveMonthsPrior) { adjHolYearStart = twelveMonthsPrior; } var holYearEndDate = await data.GetHolidayYearEnd(); var statMaxWeeklyPay = ConfigValueLookupHelper.GetStatutoryMax(options, data.DismissalDate); // Calculate totals for holiday pay accrued int totalBusinessDaysInClaim = await data.HolidayYearStart.GetNumBusinessDaysInRange(holYearEndDate, shiftPattern); int totalWorkingDaysInClaim = 0; totalWorkingDaysInClaim = await totalWorkingDaysInClaim.GetTotalWorkingDaysInHolidayClaim( data.ShiftPattern, adjHolYearStart, holYearEndDate.Date, data.DismissalDate.Date, data.InsolvencyDate.Date, data.EmpStartDate.Date); decimal limitedDaysCFwd = 0.00m; limitedDaysCFwd = await limitedDaysCFwd.GetLimitedDaysCFwd(shiftPattern, data.DaysCFwd.GetValueOrDefault()); decimal statHolEntitlement = 0.00m; statHolEntitlement = await statHolEntitlement.GetStatutoryHolidayEntitlement(shiftPattern); decimal adjHolidayEntitlement = await statHolEntitlement.GetAdjustedHolidayEntitlement(data.ContractedHolEntitlement.GetValueOrDefault()); decimal proRataAccruedDays = 0.00m; proRataAccruedDays = await proRataAccruedDays.GetProRataAccruedDays((decimal)adjHolidayEntitlement, totalBusinessDaysInClaim, totalWorkingDaysInClaim, limitedDaysCFwd, data.DaysTaken.GetValueOrDefault(), shiftPattern, data.IpConfirmedDays); calculationResult.BusinessDaysInClaim = totalBusinessDaysInClaim; calculationResult.StatutoryMax = Math.Round(statMaxWeeklyPay, 2); calculationResult.WorkingDaysInClaim = totalWorkingDaysInClaim; calculationResult.HolidaysOwed = Math.Round(adjHolidayEntitlement, 4); calculationResult.ProRataAccruedDays = Math.Round(proRataAccruedDays, 4); // Calculate weekly breakdown of holiday pay accrued var taxRate = ConfigValueLookupHelper.GetTaxRate(options, DateTime.Now); var niThreshold = ConfigValueLookupHelper.GetNIThreshold(options, DateTime.Now); var niRate = ConfigValueLookupHelper.GetNIRate(options, DateTime.Now); decimal entitlementWeeks = (proRataAccruedDays / data.ShiftPattern.Count); int wholeWeeks = (int)Math.Floor(entitlementWeeks); decimal partWeekDays = (entitlementWeeks - wholeWeeks) * shiftPattern.Count; decimal maximumEntitlement = 0.00m; decimal employerEntitlement = 0.00m; var weeklyResults = new List <HolidayPayAccruedWeeklyResult>(); decimal maxDays; decimal empDays; // Loop through each holiday entitlement week for (var weekNumber = 1; weekNumber <= Math.Ceiling(entitlementWeeks); weekNumber++) { var weeklyResult = new HolidayPayAccruedWeeklyResult(); maxDays = 0; empDays = 0; if (weekNumber <= wholeWeeks) { maximumEntitlement = statMaxWeeklyPay; employerEntitlement = data.WeeklyWage.GetValueOrDefault(); } if (weekNumber > wholeWeeks) { var weekDayNumber = data.PayDay; // This must be the last (partial) week so loop through each day, checking for working days for (var day = 0; day <= 6; day++) { weekDayNumber++; if (weekDayNumber > (int)DayOfWeek.Saturday) { weekDayNumber = (int)DayOfWeek.Sunday; } if (shiftPattern.Contains(weekDayNumber.ToString())) { if (partWeekDays > 1) { partWeekDays--; maxDays++; empDays++; } else if (partWeekDays > 0) { maxDays = maxDays + partWeekDays; empDays = empDays + partWeekDays; partWeekDays = 0; } } else if (partWeekDays > 0) { maxDays++; } if (day == 6) { maximumEntitlement = (maxDays * statMaxWeeklyPay / 7); employerEntitlement = (empDays * data.WeeklyWage.GetValueOrDefault() / shiftPattern.Count); } } } decimal grossEntitlement = 0.00m; grossEntitlement = await grossEntitlement.GetGrossEntitlement(maximumEntitlement, employerEntitlement); decimal taxDeducted = Math.Round(await grossEntitlement.GetTaxDeducted(taxRate, (bool)data.IsTaxable), 2); decimal niDeducted = Math.Round(await grossEntitlement.GetNIDeducted(niThreshold, niRate, (bool)data.IsTaxable), 2); grossEntitlement = Math.Round(grossEntitlement, 2); weeklyResult.WeekNumber = weekNumber; weeklyResult.MaximumEntitlement = Math.Round(maximumEntitlement, 2); weeklyResult.EmployerEntitlement = Math.Round(employerEntitlement, 2); weeklyResult.GrossEntitlement = grossEntitlement; weeklyResult.IsTaxable = (bool)data.IsTaxable; weeklyResult.TaxDeducted = taxDeducted; weeklyResult.NiDeducted = niDeducted; weeklyResult.NetEntitlement = grossEntitlement - taxDeducted - niDeducted; weeklyResult.PreferentialClaim = grossEntitlement; weeklyResult.NonPreferentialClaim = 0m; weeklyResults.Add(weeklyResult); } calculationResult.WeeklyResults = weeklyResults; return(await Task.FromResult(calculationResult)); }