Skip to content

Commit

Permalink
Merge pull request #2051 from alphagov/apply-working-pattern-to-linke…
Browse files Browse the repository at this point in the history
…d-period-of-sickness-in-calculate-statutory-sick-pay-v2

Apply working pattern to linked period of sickness in calculate-statutory-sick-pay (without change in order of questions)
  • Loading branch information
floehopper committed Nov 5, 2015
2 parents ad38d97 + 8276220 commit 642c4f6
Show file tree
Hide file tree
Showing 4,556 changed files with 139,185 additions and 42,387 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
93 changes: 50 additions & 43 deletions lib/smart_answer/calculators/statutory_sick_pay_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module SmartAnswer::Calculators
class StatutorySickPayCalculator
attr_reader :waiting_days, :normal_workdays, :pattern_days

def initialize(prev_sick_days, sick_start_date, sick_end_date, days_of_the_week_worked)
def initialize(prev_sick_days:, sick_start_date:, sick_end_date:, days_of_the_week_worked:)
@prev_sick_days = prev_sick_days
@waiting_days = (@prev_sick_days >= 3 ? 0 : 3 - @prev_sick_days)
@sick_start_date = sick_start_date
Expand All @@ -18,10 +18,6 @@ def self.lower_earning_limit_on(date)
SmartAnswer::Calculators::RatesQuery.new('statutory_sick_pay').rates(date).lower_earning_limit_rate
end

def weekly_rate_on(date)
SmartAnswer::Calculators::RatesQuery.new('statutory_sick_pay').rates(date).ssp_weekly_rate
end

def self.months_between(start_date, end_date)
end_month = end_date.month
current_month = start_date.next_month
Expand Down Expand Up @@ -55,24 +51,54 @@ def daily_rate_from_weekly(weekly_rate, pattern_days)
pattern_days > 0 ? ((((weekly_rate / pattern_days) * 10000).round(6).floor) / 10000.0) : 0.0000
end

def max_days_that_can_be_paid
(28 * @pattern_days).round(10)
def days_paid
[days_to_pay, days_that_can_be_paid_for_this_period].min
end

def days_paid_in_linked_period
if @prev_sick_days > 3
@prev_sick_days - 3
def days_that_can_be_paid_for_this_period
[max_days_that_can_be_paid - days_paid_in_linked_period, 0].max
end

def formatted_sick_pay_weekly_amounts
weekly_payments.map { |week|
[week.first.strftime("%e %B %Y"), sprintf("£%.2f", week.second)].join("|")
}.join("\n")
end

def ssp_payment
BigDecimal.new(weekly_payments.map(&:last).sum.round(10).to_s).round(2, BigDecimal::ROUND_UP).to_f
end

def self.contractual_earnings_awe(pay, days_worked)
(pay / BigDecimal.new(days_worked.to_s) * 7).round(2)
end

def self.total_earnings_awe(pay, days_worked)
if days_worked % 7 == 0
(pay / (days_worked / 7)).round(2)
else
0
(pay / BigDecimal.new(days_worked.to_s) * 7).round(2)
end
end

def days_paid
[days_to_pay, days_that_can_be_paid_for_this_period].min
def self.dates_matching_pattern(from:, to:, pattern:)
dates = from..to
# create an array of all dates that would have been normal workdays
matching_dates = []
dates.each do |d|
matching_dates << d if pattern.include?(d.wday.to_s)
end
matching_dates
end

def days_that_can_be_paid_for_this_period
[max_days_that_can_be_paid - days_paid_in_linked_period, 0].max
private

def weekly_rate_on(date)
SmartAnswer::Calculators::RatesQuery.new('statutory_sick_pay').rates(date).ssp_weekly_rate
end

def max_days_that_can_be_paid
(28 * @pattern_days).round(10)
end

def days_to_pay
Expand All @@ -88,16 +114,6 @@ def sick_pay_weekly_dates
(@sick_start_date..ssp_week_end).select { |day| day.wday == 6 }
end

def formatted_sick_pay_weekly_amounts
weekly_payments.map { |week|
[week.first.strftime("%e %B %Y"), sprintf("£%.2f", week.second)].join("|")
}.join("\n")
end

def ssp_payment
BigDecimal.new(weekly_payments.map(&:last).sum.round(10).to_s).round(2, BigDecimal::ROUND_UP).to_f
end

def weekly_payments
payments = sick_pay_weekly_dates.map { |date| [date, weekly_payment(date)] }
payments.pop while payments.any? and payments.last.last == 0
Expand All @@ -112,29 +128,20 @@ def weekly_payment(week_start_date)
BigDecimal.new(pay.round(10).to_s).round(2, BigDecimal::ROUND_UP).to_f
end

def self.contractual_earnings_awe(pay, days_worked)
(pay / BigDecimal.new(days_worked.to_s) * 7).round(2)
end

def self.total_earnings_awe(pay, days_worked)
if days_worked % 7 == 0
(pay / (days_worked / 7)).round(2)
def days_paid_in_linked_period
if @prev_sick_days > 3
@prev_sick_days - 3
else
(pay / BigDecimal.new(days_worked.to_s) * 7).round(2)
0
end
end

private
def init_normal_workdays_missed(days_of_the_week_worked)
dates = @sick_start_date..@sick_end_date
# create an array of all dates that would have been normal workdays
normal_workdays_missed = []
dates.each do |d|
if days_of_the_week_worked.include?(d.wday.to_s)
normal_workdays_missed << d
end
end
normal_workdays_missed
self.class.dates_matching_pattern(
from: @sick_start_date,
to: @sick_end_date,
pattern: days_of_the_week_worked
)
end

def init_payable_days
Expand Down
64 changes: 42 additions & 22 deletions lib/smart_answer_flows/calculate-statutory-sick-pay.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module SmartAnswer
class CalculateStatutorySickPayFlow < Flow
MINIMUM_NUMBER_OF_DAYS_IN_PERIOD_OF_INCAPACITY_TO_WORK = 4

def define
content_id "1c676a9e-0424-4ebb-bab8-d8cb8d2fc6f8"
name 'calculate-statutory-sick-pay'
Expand All @@ -11,7 +13,7 @@ def define
checkbox_question :is_your_employee_getting? do
option :statutory_maternity_pay
option :maternity_allowance
option :ordinary_statutory_paternity_pay
option :statutory_paternity_pay
option :statutory_adoption_pay
option :additional_statutory_paternity_pay

Expand All @@ -20,10 +22,10 @@ def define
PhraseList.new(:ssp_link)
end
calculate :paternity_maternity_warning do |response|
(response.split(",") & %w{ordinary_statutory_paternity_pay additional_statutory_paternity_pay statutory_adoption_pay}).any?
(response.split(",") & %w{statutory_paternity_pay additional_statutory_paternity_pay statutory_adoption_pay}).any?
end
next_node_if(:employee_tell_within_limit?,
response_is_one_of(%w{ordinary_statutory_paternity_pay additional_statutory_paternity_pay statutory_adoption_pay none}))
response_is_one_of(%w{statutory_paternity_pay additional_statutory_paternity_pay statutory_adoption_pay none}))
next_node(:already_getting_maternity)
end

Expand Down Expand Up @@ -91,13 +93,14 @@ def define
end

next_node_calculation(:days_sick) do |response|
start_date = sick_start_date
last_day_sick = response
(last_day_sick - start_date).to_i + 1
period = DateRange.new(begins_on: sick_start_date, ends_on: response)
period.number_of_days
end

validate { days_sick >= 1 }
next_node_if(:has_linked_sickness?) { days_sick > 3 }
next_node_if(:has_linked_sickness?) do
days_sick >= MINIMUM_NUMBER_OF_DAYS_IN_PERIOD_OF_INCAPACITY_TO_WORK
end
next_node(:must_be_sick_for_4_days)
end

Expand All @@ -106,6 +109,8 @@ def define
option :yes
option :no

save_input_as :has_linked_sickness

permitted_next_nodes = [
:linked_sickness_start_date?,
:paid_at_least_8_weeks?
Expand Down Expand Up @@ -152,14 +157,13 @@ def define
sick_end_date_for_awe > furthest_allowed_date
end

next_node_calculation :prior_sick_days do |response|
start_date = sick_start_date_for_awe
last_day_sick = response
(last_day_sick - start_date).to_i + 1
validate :must_be_at_least_1_day_before_first_sick_day do
sick_end_date_for_awe < sick_start_date - 1
end

validate :start_before_end do
prior_sick_days >= 1
validate :must_be_valid_period_of_incapacity_for_work do |response|
period = DateRange.new(begins_on: sick_start_date_for_awe, ends_on: response)
period.number_of_days >= MINIMUM_NUMBER_OF_DAYS_IN_PERIOD_OF_INCAPACITY_TO_WORK
end

next_node(:paid_at_least_8_weeks?)
Expand All @@ -180,9 +184,9 @@ def define
next_node(permitted: permitted_next_nodes) do |response|
case response
when 'eight_weeks_more', 'before_payday'
:how_often_pay_employee_pay_patterns? # Question 5.2
:how_often_pay_employee_pay_patterns? # Question 7.2
when 'eight_weeks_less'
:total_earnings_before_sick_period? # Question 8
:total_earnings_before_sick_period? # Question 10
end
end
end
Expand All @@ -197,8 +201,8 @@ def define

save_input_as :pay_pattern

next_node_if(:last_payday_before_sickness?, variable_matches(:eight_weeks_earnings, 'eight_weeks_more')) # Question 6
next_node(:pay_amount_if_not_sick?) # Question 7
next_node_if(:last_payday_before_sickness?, variable_matches(:eight_weeks_earnings, 'eight_weeks_more')) # Question 8
next_node(:pay_amount_if_not_sick?) # Question 9
end

# Question 8
Expand Down Expand Up @@ -299,7 +303,7 @@ def define
next_node :usual_work_days?
end

# Q11
# Question 11
checkbox_question :usual_work_days? do
%w{1 2 3 4 5 6 0}.each { |n| option n.to_s }

Expand All @@ -312,23 +316,39 @@ def define
end

calculate :formatted_sick_pay_weekly_amounts do |response|
calculator = Calculators::StatutorySickPayCalculator.new(prior_sick_days.to_i, sick_start_date, sick_end_date, response.split(","))

if calculator.ssp_payment > 0
calculator.formatted_sick_pay_weekly_amounts
else
""
end
end

next_node_calculation(:prior_sick_days) do |response|
if has_linked_sickness == 'yes'
prev_sick_days = Calculators::StatutorySickPayCalculator.dates_matching_pattern(
from: sick_start_date_for_awe,
to: sick_end_date_for_awe,
pattern: response.split(",")
)
prev_sick_days.length
else
0
end
end

next_node_calculation(:calculator) do |response|
Calculators::StatutorySickPayCalculator.new(prior_sick_days.to_i, sick_start_date, sick_end_date, response.split(","))
Calculators::StatutorySickPayCalculator.new(
prev_sick_days: prior_sick_days,
sick_start_date: sick_start_date,
sick_end_date: sick_end_date,
days_of_the_week_worked: response.split(",")
)
end

# Answer 8
next_node_if(:maximum_entitlement_reached) do |response|
days_worked = response.split(',').size
prior_sick_days and prior_sick_days.to_i >= (days_worked * 28 + 3)
prior_sick_days >= (days_worked * 28 + 3)
end

# Answer 6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
##What you need to know

<% if paternity_maternity_warning %>
^ Your employee will not be able to collect Ordinary Statutory Paternity Pay or Statutory Adoption Pay while collecting Statutory Sick Pay. ^
^ Your employee will not be able to collect Statutory Paternity Pay or Statutory Adoption Pay while collecting Statutory Sick Pay. ^

<% end %>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ en-GB:
options:
statutory_maternity_pay: Statutory Maternity Pay
maternity_allowance: Maternity Allowance
ordinary_statutory_paternity_pay: Ordinary Statutory Paternity Pay
statutory_paternity_pay: Statutory Paternity Pay
statutory_adoption_pay: Statutory Adoption Pay
additional_statutory_paternity_pay: Additional Statutory Paternity Pay

Expand Down Expand Up @@ -64,8 +64,9 @@ en-GB:
# Question 6.2
linked_sickness_end_date?:
title: Enter the end date for this linked period of sickness.
start_before_end: End date should be on or after start date
must_be_valid_period_of_incapacity_for_work: The linked period of sickness must be at least 4 calendar days long.
must_be_within_eight_weeks: You need to enter a date within 8 weeks of the current period of sickness or it isn't a linked period of sickness.
must_be_at_least_1_day_before_first_sick_day: You need to enter a date at least 1 day before the start of the current period of sickness or it isn't a separate linked period of sickness.

# Q7.1
paid_at_least_8_weeks?:
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 642c4f6

Please sign in to comment.