Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAPT 2121/expand topup functionality #3527

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/models/base_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,9 @@ def task_available?(task)
def require_in_progress_update_emails?
true
end

# Overwrite this in the policies if they set a maximum topup amount
def max_topup_amount(claim)
Float::INFINITY
end
end
43 changes: 27 additions & 16 deletions app/models/payroll_run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,42 @@ def payments_count
class LineItem < Struct.new(:id, :award_amount, keyword_init: true); end

def line_items(policy, filter: :all)
scope = Claim
.select(
"
DISTINCT(claims.id),
COALESCE(topups.award_amount, eligibilities.award_amount) AS award_amount
"
)
.with_award_amounts
.left_joins(payments: :topups)
.joins(payments: :payroll_run)
.where(payroll_runs: {id: id})
policies = if policy == :all
Policies::POLICIES
else
[policy]
end

scope = scope.by_policy(policy) unless policy == :all
claims_topped_up_in_payroll_run = Claim
.select("claims.id AS id, topups.award_amount AS award_amount")
.joins(topups: :payment)
.where(payments: {payroll_run_id: id})
.by_policies(policies)

claims_without_topups_in_payroll_run = Claim
.select("claims.id AS id, eligibilities.award_amount AS award_amount")
.with_award_amounts
.joins(:payments)
.where(payments: {payroll_run_id: id})
.where.not(id: claims_topped_up_in_payroll_run.reselect(:id))
.by_policies(policies)

case filter
sql = case filter
when :claims
scope = scope.where(topups: {id: nil})
claims_without_topups_in_payroll_run.to_sql
when :topups
scope = scope.where.not(topups: {id: nil})
claims_topped_up_in_payroll_run.to_sql
else
[
claims_without_topups_in_payroll_run.to_sql,
claims_topped_up_in_payroll_run.to_sql
].join("\nUNION\n")
end

# Claim delegates it's award amount to eligibility, so we want to return
# a non claim object ensuring the award amount is from the topup if there
# is one
ActiveRecord::Base.connection.execute(scope.to_sql).map(&LineItem.method(:new))
ActiveRecord::Base.connection.execute(sql).map(&LineItem.method(:new))
end

def ensure_no_payroll_run_this_month
Expand Down
4 changes: 4 additions & 0 deletions app/models/policies/levelling_up_premium_payments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,9 @@ def selectable_itt_years_for_claim_year(claim_year)
def closed?(claim_year)
claim_year > POLICY_END_YEAR
end

def max_topup_amount(claim)
Award.where(academic_year: claim.academic_year.to_s).maximum(:award_amount)
end
end
end
3 changes: 2 additions & 1 deletion app/models/topup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ def teacher_reference_number
def award_amount_must_be_in_range
return unless award_amount.present?

max = Policies::LevellingUpPremiumPayments::Award.where(academic_year: claim.academic_year.to_s).maximum(:award_amount)
max = claim.policy.max_topup_amount(claim)

total_amount = claim.award_amount_with_topups + award_amount

unless total_amount.between?(1, max)
Expand Down
132 changes: 132 additions & 0 deletions spec/models/payroll_run_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,138 @@
).to eq(204) # 103 + 101
end
end

it "handles claims that have topups in multiple payroll runs" do
claim_1 = create(
:claim,
:approved,
policy: Policies::EarlyCareerPayments,
eligibility_attributes: {
award_amount: 1
}
)

claim_2 = create(
:claim,
:approved,
policy: Policies::EarlyCareerPayments,
eligibility_attributes: {
award_amount: 7
},
date_of_birth: claim_1.date_of_birth,
student_loan_plan: claim_1.student_loan_plan,
bank_sort_code: claim_1.bank_sort_code,
bank_account_number: claim_1.bank_account_number,
building_society_roll_number: claim_1.building_society_roll_number,
national_insurance_number: claim_1.national_insurance_number
)

first_payroll_run = nil

travel_to 2.month.ago do
first_payroll_run = create(:payroll_run)

create(
:payment,
claims: [claim_1],
payroll_run: first_payroll_run
)
end

second_payroll_run = nil

travel_to 1.month.ago do
second_payroll_run = create(:payroll_run)

create(
:payment,
claims: [claim_1, claim_2],
topups: [create(:topup, claim: claim_1, award_amount: 3)],
payroll_run: second_payroll_run
)
end

third_payroll_run = create(:payroll_run)

create(
:payment,
claims: [claim_1],
topups: [create(:topup, claim: claim_1, award_amount: 5)],
payroll_run: third_payroll_run
)

expect(
first_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments)
).to eq(1)

expect(
first_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(1)

expect(
first_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(0)

expect(
first_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments)
).to eq(1)

expect(
first_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(1)

expect(
first_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(0)

expect(
second_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments)
).to eq(10) # topup 3 + claim 7

expect(
second_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(7)

expect(
second_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(3)

expect(
second_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments)
).to eq(2) # topup for claim 1 + claim 2

expect(
second_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(1)

expect(
second_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(1)

expect(
third_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments)
).to eq(5)

expect(
third_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(0)

expect(
third_payroll_run.total_claim_amount_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(5)

expect(
third_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments)
).to eq(1)

expect(
third_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :claims)
).to eq(0)

expect(
third_payroll_run.number_of_claims_for_policy(Policies::EarlyCareerPayments, filter: :topups)
).to eq(1)
end
end

describe ".this_month" do
Expand Down
Loading