diff --git a/app/models/automated_checks/claim_verifiers/student_loan_plan.rb b/app/models/automated_checks/claim_verifiers/student_loan_plan.rb index 71a756de0b..5abdcad073 100644 --- a/app/models/automated_checks/claim_verifiers/student_loan_plan.rb +++ b/app/models/automated_checks/claim_verifiers/student_loan_plan.rb @@ -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 @@ -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( { @@ -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 } diff --git a/app/models/claim.rb b/app/models/claim.rb index d0f37231eb..1d99da27cf 100644 --- a/app/models/claim.rb +++ b/app/models/claim.rb @@ -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"} diff --git a/app/models/claim_student_loan_details_updater.rb b/app/models/claim_student_loan_details_updater.rb index 23be40dd80..254d779ed7 100644 --- a/app/models/claim_student_loan_details_updater.rb +++ b/app/models/claim_student_loan_details_updater.rb @@ -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 @@ -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 diff --git a/app/models/journeys/answers_student_loans_details_updater.rb b/app/models/journeys/answers_student_loans_details_updater.rb index 58c4762946..a27d83013d 100644 --- a/app/models/journeys/answers_student_loans_details_updater.rb +++ b/app/models/journeys/answers_student_loans_details_updater.rb @@ -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? ) diff --git a/app/models/policies/student_loans/policy_eligibility_checker.rb b/app/models/policies/student_loans/policy_eligibility_checker.rb index e5a086300d..17ba4165e4 100644 --- a/app/models/policies/student_loans/policy_eligibility_checker.rb +++ b/app/models/policies/student_loans/policy_eligibility_checker.rb @@ -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 diff --git a/app/models/student_loans_data_presenter.rb b/app/models/student_loans_data_presenter.rb index cc365bfd62..cb9ca2ffd8 100644 --- a/app/models/student_loans_data_presenter.rb +++ b/app/models/student_loans_data_presenter.rb @@ -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 diff --git a/spec/factories/student_loans_data.rb b/spec/factories/student_loans_data.rb index 1c2d14f421..bd30a0e550 100644 --- a/spec/factories/student_loans_data.rb +++ b/spec/factories/student_loans_data.rb @@ -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 diff --git a/spec/features/admin/upload_slc_data_spec.rb b/spec/features/admin/upload_slc_data_spec.rb new file mode 100644 index 0000000000..be6ba41464 --- /dev/null +++ b/spec/features/admin/upload_slc_data_spec.rb @@ -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 diff --git a/spec/features/ineligible_student_loans_claims_spec.rb b/spec/features/ineligible_student_loans_claims_spec.rb index 5676919e65..abe4dfa63e 100644 --- a/spec/features/ineligible_student_loans_claims_spec.rb +++ b/spec/features/ineligible_student_loans_claims_spec.rb @@ -7,7 +7,8 @@ let!(:journey_configuration) { create(:journey_configuration, :student_loans) } let!(:school) { create(:school, :student_loans_eligible) } let!(:ineligible_school) { create(:school, :student_loans_ineligible) } - let(:imported_slc_data) { create(:student_loans_data, nino:, date_of_birth:, plan_type_of_deduction: 1, amount: 0) } + let(:import_zero_amount_slc_data) { create(:student_loans_data, nino:, date_of_birth:, plan_type_of_deduction: 1, amount: 0) } + let(:import_no_data_slc_data) { create(:student_loans_data, nino:, date_of_birth:, plan_type_of_deduction: nil, amount: 0) } let(:eligible_itt_years) { JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } let(:academic_date) { Date.new(eligible_itt_years.first.start_year, 12, 1) } let(:itt_year) { AcademicYear.for(academic_date) } @@ -118,7 +119,7 @@ end scenario "claimant made zero student loan repayments (Non-TID journey)" do - imported_slc_data + import_zero_amount_slc_data start_student_loans_claim choose_school school @@ -133,9 +134,41 @@ choose "No" click_on "Continue" + click_on "Continue" + click_on "Continue" + + # - Personal details + fill_in "First name", with: "Russell" + fill_in "Last name", with: "Wong" + + fill_in "Day", with: Date.parse(date_of_birth).day + fill_in "Month", with: Date.parse(date_of_birth).month + fill_in "Year", with: Date.parse(date_of_birth).year + + fill_in "National Insurance number", with: nino + click_on "Continue" + + expect(page).to have_text("Your student loan repayment amount is £0.00") + expect(page).to have_text("you are not eligible to claim back any repayments") + end + + scenario "claimant has no student loan (Non-TID journey)" do + import_no_data_slc_data + + start_student_loans_claim + choose_school school + check "Physics" click_on "Continue" + choose_still_teaching("Yes, at #{school.name}") + + choose "Yes" + click_on "Continue" + + choose "No" + click_on "Continue" + click_on "Continue" click_on "Continue" # - Personal details @@ -157,7 +190,54 @@ set_mock_auth(trn, {date_of_birth:, nino:}) stub_qualified_teaching_statuses_show(trn:, params: {birthdate: date_of_birth, nino:}, body: eligible_dqt_body) - imported_slc_data + import_zero_amount_slc_data + + visit landing_page_path(Journeys::TeacherStudentLoanReimbursement::ROUTING_NAME) + + # - Landing (start) + click_on "Start now" + click_on "Continue with DfE Identity" + + # - Teacher details page + choose "Yes" + click_on "Continue" + + # - Qualification details + choose "Yes" + click_on "Continue" + + # - Which school do you teach at + choose_school school + click_on "Continue" + + # - Select subject + check "Physics" + click_on "Continue" + choose_still_teaching("Yes, at #{school.name}") + + # - Are you still employed to teach at + choose "Yes" + click_on "Continue" + + # - leadership-position question + choose "No" + click_on "Continue" + + # - Eligibility confirmed + click_on "Continue" + + # - information-provided page + click_on "Continue" + + expect(page).to have_text("Your student loan repayment amount is £0.00") + expect(page).to have_text("you are not eligible to claim back any repayments") + end + + scenario "claimant has no student loan (TID journey)" do + set_mock_auth(trn, {date_of_birth:, nino:}) + stub_qualified_teaching_statuses_show(trn:, params: {birthdate: date_of_birth, nino:}, body: eligible_dqt_body) + + import_no_data_slc_data visit landing_page_path(Journeys::TeacherStudentLoanReimbursement::ROUTING_NAME) diff --git a/spec/features/student_loans_claim_spec.rb b/spec/features/student_loans_claim_spec.rb index 47428cce5a..ed306fef27 100644 --- a/spec/features/student_loans_claim_spec.rb +++ b/spec/features/student_loans_claim_spec.rb @@ -245,7 +245,7 @@ def fill_in_remaining_personal_details_and_submit expect(answers).not_to have_student_loan expect(answers.student_loan_repayment_amount).to eql(0) - expect(answers.student_loan_plan).to eql(Claim::NO_STUDENT_LOAN) + expect(answers.student_loan_plan).to be nil fill_in_remaining_personal_details_and_submit end diff --git a/spec/models/automated_checks/claim_verifiers/student_loan_plan_spec.rb b/spec/models/automated_checks/claim_verifiers/student_loan_plan_spec.rb index 0d04fd829d..938c308a91 100644 --- a/spec/models/automated_checks/claim_verifiers/student_loan_plan_spec.rb +++ b/spec/models/automated_checks/claim_verifiers/student_loan_plan_spec.rb @@ -72,56 +72,57 @@ module ClaimVerifiers context "when the policy is #{policy}" do let(:policy) { policy } let(:claim) { create(:claim, :submitted, policy:, national_insurance_number: "QQ123456A", has_student_loan: true, student_loan_plan: claim_student_loan_plan, submitted_using_slc_data:) } - let(:imported_slc_data) { create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: slc_student_loan_plan) } + let(:claim_student_loan_plan) { nil } - let(:claim_student_loan_plan) { StudentLoan::PLAN_1 } - let(:slc_student_loan_plan) { 1 } - let(:submitted_using_slc_data) { false } + context "when there is already a student_loan_plan task" do + before { create(:task, claim: claim, name: "student_loan_plan") } - context "when the claim was submitted using SLC data" do - let(:submitted_using_slc_data) { true } + let(:submitted_using_slc_data) { false } it_behaves_like :execution_without_an_outcome end - context "when the claim was submitted using the student loan questions" do - let(:submitted_using_slc_data) { nil } + context "when the claim was submitted using SLC data" do + let(:submitted_using_slc_data) { true } + let(:claim_student_loan_plan) { StudentLoan::PLAN_1 } it_behaves_like :execution_without_an_outcome end - context "when is no student loans data for the claim" do - let(:expected_to_pass?) { nil } - let(:expected_match_value) { nil } - let(:expected_note) { "[SLC Student loan plan] - No data" } + context "when the claim was not submitted using SLC data" do + let(:submitted_using_slc_data) { false } - it_behaves_like :execution_with_an_outcome - end + context "when there is no student loan data for the claim" do + let(:expected_to_pass?) { nil } + let(:expected_match_value) { nil } + let(:expected_note) { "[SLC Student loan plan] - No data" } - context "when the plan type on the claim is equal to the SLC value" do - before { imported_slc_data } + it_behaves_like :execution_with_an_outcome + end - let(:claim_student_loan_plan) { StudentLoan::PLAN_1 } - let(:slc_student_loan_plan) { 1 } + context "when there is student loan data - with a plan" do + before do + create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: 1) + end - let(:expected_to_pass?) { true } - let(:expected_match_value) { "all" } - let(:expected_note) { "[SLC Student loan plan] - Matched" } + let(:expected_to_pass?) { true } + let(:expected_match_value) { "all" } + let(:expected_note) { "[SLC Student loan plan] - Matched - has a student loan" } - it_behaves_like :execution_with_an_outcome - end + it_behaves_like :execution_with_an_outcome + end - context "when the plan type on the claim is not equal to the SLC value" do - before { imported_slc_data } - - let(:claim_student_loan_plan) { StudentLoan::PLAN_1 } - let(:slc_student_loan_plan) { 2 } + context "when there is student loan data - without a plan" do + before do + create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: nil) + end - let(:expected_to_pass?) { false } - let(:expected_match_value) { "none" } - let(:expected_note) { "[SLC Student loan plan] - The plan type on the claim (Plan 1) didn't match the SLC value (Plan 2)" } + let(:expected_to_pass?) { true } + let(:expected_match_value) { "all" } + let(:expected_note) { "[SLC Student loan plan] - Matched - does not have a student loan" } - it_behaves_like :execution_with_an_outcome + it_behaves_like :execution_with_an_outcome + end end end end diff --git a/spec/models/claim_spec.rb b/spec/models/claim_spec.rb index 3342b81d5d..56e8526f54 100644 --- a/spec/models/claim_spec.rb +++ b/spec/models/claim_spec.rb @@ -104,8 +104,8 @@ end context "when saving in the “student-loan” validation context" do - it "validates the presence of has_student_loan" do - expect(build(:claim, student_loan_plan: StudentLoan::PLAN_1, has_student_loan: nil)).not_to be_valid(:"student-loan") + it "validates has_student_loan" do + expect(build(:claim, student_loan_plan: nil, has_student_loan: nil)).to be_valid(:"student-loan") expect(build(:claim, student_loan_plan: StudentLoan::PLAN_1, has_student_loan: true)).to be_valid(:"student-loan") expect(build(:claim, student_loan_plan: StudentLoan::PLAN_1, has_student_loan: false)).to be_valid(:"student-loan") end diff --git a/spec/models/claim_student_loan_details_updater_spec.rb b/spec/models/claim_student_loan_details_updater_spec.rb index 78a9d29d6a..450c270eec 100644 --- a/spec/models/claim_student_loan_details_updater_spec.rb +++ b/spec/models/claim_student_loan_details_updater_spec.rb @@ -29,10 +29,8 @@ context "when the policy is StudentLoans" do let(:policy) { Policies::StudentLoans } - it "updates the claim with no student plan and zero repayment total" do - expect { call }.to change { claim.reload.has_student_loan }.to(false) - .and change { claim.student_loan_plan }.to(Claim::NO_STUDENT_LOAN) - .and change { claim.eligibility.student_loan_repayment_amount }.to(0) + it "does not update the claim student plan and zero repayment total" do + expect { call }.not_to change { claim.reload.has_student_loan } end it "keeps the `submitted_using_slc_data` flag to `false` (default)" do @@ -44,19 +42,14 @@ context "when the policy is #{policy}" do let(:policy) { policy } - it "updates the claim with no student plan" do - expect { call }.to change { claim.reload.has_student_loan }.to(false) - .and change { claim.student_loan_plan }.to(Claim::NO_STUDENT_LOAN) - end - - it "keeps the `submitted_using_slc_data` flag to `false` (default)" do - expect { call }.not_to change { claim.submitted_using_slc_data }.from(false) + it "does not update the claim" do + expect { call }.not_to change { claim.reload } end end end end - context "when existing SLC data is found for the claimant" do + context "when SLC data is found with student loan information for the claimant" do before do create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: 1, amount: 50) create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: 2, amount: 60) @@ -86,11 +79,40 @@ end end + context "when SLC data is found with no student loan information for the claimant" do + before do + create(:student_loans_data, nino: claim.national_insurance_number, date_of_birth: claim.date_of_birth, plan_type_of_deduction: nil, amount: nil) + end + + it "returns true" do + expect(call).to eq(true) + end + + context "when the policy is StudentLoans" do + it "updates the claim with the student plan and the repayment total" do + expect { call }.to change { claim.reload.has_student_loan }.to(false) + .and change { claim.student_loan_plan }.to(Claim::NO_STUDENT_LOAN) + .and change { claim.eligibility.student_loan_repayment_amount }.to(0) + end + end + + [Policies::EarlyCareerPayments, Policies::LevellingUpPremiumPayments].each do |policy| + context "when the policy is #{policy}" do + let(:policy) { policy } + + it "updates the claim with the student plan only" do + expect { call }.to change { claim.reload.has_student_loan }.to(false) + .and change { claim.student_loan_plan }.to(Claim::NO_STUDENT_LOAN) + end + end + end + end + context "when an error occurs while updating" do let(:exception) { ActiveRecord::RecordInvalid } before do - allow(claim).to receive_message_chain(:assign_attributes, :assign_attributes, :save!) { raise(exception) } + allow(claim).to receive(:save!) { raise(exception) } allow(Rollbar).to receive(:error) end diff --git a/spec/models/student_loans/eligibility_spec.rb b/spec/models/student_loans/eligibility_spec.rb index 9dc19a469b..6530b71ca4 100644 --- a/spec/models/student_loans/eligibility_spec.rb +++ b/spec/models/student_loans/eligibility_spec.rb @@ -201,7 +201,7 @@ context "when the has_student_loan claim flag is false" do let(:claim) { build(:claim, has_student_loan: false) } - it { is_expected.not_to be_ineligible } + it { is_expected.to be_ineligible } end context "when the has_student_loan claim flag is nil" do diff --git a/spec/requests/admin/admin_student_loans_data_upload_spec.rb b/spec/requests/admin/admin_student_loans_data_upload_spec.rb index 55800a03a9..0f13b8bf81 100644 --- a/spec/requests/admin/admin_student_loans_data_upload_spec.rb +++ b/spec/requests/admin/admin_student_loans_data_upload_spec.rb @@ -52,8 +52,7 @@ let(:csv) do <<~CSV Claim reference,NINO,Full name,Date of birth,Policy name,No of Plans Currently Repaying,Plan Type of Deduction,Amount - #{rows[0].values.join(",")} - #{rows[1].values.join(",")} + #{rows.map { |row| row.values.join(",") }.join("\n")} CSV end @@ -78,6 +77,16 @@ no_of_plans_currently_repaying: "1", plan_type_of_deduction: "2", amount: "50" + }, + { + claim_reference: "TESTREF03", + nino: "QQ234567B", + full_name: "Guybrush Threepwood", + date_of_birth: "1/12/1980", + policy_name: "EarlyCareerPayments", + no_of_plans_currently_repaying: "No data", + plan_type_of_deduction: "No data", + amount: "No data" } ] end @@ -101,14 +110,30 @@ expect { upload }.to have_enqueued_job(ImportStudentLoansDataJob) end - it "parses the rows and saves them as student loans data records" do + it "parses the rows with data and saves them as student loans data records" do aggregate_failures do - expect { perform_enqueued_jobs { upload } }.to change(StudentLoansData, :count).by(2) + expect { perform_enqueued_jobs { upload } }.to change(StudentLoansData, :count).by(3) expect(StudentLoansData.where(nino: "QQ123456A").first).to have_attributes(expected_records[0]) expect(StudentLoansData.where(nino: "QQ123456B").first).to have_attributes(expected_records[1]) end end + it "parses the rows with no data and saves them as student loans data records" do + perform_enqueued_jobs { upload } + expect(StudentLoansData.where(nino: "QQ234567B").first).to have_attributes( + { + claim_reference: "TESTREF03", + nino: "QQ234567B", + full_name: "Guybrush Threepwood", + date_of_birth: Date.strptime("1/12/1980", "%d/%m/%Y"), + policy_name: "EarlyCareerPayments", + no_of_plans_currently_repaying: nil, + plan_type_of_deduction: nil, + amount: 0 + } + ) + end + shared_examples :no_upload do it "does not upload the rows" do expect { perform_enqueued_jobs { upload } }.not_to change(StudentLoansData, :count) diff --git a/spec/requests/claims_spec.rb b/spec/requests/claims_spec.rb index 4cd547c865..68f255aca7 100644 --- a/spec/requests/claims_spec.rb +++ b/spec/requests/claims_spec.rb @@ -201,9 +201,28 @@ def check_slug_redirection set_slug_sequence_in_session(journey_session, "personal-details") end - it "updates the student loan details" do - expect { request }.to change { journey_session.reload.answers.has_student_loan } - .and change { journey_session.reload.answers.student_loan_plan } + context "when there is no student loan data for the claimant" do + it "does not update the student loan details" do + expect { request }.not_to change { journey_session.reload } + end + end + + context "when there is student loan data showing the claimant has a student loan" do + before { create(:student_loans_data, nino: "QQ123456C", date_of_birth: Date.new(1990, 1, 1)) } + + it "updates the student loan details" do + expect { request }.to change { journey_session.reload.answers.has_student_loan }.to(true) + .and change { journey_session.reload.answers.student_loan_plan }.to("plan_1") + end + end + + context "when there is student loan data showing the claimant does not have student loan" do + before { create(:student_loans_data, :no_student_loan, nino: "QQ123456C", date_of_birth: Date.new(1990, 1, 1)) } + + it "updates the student loan details" do + expect { request }.to change { journey_session.reload.answers.has_student_loan }.to(false) + .and change { journey_session.reload.answers.student_loan_plan }.to("not_applicable") + end end end @@ -248,12 +267,28 @@ def check_slug_redirection journey_session.save! end - it "updates the student loan details" do - expect { request }.to( - change { journey_session.reload.answers.has_student_loan }.and( - change { journey_session.reload.answers.student_loan_plan } - ) - ) + context "when there is no student loan data for the claimant" do + it "does not update the student loan details" do + expect { request }.not_to change { journey_session.reload } + end + end + + context "when there is student loan data showing the claimant has a student loan" do + before { create(:student_loans_data, nino: "QQ123456C", date_of_birth: Date.new(1990, 1, 1)) } + + it "updates the student loan details" do + expect { request }.to change { journey_session.reload.answers.has_student_loan }.to(true) + .and change { journey_session.reload.answers.student_loan_plan }.to("plan_1") + end + end + + context "when there is student loan data showing the claimant does not have student loan" do + before { create(:student_loans_data, :no_student_loan, nino: "QQ123456C", date_of_birth: Date.new(1990, 1, 1)) } + + it "updates the student loan details" do + expect { request }.to change { journey_session.reload.answers.has_student_loan }.to(false) + .and change { journey_session.reload.answers.student_loan_plan }.to("not_applicable") + end end end