public StatutoryCalculationResult <SickPayAssessment> Calculate(SickPayAssessment model, IEnumerable <SickPayAssessment> previousSicknotes = null)
        {
            var assessmentCalculation = new StatutoryCalculationResult <SickPayAssessment>();

            assessmentCalculation.Assessment = model;

            if (!model.UpcomingPaymentDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The next Upcoming Payment Date must be provided");
            }

            if (assessmentCalculation.Errors.Any())
            {
                return(assessmentCalculation);
            }

            assessmentCalculation.IsEligible = model.IsEligible;
            var previousSickDays = new List <DateTime>();

            // If we are providing some historical sick notes, extract the actual sick days for each of them
            if (previousSicknotes != null)
            {
                previousSickDays = previousSicknotes.OrderBy(m => m.StartDate).SelectMany(m => GetSickDays(m, true)).Distinct().ToList();
            }

            var scheduledPayments = new List <StatutoryPayment>();

            var datesInRange     = GetSickDays(model, !model.ApplyWaitingDays);
            var nextPaymentDate  = model.UpcomingPaymentDateForPeriod;
            var maxSickDays      = Math.Max(140 - model.PreviousSickDaysTotal, 0);
            var totalDaysClaimed = 0;

            var statPayment = new StatutoryPayment
            {
                ReferenceDate = nextPaymentDate,
                PaymentDate   = nextPaymentDate.AddDays(7),
                Cost          = taxYearConfigurationData.StatutorySickPayDayRate,
                Qty           = 0m
            };

            foreach (var claimDate in datesInRange)
            {
                if (claimDate > nextPaymentDate)
                {
                    scheduledPayments.Add(statPayment);

                    // Next payment is one week away, Fort/Monthly change
                    nextPaymentDate = nextPaymentDate.AddDays(7);

                    statPayment = new StatutoryPayment
                    {
                        ReferenceDate = nextPaymentDate,
                        PaymentDate   = nextPaymentDate.AddDays(7),
                        Cost          = taxYearConfigurationData.StatutorySickPayDayRate,
                        Qty           = 0m
                    };
                }

                // If we have already been paid a sick note for this date, don't pay it twice
                if (previousSickDays.Contains(claimDate))
                {
                    continue;
                }

                // If we have reached our max sick days, don't pay any more
                if (totalDaysClaimed >= maxSickDays)
                {
                    break;
                }

                // We do want to pay this date, woop for the worker
                statPayment.Qty += 1m;
                totalDaysClaimed++;
            }

            // Add the last period
            scheduledPayments.Add(statPayment);

            // Filter out empty schedules
            assessmentCalculation.Payments = scheduledPayments.Where(m => m.Qty > 0).Select(m => m);

            return(assessmentCalculation);
        }
Пример #2
0
        public StatutoryCalculationResult <PaternityPayAssessment> Calculate(PaternityPayAssessment model)
        {
            var assessmentCalculation = new StatutoryCalculationResult <PaternityPayAssessment>();

            if (!model.UpcomingPaymentDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The next Upcoming Payment Date must be provided");
            }
            if (!model.StartDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The Start Date must be provided");
            }
            if (!model.BirthDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The Birth Date must be provided");
            }
            if (model.UpcomingPaymentDate.HasValue && model.StartDate.HasValue && model.UpcomingPaymentDate.Value < model.StartDate.Value)
            {
                assessmentCalculation.AddError(StatutoryValidationError.InvalidUpcomingPayDate, "The upcoming process date cannot be before the Start Date");
            }
            if (model.BirthDate.HasValue && model.StartDate.HasValue && model.StartDate.Value < model.BirthDate.Value)
            {
                assessmentCalculation.AddError(StatutoryValidationError.InvalidStartDate, "Paternity pay cannot be started before the birth date");
            }

            if (assessmentCalculation.Errors.Any())
            {
                return(assessmentCalculation);
            }

            if (!model.EndDate.HasValue)
            {
                model.EndDate = model.StartDate?.AddDays(model.TotalClaimDays);
            }

            assessmentCalculation.IsEligible = model.IsEligible;
            var scheduledPayments = new List <StatutoryPayment>();
            var datesInRange      = model.GetQualifyingDatesInRange();
            var nextPaymentDate   = (model.UpcomingPaymentDate.Value >= datesInRange.First() ? model.UpcomingPaymentDate.Value : model.UpcomingPaymentDate.Value.AddDays(7));

            var statPayment = new StatutoryPayment
            {
                ReferenceDate = nextPaymentDate,
                PaymentDate   = nextPaymentDate.AddDays(7),
                Cost          = taxYearConfigurationData.StatutoryPaternityPayDayRate,
                Qty           = 0m
            };

            foreach (var claimDate in datesInRange)
            {
                if (claimDate > nextPaymentDate)
                {
                    scheduledPayments.Add(statPayment);

                    // Next payment is one week away, Fort/Monthly change
                    nextPaymentDate = nextPaymentDate.AddDays(7);

                    statPayment = new StatutoryPayment
                    {
                        ReferenceDate = nextPaymentDate,
                        PaymentDate   = nextPaymentDate.AddDays(7),
                        Cost          = taxYearConfigurationData.StatutoryPaternityPayDayRate,
                        Qty           = 0m
                    };
                }

                // We do want to pay this date
                statPayment.Qty += 1m;
            }

            // Add the last period
            scheduledPayments.Add(statPayment);

            // Filter out empty schedules
            assessmentCalculation.Payments = scheduledPayments.Where(m => m.Qty > 0).Select(m => m);

            return(assessmentCalculation);
        }
        public StatutoryCalculationResult <MaternityPayAssessment> Calculate(MaternityPayAssessment model)
        {
            var assessmentCalculation = new StatutoryCalculationResult <MaternityPayAssessment>();

            if (!model.UpcomingPaymentDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The next Upcoming Payment Date must be provided");
            }
            if (!model.StartDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The Start Date must be provided");
            }
            if (!model.DueDate.HasValue)
            {
                assessmentCalculation.AddError(StatutoryValidationError.MissingRequiredValue, "The Due Date must be provided");
            }
            if (model.UpcomingPaymentDate.Value < model.StartDate.Value)
            {
                assessmentCalculation.AddError(StatutoryValidationError.InvalidUpcomingPayDate, "The upcoming process date cannot be before the Start Date");
            }

            if (assessmentCalculation.Errors.Any())
            {
                return(assessmentCalculation);
            }

            assessmentCalculation.IsEligible = model.IsEligible;
            if (!model.StartDate.HasValue)
            {
                model.StartDate = model.DueDate;
            }

            // Statutory Maternity Pay ends after 39 weeks
            if (!model.EndDate.HasValue)
            {
                model.EndDate = model.StartDate.Value.AddDays((7 * 39) - 1);
            }

            var scheduledPayments = new List <StatutoryPayment>();

            var datesInRange    = model.GetQualifyingDatesInRange();
            var nextPaymentDate = (model.UpcomingPaymentDate.Value >= datesInRange.First() ? model.UpcomingPaymentDate.Value : model.UpcomingPaymentDate.Value.AddDays(7));

            var belowAverageEarningsCost = (model.AverageWeeklyEarnings * 0.9m) / 7;

            var statPayment = new StatutoryPayment
            {
                ReferenceDate = nextPaymentDate,
                PaymentDate   = nextPaymentDate.AddDays(7),
                Cost          = taxYearConfigurationData.StatutoryMaternityPayDayRate,
                Qty           = 0m
            };

            int totalDaysClaimed = 0;

            foreach (var claimDate in datesInRange)
            {
                totalDaysClaimed++;

                // First 6 weeks we claim the average rate
                if (totalDaysClaimed <= 43)
                {
                    statPayment.Cost = belowAverageEarningsCost;
                    statPayment.IsStatutoryMinimumRate = false;
                }

                if (claimDate > nextPaymentDate)
                {
                    scheduledPayments.Add(statPayment);

                    // Next payment is one week away, Fort/Monthly change
                    nextPaymentDate = nextPaymentDate.AddDays(7);

                    statPayment = new StatutoryPayment
                    {
                        ReferenceDate          = nextPaymentDate,
                        PaymentDate            = nextPaymentDate.AddDays(7),
                        Cost                   = Math.Min(belowAverageEarningsCost, taxYearConfigurationData.StatutoryMaternityPayDayRate),
                        Qty                    = 0m,
                        IsStatutoryMinimumRate = (belowAverageEarningsCost > taxYearConfigurationData.StatutoryMaternityPayDayRate)
                    };
                }

                // If this is the first day of our statutory minimum, create a new holder at the reduced rate
                if (totalDaysClaimed == (7 * 6) + 1)
                {
                    scheduledPayments.Add(statPayment);

                    statPayment = new StatutoryPayment
                    {
                        ReferenceDate          = statPayment.ReferenceDate,
                        PaymentDate            = statPayment.PaymentDate,
                        Cost                   = Math.Min(belowAverageEarningsCost, taxYearConfigurationData.StatutoryMaternityPayDayRate),
                        Qty                    = 0m,
                        IsStatutoryMinimumRate = (belowAverageEarningsCost > taxYearConfigurationData.StatutoryMaternityPayDayRate)
                    };
                }

                // We do want to pay this date
                statPayment.Qty += 1m;
            }

            // Add the last period
            scheduledPayments.Add(statPayment);

            // Filter out empty schedules
            assessmentCalculation.Payments = scheduledPayments.Where(m => m.Qty > 0).Select(m => m);

            return(assessmentCalculation);
        }