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

Block invalid policy combinations #3474

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
23 changes: 21 additions & 2 deletions app/models/claim.rb
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,12 @@ def approvable?
(!decision_made? || awaiting_qa?) &&
!payment_prevented_by_other_claims? &&
attributes_flagged_by_risk_indicator.none? &&
policy.approvable?(self)
policy.approvable?(self) &&
!precluded_by_previous_claim?
end

def approved?
decision_made? && latest_decision.approved?
end

def rejectable?
Expand All @@ -296,7 +301,7 @@ def holdable?
end

def flaggable_for_qa?
decision_made? && latest_decision.approved? && below_min_qa_threshold? && !awaiting_qa? && !qa_completed?
approved? && below_min_qa_threshold? && !awaiting_qa? && !qa_completed?
end

# This method's intention is to help make a decision on whether a claim should
Expand Down Expand Up @@ -570,4 +575,18 @@ def submittable_mobile_details?
def submittable_email_details?
email_address.present? && email_verified == true
end

def claims_from_same_claimant
@claims_from_same_claimant ||= MatchingAttributeFinder.new(self).matching_claims
end

def precluded_by_previous_claim?
approved_claims = claims_from_same_claimant.select(&:approved?)

other_claimed_policies = approved_claims.map(&:policy)

policies_claimed = (other_claimed_policies + [policy]).uniq

Policies.prohibited_policy_combination?(policies_claimed)
end
end
19 changes: 19 additions & 0 deletions app/models/policies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,23 @@ def self.constantize(policy)
def self.with_attribute(attr)
POLICIES.select { |policy| policy::Eligibility.has_attribute?(attr) }
end

# Claimants can't claim for these policy combinations in the same academic
# year
INVALID_POLICY_COMBINATIONS = [
[EarlyCareerPayments, EarlyYearsPayments],
[EarlyCareerPayments, FurtherEducationPayments],
[EarlyCareerPayments, LevellingUpPremiumPayments],
[EarlyYearsPayments, FurtherEducationPayments],
[EarlyYearsPayments, LevellingUpPremiumPayments],
[FurtherEducationPayments, LevellingUpPremiumPayments],
[FurtherEducationPayments, StudentLoans],
[FurtherEducationPayments, InternationalRelocationPayments]
]

def self.prohibited_policy_combination?(policies)
policies.permutation(2).any? do |policy1, policy2|
INVALID_POLICY_COMBINATIONS.include?([policy1, policy2])
end
end
end
9 changes: 9 additions & 0 deletions spec/factories/claims.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
sequence(:email_address) { |n| "person#{n}@example.com" }
sequence(:teacher_reference_number, 1000000) { |n| n }
sequence(:national_insurance_number, 100000) { |n| "QQ#{n}C" }
sequence(:name) { |n| "Name #{n}" }

factory :claim do
started_at { Time.zone.now }
Expand Down Expand Up @@ -67,6 +68,14 @@
national_insurance_number { generate(:national_insurance_number) }
end

trait :random_personal_details do
email_address { generate(:email_address) }
first_name { generate(:name) }
surname { generate(:name) }
date_of_birth { rand(18..65).years.ago.to_date }
national_insurance_number { generate(:national_insurance_number) }
end

trait :eligible do
eligibility_trait { :eligible }
end
Expand Down
17 changes: 10 additions & 7 deletions spec/factories/payments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
end

claims do
personal_details = {
national_insurance_number: generate(:national_insurance_number),
email_address: "email@example.com",
bank_sort_code: "220011",
bank_account_number: "12345678",
eligibility_attributes: {teacher_reference_number: generate(:teacher_reference_number)}
}
personal_details = attributes_for(
:claim,
:random_personal_details,
:with_bank_details
).except(:reference).merge(
eligibility_attributes: {
teacher_reference_number: generate(:teacher_reference_number)
}
)
claim_policies.map do |policy|
association(:claim, :approved, personal_details.merge(policy: policy))
end
end

association(:payroll_run, factory: :payroll_run)

award_amount { claims.map(&:award_amount).compact.sum }
Expand Down
8 changes: 4 additions & 4 deletions spec/features/admin/admin_payroll_runs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
scenario "Service operator creates a payroll run" do
click_on "Payroll"

create(:claim, :approved, policy: Policies::StudentLoans)
create(:claim, :approved, policy: Policies::StudentLoans)
create(:claim, :approved, policy: Policies::EarlyCareerPayments)
create(:claim, :approved, policy: Policies::LevellingUpPremiumPayments)
create(:claim, :approved, :random_personal_details, policy: Policies::StudentLoans)
create(:claim, :approved, :random_personal_details, policy: Policies::StudentLoans)
create(:claim, :approved, :random_personal_details, policy: Policies::EarlyCareerPayments)
create(:claim, :approved, :random_personal_details, policy: Policies::LevellingUpPremiumPayments)

paid_lup_claim = nil
travel_to 2.months.ago do
Expand Down
77 changes: 77 additions & 0 deletions spec/features/admin/claim_with_unpermitted_policy_combo_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require "rails_helper"

RSpec.describe "Claim with unpermitted policy combo" do
context "when one of the claims has been approved" do
it "doesn't allow the admin to approve the other claim" do
create(
:claim,
:approved,
:current_academic_year,
policy: Policies::InternationalRelocationPayments,
email_address: "duplicate@example.com"
)

duplicate_claim = create(
:claim,
:submitted,
:current_academic_year,
policy: Policies::FurtherEducationPayments,
email_address: "duplicate@example.com"
)

sign_in_as_service_operator

visit new_admin_claim_decision_path(duplicate_claim)

approve_option = find("input[type=radio][value=approved]")

expect(approve_option).to be_disabled
end
end

context "when neither of the claims have been approved" do
it "allows the admin to approve one of the claims" do
irp_claim = create(
:claim,
:submitted,
:current_academic_year,
policy: Policies::InternationalRelocationPayments,
email_address: "duplicate@example.com"
)

fe_claim = create(
:claim,
:submitted,
:current_academic_year,
policy: Policies::FurtherEducationPayments,
email_address: "duplicate@example.com"
)

sign_in_as_service_operator

visit new_admin_claim_decision_path(irp_claim)

approve_option = find("input[type=radio][value=approved]")

expect(approve_option).not_to be_disabled

visit new_admin_claim_decision_path(fe_claim)

approve_option = find("input[type=radio][value=approved]")

expect(approve_option).not_to be_disabled

choose "Approve"

fill_in "Decision notes", with: "LGTM"

click_on "Confirm decision"

visit new_admin_claim_decision_path(irp_claim)

approve_option = find("input[type=radio][value=approved]")

expect(approve_option).to be_disabled
end
end
end
2 changes: 1 addition & 1 deletion spec/jobs/payroll_run_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

describe "#perform" do
context "when successful" do
let(:claims) { Policies.all.map { |policy| create(:claim, :approved, policy: policy) } }
let(:claims) { Policies.all.map { |policy| create(:claim, :approved, :random_personal_details, policy: policy) } }
let(:topups) { [] }

before do
Expand Down
48 changes: 48 additions & 0 deletions spec/models/claim_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,54 @@
expect(subject).not_to be_approvable
end
end

context "when the claimant has claimed for a policy that precludes them from this policy" do
subject do
create(
:claim,
:submitted,
:current_academic_year,
policy: Policies::FurtherEducationPayments,
email_address: "duplicate@example.com"
)
end

context "when the other claim has been approved" do
it "is not approvable" do
create(
:claim,
:approved,
:current_academic_year,
policy: Policies::EarlyCareerPayments,
email_address: "duplicate@example.com"
)

expect(subject).not_to be_approvable
end
end

context "when the other claim has not been approved" do
it "is approvable" do
create(
:claim,
:submitted,
:current_academic_year,
policy: Policies::EarlyCareerPayments,
email_address: "duplicate@example.com"
)

create(
:claim,
:rejected,
:current_academic_year,
policy: Policies::EarlyCareerPayments,
email_address: "duplicate@example.com"
)

expect(subject).to be_approvable
end
end
end
end

describe "#rejectable?" do
Expand Down
Loading