diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index 5081b148e..0ec277834 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -19,6 +19,8 @@ def report @report ||= case params[:name] when "fe-approved-claims-with-failing-provider-verification" Reports::FeApprovedClaimsWithFailingProviderVerification.new + when "approved-claims-failing-qualification-task" + Reports::ApprovedClaimsFailingQualificationTask.new else raise ActiveRecord::RecordNotFound end diff --git a/app/models/admin/reports/approved_claims_failing_qualification_task.rb b/app/models/admin/reports/approved_claims_failing_qualification_task.rb new file mode 100644 index 000000000..b33363886 --- /dev/null +++ b/app/models/admin/reports/approved_claims_failing_qualification_task.rb @@ -0,0 +1,121 @@ +module Admin + module Reports + class ApprovedClaimsFailingQualificationTask + HEADERS = [ + "Claim reference", + "Teacher reference number", + "Policy", + "Status", + "Decision date", + "Decision agent", + "Qualification", + "ITT start year", + "ITT subject", + "ITT subjects", + "ITT start date", + "QTS award date", + "Qualification name" + ] + + def filename + "approved_claims_failing_qualification_task" + end + + def to_csv + CSV.generate( + row_sep: "\r\n", + write_headers: true, + headers: HEADERS + ) do |csv| + rows.each { |row| csv << row } + end + end + + private + + def rows + scope.map(&ClaimPresenter.method(:new)).map(&:to_a) + end + + def scope + Claim + .approved + .where(academic_year: AcademicYear.current) + .joins(:tasks) + .merge(Task.where(name: "qualifications", passed: false)) + .includes(:eligibility, decisions: :created_by) + end + + class ClaimPresenter + include Admin::ClaimsHelper + + def initialize(claim) + @claim = claim + end + + def to_a + [ + claim.reference, + claim.eligibility.teacher_reference_number, + I18n.t("#{claim.policy.locale_key}.policy_acronym"), + status(claim), + I18n.l(approval.created_at.to_date, format: :day_month_year), + approval.created_by.full_name, + qualification, + itt_academic_year&.to_s, + eligible_itt_subject, + dqt_teacher_record.itt_subjects.join(", "), + I18n.l(dqt_teacher_record.itt_start_date, format: :day_month_year), + I18n.l(dqt_teacher_record.qts_award_date, format: :day_month_year), + dqt_teacher_record.qualification_name + ] + end + + private + + attr_reader :claim + + def approval + @approval ||= claim.decisions.reject(&:undone).last + end + + # StudentLoans doesn't have an eligible_itt_subject + def eligible_itt_subject + claim.eligibility.try(:eligible_itt_subject) + end + + # StudentLoans doesn't have an itt_academic_year + def itt_academic_year + claim.eligibility.try(:itt_academic_year) + end + + # StudentLoans doesn't have a qualification + def qualification + claim.eligibility.try(:qualification) + end + + def itt_subjects + dqt_teacher_record&.itt_subjects + end + + def itt_start_date + dqt_teacher_record&.itt_start_date + end + + def qts_award_date + dqt_teacher_record&.qts_award_date + end + + def qualification_name + dqt_teacher_record&.qualification_name + end + + def dqt_teacher_record + @dqt_teacher_record ||= if claim.has_dqt_record? + Dqt::Teacher.new(claim.dqt_teacher_status) + end + end + end + end + end +end diff --git a/app/views/admin/reports/index.html.erb b/app/views/admin/reports/index.html.erb index 8a9d58e73..29074aefb 100644 --- a/app/views/admin/reports/index.html.erb +++ b/app/views/admin/reports/index.html.erb @@ -13,5 +13,11 @@ admin_report_path("fe-approved-claims-with-failing-provider-verification", format: :csv), secondary: true ) %> + + <%= govuk_button_link_to( + "Approved claims failing qualification task", + admin_report_path("approved-claims-failing-qualification-task", format: :csv), + secondary: true + ) %> diff --git a/spec/features/admin/reports_spec.rb b/spec/features/admin/reports_spec.rb index 93ba372d4..aa9e3c2e9 100644 --- a/spec/features/admin/reports_spec.rb +++ b/spec/features/admin/reports_spec.rb @@ -99,4 +99,68 @@ expect(row.fetch("Disciplinary")).to eq("Yes") end end + + describe "Approved claims failing qualification task" do + it "returns a CSV report" do + claim = create( + :claim, + :with_dqt_teacher_status, + :approved, + policy: Policies::LevellingUpPremiumPayments, + first_name: "Elizabeth", + surname: "Hoover", + eligibility_attributes: { + teacher_reference_number: "1234567", + qualification: :postgraduate_itt, + itt_academic_year: "2023/2024", + eligible_itt_subject: :mathematics + }, + dqt_teacher_status: { + initial_teacher_training: { + programme_start_date: "2022-09-01", + subject1: "mathematics", + subject1_code: "G100", + qualification: "BA (Hons)" + }, + qualified_teacher_status: { + qts_date: "2022-12-01" + } + } + ) + + create( + :task, + :failed, + name: "qualifications", + claim: claim + ) + + sign_in_as_service_operator + + visit admin_claims_path + + click_on "Reports" + + click_on "Approved claims failing qualification task" + + csv_data = page.body + + csv = CSV.parse(csv_data, headers: true) + row = csv.first + + expect(row.fetch("Claim reference")).to eq(claim.reference) + expect(row.fetch("Teacher reference number")).to eq("1234567") + expect(row.fetch("Policy")).to eq("STRI") + expect(row.fetch("Status")).to eq("Approved awaiting payroll") + expect(row.fetch("Decision date")).to eq("06/12/2024") + expect(row.fetch("Decision agent")).to eq("Aaron Admin") + expect(row.fetch("Qualification")).to eq("postgraduate_itt") + expect(row.fetch("ITT start year")).to eq("2023/2024") + expect(row.fetch("ITT subject")).to eq("mathematics") + expect(row.fetch("ITT subjects")).to eq("mathematics") + expect(row.fetch("ITT start date")).to eq("01/09/2022") + expect(row.fetch("QTS award date")).to eq("01/12/2022") + expect(row.fetch("Qualification name")).to eq("BA (Hons)") + end + end end diff --git a/spec/models/admin/reports/approved_claims_failing_qualification_task_spec.rb b/spec/models/admin/reports/approved_claims_failing_qualification_task_spec.rb new file mode 100644 index 000000000..1c95a7d5b --- /dev/null +++ b/spec/models/admin/reports/approved_claims_failing_qualification_task_spec.rb @@ -0,0 +1,261 @@ +require "rails_helper" + +RSpec.describe Admin::Reports::ApprovedClaimsFailingQualificationTask do + around do |example| + travel_to Date.new(2024, 11, 1) do + example.run + end + end + + describe "to_csv" do + it "returns a csv of the claims" do + # excluded, claim not approved + ecp_claim_unapporved_failed_qualification_task = create( + :claim, + policy: Policies::EarlyCareerPayments, + academic_year: AcademicYear.new(2024) + ) + + create( + :task, + :failed, + name: "qualifications", + claim: ecp_claim_unapporved_failed_qualification_task + ) + + # excluded, task passed + lup_claim_approved_passed_qualification_task = create( + :claim, + :approved, + policy: Policies::LevellingUpPremiumPayments, + academic_year: AcademicYear.new(2024) + ) + + create( + :task, + :passed, + name: "qualifications", + claim: lup_claim_approved_passed_qualification_task + ) + + # excluded, claim not approved + tslr_claim_rejected = create( + :claim, + :rejected, + policy: Policies::StudentLoans, + academic_year: AcademicYear.new(2024) + ) + + create( + :task, + :failed, + name: "qualifications", + claim: tslr_claim_rejected + ) + + # excluded, wrong policy! + _fe_claim = create( + :claim, + :approved, + policy: Policies::FurtherEducationPayments, + academic_year: AcademicYear.new(2024) + ) + + # excluded, previous academic year + ecp_claim_unapporved_failed_qualification_task = create( + :claim, + :approved, + policy: Policies::EarlyCareerPayments, + academic_year: AcademicYear.new(2023) + ) + + create( + :task, + :failed, + name: "qualifications", + claim: ecp_claim_unapporved_failed_qualification_task + ) + + # included + ecp_claim_approved_failed_qualification_task = create( + :claim, + :approved, + :flagged_for_qa, + policy: Policies::EarlyCareerPayments, + academic_year: AcademicYear.new(2024), + decision_creator: create( + :dfe_signin_user, + given_name: "Some", + family_name: "admin" + ), + eligibility_attributes: { + teacher_reference_number: "1111111", + eligible_itt_subject: :mathematics, + itt_academic_year: AcademicYear.new(2021), + qualification: :postgraduate_itt + }, + dqt_teacher_status: { + qualified_teacher_status: { + qts_date: "2023-09-01", + name: "Qualified teacher (trained)" + }, + initial_teacher_training: { + programme_start_date: "2022-08-01", + subject1: "mathematics", + subject1_code: "100403", + subject2: "physics", + subject3_code: "F300", + qualification: "Graduate Diploma" + } + } + ) + + create( + :task, + :failed, + name: "qualifications", + claim: ecp_claim_approved_failed_qualification_task + ) + + # included + lup_claim_approved_failed_qualification_task = create( + :claim, + :approved, + policy: Policies::LevellingUpPremiumPayments, + academic_year: AcademicYear.new(2024), + decision_creator: create( + :dfe_signin_user, + given_name: "Some", + family_name: "admin" + ), + eligibility_attributes: { + teacher_reference_number: "2222222", + eligible_itt_subject: :physics, + itt_academic_year: AcademicYear.new(2021), + qualification: :postgraduate_itt + }, + dqt_teacher_status: { + qualified_teacher_status: { + qts_date: "2023-10-01", + name: "Qualified teacher (trained)" + }, + initial_teacher_training: { + programme_start_date: "2022-08-02", + subject1: "physics", + subject1_code: "F300", + qualification: "Graduate Diploma" + } + } + ) + + create(:payment, claims: [lup_claim_approved_failed_qualification_task]) + + create( + :task, + :failed, + name: "qualifications", + claim: lup_claim_approved_failed_qualification_task + ) + + # included + tslr_claim_approved_failed_qualification_task = create( + :claim, + :approved, + policy: Policies::StudentLoans, + academic_year: AcademicYear.new(2024), + decision_creator: create( + :dfe_signin_user, + given_name: "Some", + family_name: "admin" + ), + eligibility_attributes: { + teacher_reference_number: "3333333" + }, + dqt_teacher_status: { + qualified_teacher_status: { + qts_date: "2023-10-01", + name: "Qualified teacher (trained)" + }, + initial_teacher_training: { + programme_start_date: "2022-08-02", + subject1: "physics", + subject1_code: "F300", + qualification: "Graduate Diploma" + } + } + ) + + create( + :task, + :failed, + name: "qualifications", + claim: tslr_claim_approved_failed_qualification_task + ) + + csv = CSV.parse(described_class.new.to_csv, headers: true) + + expect(csv.to_a).to match_array([ + [ + "Claim reference", + "Teacher reference number", + "Policy", + "Status", + "Decision date", + "Decision agent", + "Qualification", + "ITT start year", + "ITT subject", + "ITT subjects", + "ITT start date", + "QTS award date", + "Qualification name" + ], + [ + ecp_claim_approved_failed_qualification_task.reference, + "1111111", + "ECP", + "Approved awaiting QA", + "01/11/2024", + "Some admin", + "postgraduate_itt", + "2021/2022", + "mathematics", + "mathematics, physics", + "01/08/2022", + "01/09/2023", + "Graduate Diploma" + ], + [ + lup_claim_approved_failed_qualification_task.reference, + "2222222", + "STRI", + "Payrolled", + "01/11/2024", + "Some admin", + "postgraduate_itt", + "2021/2022", + "physics", + "physics", + "02/08/2022", + "01/10/2023", + "Graduate Diploma" + ], + [ + tslr_claim_approved_failed_qualification_task.reference, + "3333333", + "TSLR", + "Approved awaiting payroll", + "01/11/2024", + "Some admin", + nil, + nil, + nil, + "physics", + "02/08/2022", + "01/10/2023", + "Graduate Diploma" + ] + ]) + end + end +end