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 PerformHolidayTakenNotPaidCalculation(
            HolidayTakenNotPaidCalculationRequestModel requestModel,
            string inputSource,
            decimal maxDaysInCurrentHolidayYear,
            decimal maxDaysInTotal,
            HolidayTakenNotPaidResponseDTO expectedResult
            )
        {
            //Act 1
            var request = new List <HolidayTakenNotPaidCalculationRequestModel>()
            {
                requestModel
            };

            var actualResult1 =
                await _holidayTakenNotPaidCalculationService.PerformCalculationAsync(
                    request, inputSource, maxDaysInCurrentHolidayYear, maxDaysInTotal, new DateTime(2018, 1, 1), _options);

            //Assert 1
            actualResult1.InputSource.Should().Be(expectedResult.InputSource);
            actualResult1.StatutoryMax.Should().Be(expectedResult.StatutoryMax);
            actualResult1.WeeklyResult.Count.Should().Be(expectedResult.WeeklyResult.Count);
            for (var expectedCalcResultIndex = 0;
                 expectedCalcResultIndex < expectedResult.WeeklyResult.Count;
                 expectedCalcResultIndex++)
            {
                for (var actualCalcResultIndex = expectedCalcResultIndex;
                     actualCalcResultIndex <= expectedCalcResultIndex;
                     actualCalcResultIndex++)
                {
                    actualResult1.WeeklyResult[expectedCalcResultIndex].WeekNumber.Should()
                    .Be(expectedResult.WeeklyResult[expectedCalcResultIndex].WeekNumber);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].PayDate.Should()
                    .Be(expectedResult.WeeklyResult[expectedCalcResultIndex].PayDate);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].MaximumEntitlement.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].MaximumEntitlement);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].EmployerEntitlement.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].EmployerEntitlement);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].GrossEntitlement.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].GrossEntitlement);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].IsTaxable.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].IsTaxable);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].TaxDeducted.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].TaxDeducted);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].NiDeducted.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].NiDeducted);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].NetEntitlement.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].NetEntitlement);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].MaximumDays.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].MaximumDays);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].EmploymentDays.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].EmploymentDays);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].MaximumEntitlementIn4MonthPeriod.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].MaximumEntitlementIn4MonthPeriod);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].EmployerEntitlementIn4MonthPeriod.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].EmployerEntitlementIn4MonthPeriod);
                    actualResult1.WeeklyResult[expectedCalcResultIndex].GrossEntitlementIn4Months.Should().Be(
                        expectedResult.WeeklyResult[expectedCalcResultIndex].GrossEntitlementIn4Months);
                }
            }
        }
        public async Task PerformHolidayCalculationAsync_PerformsHpaAndHtnpCalculationsWithNoHpaAndRp14aSelected()
        {
            // Arrange
            var shiftPattern = new List <string> {
                "1", "2", "3", "4", "5"
            };

            var htnpRequest = new List <HolidayTakenNotPaidCalculationRequestModel>()
            {
                new HolidayTakenNotPaidCalculationRequestModel(InputSource.Rp14a, 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.Rp1, 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, 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)
                }
            };

            var htnpResponseRp14a = new HolidayTakenNotPaidResponseDTO()
            {
                InputSource  = InputSource.Rp14a,
                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),
                }
            };

            _htnpService.Setup(x => x.PerformCalculationAsync(htnpRequest, InputSource.Rp1, It.IsAny <decimal>(), It.IsAny <decimal>(), It.IsAny <DateTime?>(), _options, null)).ReturnsAsync(htnpResponseRp1);
            _htnpService.Setup(x => x.PerformCalculationAsync(htnpRequest, InputSource.Rp14a, It.IsAny <decimal>(), It.IsAny <decimal>(), It.IsAny <DateTime?>(), _options, null)).ReturnsAsync(htnpResponseRp14a);

            var request = new HolidayCalculationRequestModel()
            {
                Hpa  = null,
                Htnp = htnpRequest
            };

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

            // Assert
            results.Hpa.Should().BeNull();
            results.Htnp.Should().NotBeNull();
            results.Htnp.SelectedInputSource.Should().Be(InputSource.Rp14a);

            _htnpService.Verify(m => m.PerformCalculationAsync(
                                    It.IsAny <List <HolidayTakenNotPaidCalculationRequestModel> >(),
                                    InputSource.Rp1,
                                    0m,
                                    0m,
                                    null,
                                    It.IsAny <IOptions <ConfigLookupRoot> >(), null), Times.Once);
            _htnpService.Verify(m => m.PerformCalculationAsync(
                                    htnpRequest,
                                    InputSource.Rp14a,
                                    0m,
                                    30m,
                                    null,
                                    It.IsAny <IOptions <ConfigLookupRoot> >(), It.IsAny <TraceInfo>()), Times.Once);
        }
Esempio n. 4
0
        public async Task <HolidayTakenNotPaidResponseDTO> PerformCalculationAsync(
            List <HolidayTakenNotPaidCalculationRequestModel> data,
            string inputSource,
            decimal maxDaysInCurrentHolidayYear,
            decimal maxDaysInTotal,
            DateTime?holidayYearStart,
            IOptions <ConfigLookupRoot> options, TraceInfo traceInfo = null)
        {
            var statutoryMax = ConfigValueLookupHelper.GetStatutoryMax(options, data.First().DismissalDate);

            var calculationResult = new HolidayTakenNotPaidResponseDTO();

            calculationResult.StatutoryMax = Math.Round(statutoryMax, 2);
            calculationResult.InputSource  = inputSource;

            var firstRequest = data.FirstOrDefault(r => r.InputSource == inputSource);

            if (firstRequest != null)
            {
                var tweleveMonthsPrior = firstRequest.InsolvencyDate.Date.AddMonths(-12).AddDays(1);
                var htnpEndDate        = firstRequest.DismissalDate.Date < firstRequest.InsolvencyDate.Date ? firstRequest.DismissalDate.Date : firstRequest.InsolvencyDate.Date;

                var weeks = new List <Week>();

                if (holidayYearStart.HasValue)
                {
                    var htnpDaysInCurrentHolidayYear = await data.GetHTNPDays(inputSource, holidayYearStart.Value.Date, htnpEndDate);

                    var htnpDaysIn12MonthsPrior = await data.GetHTNPDays(inputSource, tweleveMonthsPrior, holidayYearStart.Value.Date.AddDays(-1));

                    await SelectDaysAndConvertToWeeks(weeks, htnpDaysInCurrentHolidayYear, firstRequest, maxDaysInCurrentHolidayYear);

                    var numHtnpDaysSelected = weeks.Where(x => x.IsSelected).Sum(x => x.EmploymentDays);
                    await SelectDaysAndConvertToWeeks(weeks, htnpDaysIn12MonthsPrior, firstRequest, maxDaysInTotal - numHtnpDaysSelected);
                }
                else
                {
                    var htnpDays = await data.GetHTNPDays(inputSource, tweleveMonthsPrior, htnpEndDate);
                    await SelectDaysAndConvertToWeeks(weeks, htnpDays, firstRequest, maxDaysInTotal);
                }

                DateTime prefPeriodStartDate = firstRequest.InsolvencyDate.Date.AddMonths(-4);
                DateTime prefPeriodEndDate   = (firstRequest.DismissalDate < firstRequest.InsolvencyDate) ? firstRequest.DismissalDate.Date : firstRequest.InsolvencyDate.Date;

                // generate the output weeks
                int     weekNum    = 1;
                decimal total_days = 0.00m;

                foreach (var week in weeks.OrderBy(x => x.PayDate).ThenBy(x => x.IsSelected))
                {
                    var weekStartDate = week.PayDate.AddDays(-6);
                    var maximumDays   = await weekStartDate.GetNumDaysInIntersectionOfTwoRanges(week.PayDate, DateTime.MinValue.Date, firstRequest.DismissalDate.Date);

                    var maximumDaysInPrefPeriod = await weekStartDate.GetNumDaysInIntersectionOfTwoRanges(week.PayDate, prefPeriodStartDate, prefPeriodEndDate);

                    //calculate Employer Liability for week
                    var employerEntitlement             = firstRequest.WeeklyWage / firstRequest.ShiftPattern.Count * week.EmploymentDays;
                    var employerEntitlementInPrefPeriod = firstRequest.WeeklyWage / firstRequest.ShiftPattern.Count * week.EmploymentDaysInPrefPeriod;
                    var maximumEntitlement             = statutoryMax / 7 * maximumDays;
                    var maximumEntitlementInPrefPeriod = statutoryMax / 7 * maximumDaysInPrefPeriod;

                    var grossEntitlement = Math.Min(maximumEntitlement, employerEntitlement);
                    var taxRate          = ConfigValueLookupHelper.GetTaxRate(options, DateTime.Now);
                    var taxDeducated     = Math.Round(await grossEntitlement.GetTaxDeducted(taxRate, firstRequest.IsTaxable), 2);
                    var niThreshold      = ConfigValueLookupHelper.GetNIThreshold(options, DateTime.Now);
                    var niRate           = ConfigValueLookupHelper.GetNIRate(options, DateTime.Now);
                    var niDeducted       = Math.Round(await grossEntitlement.GetNIDeducted(niThreshold, niRate, firstRequest.IsTaxable), 2);

                    grossEntitlement = Math.Round(grossEntitlement, 2);
                    var netLiability = await grossEntitlement.GetNetLiability(taxDeducated, niDeducted);

                    total_days += week.EmploymentDays;
                    calculationResult.WeeklyResult.Add(new HolidayTakenNotPaidWeeklyResult()
                    {
                        WeekNumber          = weekNum++,
                        PayDate             = week.PayDate,
                        IsSelected          = week.IsSelected,
                        MaximumEntitlement  = Math.Round(maximumEntitlement, 2),
                        EmployerEntitlement = Math.Round(employerEntitlement, 2),
                        GrossEntitlement    = grossEntitlement,
                        IsTaxable           = firstRequest.IsTaxable,
                        TaxDeducted         = taxDeducated,
                        NiDeducted          = niDeducted,
                        NetEntitlement      = netLiability,
                        MaximumDays         = maximumDays,
                        EmploymentDays      = Math.Round(week.EmploymentDays, 4),
                        MaximumEntitlementIn4MonthPeriod  = Math.Round(maximumEntitlementInPrefPeriod, 2),
                        EmployerEntitlementIn4MonthPeriod = Math.Round(employerEntitlementInPrefPeriod, 2),
                        GrossEntitlementIn4Months         = Math.Round(Math.Min(maximumEntitlementInPrefPeriod, employerEntitlementInPrefPeriod), 2),
                    });
                }
                foreach (var req in data.Where(x => x.InputSource == inputSource))
                {
                    traceInfo?.Dates.Add(new TraceInfoDate
                    {
                        StartDate = req.UnpaidPeriodFrom,
                        EndDate   = req.UnpaidPeriodTo,
                    });
                }
                if (traceInfo != null)
                {
                    traceInfo.NumberOfDays = total_days;
                }
            }
            return(await Task.FromResult(calculationResult));
        }