コード例 #1
0
        public async Task PerformHolidayPayAccruedCalculationAsync_Return_WhenHolidayStartDate12MonthsBeforeInsolvencyDate()
        {
            // Arrange
            var inputData = new HolidayPayAccruedCalculationRequestModel
            {
                InsolvencyDate           = new DateTime(2019, 1, 14),
                EmpStartDate             = new DateTime(2016, 1, 1),
                DismissalDate            = new DateTime(2018, 11, 30),
                ContractedHolEntitlement = 28,
                HolidayYearStart         = new DateTime(2018, 01, 01),
                IsTaxable    = true,
                PayDay       = (int)DayOfWeek.Saturday,
                ShiftPattern = new List <string> {
                    "1", "2", "3", "4", "5"
                },
                WeeklyWage      = 575.34m,
                DaysCFwd        = 8m,
                DaysTaken       = 10m,
                IpConfirmedDays = 41
            };

            // Act
            var outputData = await Task.FromResult(_holidayPayAccruedCalculationService.PerformHolidayPayAccruedCalculationAsync(inputData, _options));

            // Assert
            outputData.Result.StatutoryMax.Should().Be(508m);
            outputData.Result.HolidaysOwed.Should().Be(28);
            outputData.Result.BusinessDaysInClaim.Should().Be(261.00m);
            outputData.Result.WorkingDaysInClaim.Should().Be(230m);
            outputData.Result.ProRataAccruedDays.Should().Be(22.6743m);
        }
コード例 #2
0
        public static async Task <DateTime> GetHolidayYearEnd(this HolidayPayAccruedCalculationRequestModel model)
        {
            var holidayStart = model.HolidayYearStart.Date;

            if (holidayStart < model.EmpStartDate.Date)
            {
                holidayStart = model.EmpStartDate.Date;
            }

            return(await Task.FromResult(holidayStart.AddMonths(12).AddDays(-1)));
        }
        public async Task GetHolidayYearEnd_Returns_HolidayYearEnd()
        {
            // Arrange
            var model = new HolidayPayAccruedCalculationRequestModel()
            {
                EmpStartDate     = new DateTime(2018, 08, 01),
                HolidayYearStart = new DateTime(2018, 03, 01)
            };

            var expectedHolidayYearEnd = new DateTime(2019, 07, 31);

            // Act
            var result = await model.GetHolidayYearEnd();

            // Assert
            result.Should().Be(expectedHolidayYearEnd);
        }
        public async Task GetHolidayYearStart_Returns_AdjustedHolidayYearStart()
        {
            // Arrange
            var model = new HolidayPayAccruedCalculationRequestModel()
            {
                EmpStartDate     = new DateTime(2017, 08, 22),
                HolidayYearStart = new DateTime(2018, 01, 01)
            };

            var expectedAdjEmpStartDate = new DateTime(2018, 01, 01);

            // Act
            var result = await model.GetHolidayYearStart();

            // Assert
            result.Should().Be(expectedAdjEmpStartDate);
        }
コード例 #5
0
        public async Task PerformHolidayPayAccruedCalculationAsync_Return_PartialDay3()
        {
            // Arrange
            var inputData = new HolidayPayAccruedCalculationRequestModel
            {
                InsolvencyDate           = new DateTime(2019, 10, 22),
                EmpStartDate             = new DateTime(2010, 10, 22),
                DismissalDate            = new DateTime(2019, 10, 22),
                ContractedHolEntitlement = 28,
                HolidayYearStart         = new DateTime(2019, 01, 01),
                IsTaxable    = true,
                PayDay       = (int)DayOfWeek.Friday,
                ShiftPattern = new List <string> {
                    "1", "3", "4"
                },
                WeeklyWage      = 800m,
                DaysCFwd        = 0m,
                DaysTaken       = 0m,
                IpConfirmedDays = 3m
            };

            // Act
            var outputData = await Task.FromResult(_holidayPayAccruedCalculationService.PerformHolidayPayAccruedCalculationAsync(inputData, _options));

            // Assert
            outputData.Result.StatutoryMax.Should().Be(525m);
            outputData.Result.HolidaysOwed.Should().Be(28);
            outputData.Result.BusinessDaysInClaim.Should().Be(156m);
            outputData.Result.WorkingDaysInClaim.Should().Be(126m);
            outputData.Result.ProRataAccruedDays.Should().Be(3m);

            outputData.Result.WeeklyResults.Count.Should().Be(1);
            outputData.Result.WeeklyResults[0].WeekNumber.Should().Be(1);
            outputData.Result.WeeklyResults[0].MaximumEntitlement.Should().Be(525m);
            outputData.Result.WeeklyResults[0].EmployerEntitlement.Should().Be(800m);
            outputData.Result.WeeklyResults[0].GrossEntitlement.Should().Be(525m);
            outputData.Result.WeeklyResults[0].IsTaxable.Should().Be(true);
            outputData.Result.WeeklyResults[0].TaxDeducted.Should().Be(105m);
            outputData.Result.WeeklyResults[0].NiDeducted.Should().Be(41.04m);
            outputData.Result.WeeklyResults[0].NetEntitlement.Should().Be(378.96m);
            outputData.Result.WeeklyResults[0].PreferentialClaim.Should().Be(outputData.Result.WeeklyResults[0].GrossEntitlement);
            outputData.Result.WeeklyResults[0].NonPreferentialClaim.Should().Be(0m);
        }
        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 PostAsync_FailsWithBadRequest_WhenThereIsAHpaValidationError(HolidayPayAccruedCalculationRequestModel hpaRequest, string expectedErrorMessage)
        {
            //Arrange
            var request = new HolidayCalculationRequestModel()
            {
                Hpa = hpaRequest
            };

            var controller = new HolidayController(_service.Object, _mockLogger.Object, _confOptions);

            //Act
            var result = await controller.PostAsync(request);

            //Assert
            var badRequestObjectRequest = result.Should().BeOfType <BadRequestObjectResult>().Subject;

            badRequestObjectRequest.StatusCode.Should().Be((int)System.Net.HttpStatusCode.BadRequest);

            _mockLogger.Verify(x => x.Log(
                                   LogLevel.Error,
                                   It.IsAny <EventId>(),
                                   It.Is <object>(v => v.ToString().Contains(expectedErrorMessage)),
                                   null,
                                   It.IsAny <Func <object, Exception, string> >()
                                   ));
        }
        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));
        }
コード例 #9
0
 public static async Task <DateTime> GetHolidayYearStart(this HolidayPayAccruedCalculationRequestModel model)
 {
     return(await Task.FromResult(model.EmpStartDate.Date > model.HolidayYearStart.Date?model.EmpStartDate.Date : model.HolidayYearStart.Date));
 }