Skip to content

Commit

Permalink
Merge pull request #3183 from DFE-Digital/LUPEYALPHA-1031-student-loa…
Browse files Browse the repository at this point in the history
…n-task-no-data

[LUPEYALPHA-1031] Cope with student loan data with "No data" rows. Remove invalid match logic
  • Loading branch information
alkesh authored Sep 23, 2024
2 parents 2d1d555 + afc065e commit 0403b83
Show file tree
Hide file tree
Showing 16 changed files with 407 additions and 95 deletions.
40 changes: 14 additions & 26 deletions app/models/automated_checks/claim_verifiers/student_loan_plan.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def perform
return unless claim.submitted_without_slc_data?
return unless awaiting_task?

no_data || invalid_match || complete_match
no_student_loan_data_entry || student_loan_data_exists
end

private
Expand All @@ -35,28 +35,16 @@ def awaiting_task?
claim.tasks.where(name: TASK_NAME).count.zero?
end

def no_data
def no_student_loan_data_entry
return if student_loans_data.any?

create_task(match: nil)
end

def invalid_match
return if student_loan_plan_type_exact_match?

create_task(match: :none, passed: false)
end

def complete_match
return unless student_loan_plan_type_exact_match?

def student_loan_data_exists
create_task(match: :all, passed: true)
end

def student_loan_plan_type_exact_match?
claim_student_loan_plan == slc_repaying_plan_types
end

def create_task(match:, passed: nil)
task = claim.tasks.build(
{
Expand All @@ -75,21 +63,21 @@ def create_task(match:, passed: nil)
task
end

def create_note(match:)
body = case match
when nil
"[SLC Student loan plan] - No data"
when :none
sprintf "[SLC Student loan plan] - The plan type on the claim (%s) didn't match the SLC value (%s)",
claim_student_loan_plan&.humanize,
slc_repaying_plan_types&.humanize
when :all
"[SLC Student loan plan] - Matched"
def note_body(match:)
prefix = "[SLC Student loan plan]"
return "#{prefix} - No data" unless match

if slc_repaying_plan_types
"#{prefix} - Matched - has a student loan"
else
"#{prefix} - Matched - does not have a student loan"
end
end

def create_note(match:)
claim.notes.create!(
{
body: body,
body: note_body(match:),
label: TASK_NAME,
created_by: admin_user
}
Expand Down
4 changes: 2 additions & 2 deletions app/models/claim.rb
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ class Claim < ApplicationRecord

validates :academic_year_before_type_cast, format: {with: AcademicYear::ACADEMIC_YEAR_REGEXP}

validates :has_student_loan, on: [:"student-loan"], inclusion: {in: [true, false]}
validates :has_student_loan, on: [:"student-loan"], inclusion: {in: [true, false]}, allow_nil: true
validates :student_loan_plan, inclusion: {in: STUDENT_LOAN_PLAN_OPTIONS}, allow_nil: true
validates :student_loan_plan, on: [:"student-loan", :amendment], presence: {message: "Enter a valid student loan plan"}
validates :student_loan_plan, on: [:amendment], presence: {message: "Enter a valid student loan plan"}

# TODO: remove when a form object is created for email-address
validates :email_address, on: [:submit], presence: {message: "Enter an email address"}
Expand Down
3 changes: 2 additions & 1 deletion app/models/claim_student_loan_details_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def update_claim_with_latest_data
eligibility.update!(eligibility_student_loan_attributes) if claim.has_tslr_policy?

claim.assign_attributes(claim_student_loan_attributes)

claim.save!(context: :"student-loan")
end
rescue => e
Expand All @@ -32,7 +33,7 @@ def eligibility_student_loan_attributes

def claim_student_loan_attributes
{
has_student_loan: student_loans_data.found_data?,
has_student_loan: student_loans_data.has_student_loan?,
student_loan_plan: student_loans_data.student_loan_plan
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def save!
# held before submission; after submission, the
# `submitted_using_slc_data` value must not change
journey_session.answers.assign_attributes(
has_student_loan: student_loans_data.found_data?,
has_student_loan: student_loans_data.has_student_loan?,
student_loan_plan: student_loans_data.student_loan_plan,
submitted_using_slc_data: student_loans_data.found_data?
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ def not_taught_enough?
answers.mostly_performed_leadership_duties == true
end

# checks two scenarios: (1) they do not have a student loan, (2) they have a student loan but the repayment amount is zero
def made_zero_repayments?
return true if answers.has_student_loan == false

answers.has_student_loan == true && answers.student_loan_repayment_amount == 0
end
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/student_loans_data_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ def found_data?
student_loans_data.any?
end

def has_student_loan?
return unless found_data?

student_loans_data.repaying_plan_types.present?
end

def student_loan_repayment_amount
student_loans_data.total_repayment_amount
end

def student_loan_plan
return nil if student_loans_data.repaying_plan_types.nil? && !found_data?

student_loans_data.repaying_plan_types || Claim::NO_STUDENT_LOAN
end

Expand Down
6 changes: 6 additions & 0 deletions spec/factories/student_loans_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@
no_of_plans_currently_repaying { 1 }
plan_type_of_deduction { 1 }
amount { 150 }

trait :no_student_loan do
no_of_plans_currently_repaying { nil }
plan_type_of_deduction { nil }
amount { 0 }
end
end
end
143 changes: 143 additions & 0 deletions spec/features/admin/upload_slc_data_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
require "rails_helper"

RSpec.feature "Upload SLC data" do
before do
create(:journey_configuration, :student_loans) # used by StudentLoanAmountCheckJob
create(:journey_configuration, :early_career_payments)
sign_in_as_service_operator
end

let!(:sl_claim_with_slc_data_no_student_loan) {
create(:claim, :submitted, policy: Policies::StudentLoans, academic_year: AcademicYear.current,
eligibility: build(:student_loans_eligibility, :eligible, student_loan_repayment_amount: 0),
has_student_loan: false, student_loan_plan: "not_applicable", submitted_using_slc_data: false)
}
let!(:sl_claim_with_slc_data_with_student_loan) {
create(:claim, :submitted, policy: Policies::StudentLoans, academic_year: AcademicYear.current,
eligibility: build(:student_loans_eligibility, :eligible, student_loan_repayment_amount: 100),
has_student_loan: true, student_loan_plan: "plan_1", submitted_using_slc_data: false)
}
let!(:sl_claim_no_slc_data) {
create(:claim, :submitted, policy: Policies::StudentLoans, academic_year: AcademicYear.current,
eligibility: build(:student_loans_eligibility, :eligible, student_loan_repayment_amount: 0),
has_student_loan: false, student_loan_plan: "not_applicable", submitted_using_slc_data: false)
}

let!(:ecp_claim_with_slc_data_no_student_loan) {
create(:claim, :submitted, policy: Policies::EarlyCareerPayments,
eligibility: build(:early_career_payments_eligibility, :eligible),
has_student_loan: nil, student_loan_plan: nil, submitted_using_slc_data: false)
}
let!(:ecp_claim_with_slc_data_with_student_loan) {
create(:claim, :submitted, policy: Policies::EarlyCareerPayments,
eligibility: build(:early_career_payments_eligibility, :eligible),
has_student_loan: true, student_loan_plan: "plan_1", submitted_using_slc_data: false)
}
let!(:ecp_claim_no_slc_data) {
create(:claim, :submitted, policy: Policies::EarlyCareerPayments,
eligibility: build(:early_career_payments_eligibility, :eligible),
has_student_loan: false, student_loan_plan: "not_applicable", submitted_using_slc_data: false)
}

scenario "automated task to verify student loan plan" do
visit admin_claims_path
click_link "Upload SLC data"
attach_file "file", slc_data_csv_file.path
perform_enqueued_jobs do
click_button "Upload"
end
expect(page).to have_content "SLC file uploaded and queued to be imported"
expect(StudentLoansData.count).to eq 4

# Student Loans

click_link sl_claim_with_slc_data_no_student_loan.reference
expect(page).to have_content "Student loan amount"
within "li.student_loan_amount" do
expect(page).to have_content "No match"
end
expect(sl_claim_with_slc_data_no_student_loan.reload.student_loan_plan).to eq "not_applicable"
expect(sl_claim_with_slc_data_no_student_loan.has_student_loan).to be false
expect(sl_claim_with_slc_data_no_student_loan.eligibility.student_loan_repayment_amount).to eq 0

visit admin_claims_path
click_link ecp_claim_with_slc_data_with_student_loan.reference
expect(page).not_to have_content "Student loan amount"
expect(sl_claim_with_slc_data_with_student_loan.reload.student_loan_plan).to eq "plan_1"
expect(sl_claim_with_slc_data_with_student_loan.has_student_loan).to eq true
expect(sl_claim_with_slc_data_with_student_loan.eligibility.student_loan_repayment_amount).to eq 100

visit admin_claims_path
click_link sl_claim_no_slc_data.reference
expect(page).to have_content "Student loan amount"
within "li.student_loan_amount" do
expect(page).to have_content "No data"
end
expect(sl_claim_no_slc_data.reload.student_loan_plan).to be nil
expect(sl_claim_no_slc_data.has_student_loan).to be nil
expect(sl_claim_no_slc_data.eligibility.student_loan_repayment_amount).to eq 0

# Early Career Payments

visit admin_claims_path
click_link ecp_claim_with_slc_data_no_student_loan.reference
expect(page).to have_content "Student loan plan"
within "li.student_loan_plan" do
expect(page).to have_content "Passed"
end
expect(ecp_claim_with_slc_data_no_student_loan.reload.student_loan_plan).to eq "not_applicable"
expect(ecp_claim_with_slc_data_no_student_loan.has_student_loan).to be false

visit admin_claims_path
click_link ecp_claim_with_slc_data_with_student_loan.reference
expect(page).to have_content "Student loan plan"
within "li.student_loan_plan" do
expect(page).to have_content "Passed"
end
expect(ecp_claim_with_slc_data_with_student_loan.reload.student_loan_plan).to eq "plan_1"
expect(ecp_claim_with_slc_data_with_student_loan.has_student_loan).to eq true

visit admin_claims_path
click_link ecp_claim_no_slc_data.reference
expect(page).to have_content "Student loan plan"
within "li.student_loan_plan" do
expect(page).to have_content "No data"
end
expect(ecp_claim_no_slc_data.reload.student_loan_plan).to be nil # this was "not_applicable" before LUPEYALPHA-1031
expect(ecp_claim_no_slc_data.has_student_loan).to be nil # this was false before LUPEYALPHA-1031
end

def slc_data_csv_file
return @slc_data_csv_file if @slc_data_csv_file

@slc_data_csv_file = Tempfile.new
@slc_data_csv_file.write StudentLoansDataImporter.mandatory_headers.join(",") + "\n"
@slc_data_csv_file.write csv_row(sl_claim_with_slc_data_no_student_loan, no_data: true)
@slc_data_csv_file.write csv_row(sl_claim_with_slc_data_with_student_loan, plan_type: "1", amount: "100")
@slc_data_csv_file.write csv_row(ecp_claim_with_slc_data_no_student_loan, no_data: true)
@slc_data_csv_file.write csv_row(ecp_claim_with_slc_data_with_student_loan, plan_type: "1", amount: "100")

@slc_data_csv_file.rewind

@slc_data_csv_file
end

def csv_row(claim, no_data: nil, plan_type: nil, amount: nil)
values = [
claim.reference,
claim.national_insurance_number,
"#{claim.first_name} #{claim.surname}",
claim.date_of_birth.strftime(I18n.t("date.formats.day_month_year")),
claim.policy.locale_key,
"1",
plan_type,
amount
]
values += if no_data
["No data", "No data", "No data"]
else
["1", plan_type, amount]
end
values.join(",") << "\n"
end
end
Loading

0 comments on commit 0403b83

Please sign in to comment.