diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb new file mode 100644 index 000000000..a42e39944 --- /dev/null +++ b/app/controllers/admin/reports_controller.rb @@ -0,0 +1,18 @@ +module Admin + class ReportsController < BaseAdminController + before_action :ensure_service_operator + + def index + @reports = Report.order(created_at: :desc) + end + + def show + respond_to do |format| + format.csv { + report = Report.find(params[:id]) + send_data report.csv, filename: "#{report.name.parameterize(separator: "_")}_#{report.created_at.iso8601}.csv" + } + end + end + end +end diff --git a/app/jobs/reports_job.rb b/app/jobs/reports_job.rb new file mode 100644 index 000000000..8032c8408 --- /dev/null +++ b/app/jobs/reports_job.rb @@ -0,0 +1,14 @@ +class ReportsJob < CronJob + self.cron_expression = "0 6 * * 2#2" # second Tuesday of the month + + def perform + Rails.logger.info "Generating Ops reports" + + csv = Reports::DuplicateClaims.new.to_csv + Report.create!(name: Reports::DuplicateClaims::NAME, csv: csv, number_of_rows: csv.lines.count - 1) + csv = Reports::FailedQualificationClaims.new.to_csv + Report.create!(name: Reports::FailedQualificationClaims::NAME, csv: csv, number_of_rows: csv.lines.count - 1) + csv = Reports::FailedProviderCheckClaims.new.to_csv + Report.create!(name: Reports::FailedProviderCheckClaims::NAME, csv: csv, number_of_rows: csv.lines.count - 1) + end +end diff --git a/app/models/report.rb b/app/models/report.rb new file mode 100644 index 000000000..1dfff22ff --- /dev/null +++ b/app/models/report.rb @@ -0,0 +1,2 @@ +class Report < ApplicationRecord +end diff --git a/app/models/reports/duplicate_claims.rb b/app/models/reports/duplicate_claims.rb new file mode 100644 index 000000000..1d3610ad5 --- /dev/null +++ b/app/models/reports/duplicate_claims.rb @@ -0,0 +1,47 @@ +require "csv" +require "excel_utils" + +module Reports + class DuplicateClaims + include Admin::ClaimsHelper + + NAME = "Duplicate Approved Claims" + HEADERS = [ + "Claim reference", + "Teacher reference number", + "Full name", + "Policy name", + "Claim amount", + "Claim status", + "Decision date", + "Decision agent" + ].freeze + + def initialize + @claims = Claim.approved.select { |claim| Claim::MatchingAttributeFinder.new(claim).matching_claims.any? } + end + + def to_csv + CSV.generate(write_headers: true, headers: HEADERS) do |csv| + @claims.each do |claim| + csv << row( + claim.reference, + claim.eligibility.teacher_reference_number, + claim.full_name, + claim.policy, + claim.award_amount, + status(claim), + claim.latest_decision.created_at, + claim.latest_decision.created_by.full_name + ) + end + end + end + + private + + def row(*entries) + entries.map { |entry| ExcelUtils.escape_formulas(entry) } + end + end +end diff --git a/app/models/reports/failed_provider_check_claims.rb b/app/models/reports/failed_provider_check_claims.rb new file mode 100644 index 000000000..d3782a148 --- /dev/null +++ b/app/models/reports/failed_provider_check_claims.rb @@ -0,0 +1,72 @@ +require "csv" +require "excel_utils" + +module Reports + class FailedProviderCheckClaims + include Admin::ClaimsHelper + + def self.provider_verification_label(field) + I18n.t("further_education_payments.admin.task_questions.provider_verification.#{field}.label") + end + private_class_method :provider_verification_label + + NAME = "Claims with failed provider check" + HEADERS = [ + "Claim reference", + "Teacher reference number", + "Full name", + "Claim amount", + "Claim status", + "Decision date", + "Decision agent", + "Provider response: #{provider_verification_label("contract_type")}", + "Provider response: #{provider_verification_label("teaching_responsibilities")}", + "Provider response: #{provider_verification_label("further_education_teaching_start_year")}", + "Provider response: #{provider_verification_label("teaching_hours_per_week")}", + "Provider response: #{provider_verification_label("half_teaching_hours")}", + "Provider response: #{provider_verification_label("subjects_taught")}", + "Provider response: #{provider_verification_label("taught_at_least_one_term")}", + "Provider response: #{provider_verification_label("teaching_hours_per_week_next_term")}" + ].freeze + + def initialize + @claims = Claim.includes(:tasks) + .where(eligibility_type: "Policies::FurtherEducationPayments::Eligibility", tasks: {name: "provider_verification", passed: false}) + .approved + end + + def to_csv + CSV.generate(write_headers: true, headers: HEADERS) do |csv| + @claims.each do |claim| + csv << row( + claim.reference, + claim.eligibility.teacher_reference_number, + claim.full_name, + claim.award_amount, + status(claim), + claim.latest_decision.created_at, + claim.latest_decision.created_by.full_name, + verification_assertion(claim, "contract_type"), + verification_assertion(claim, "teaching_responsibilities"), + verification_assertion(claim, "further_education_teaching_start_year"), + verification_assertion(claim, "teaching_hours_per_week"), + verification_assertion(claim, "half_teaching_hours"), + verification_assertion(claim, "subjects_taught"), + verification_assertion(claim, "taught_at_least_one_term"), + verification_assertion(claim, "teaching_hours_per_week_next_term") + ) + end + end + end + + private + + def row(*entries) + entries.map { |entry| ExcelUtils.escape_formulas(entry) } + end + + def verification_assertion(claim, name) + claim.eligibility["assertions"].find { |assertion| assertion["name"] == name }["outcome"] + end + end +end diff --git a/app/models/reports/failed_qualification_claims.rb b/app/models/reports/failed_qualification_claims.rb new file mode 100644 index 000000000..dc73e7f41 --- /dev/null +++ b/app/models/reports/failed_qualification_claims.rb @@ -0,0 +1,77 @@ +require "csv" +require "excel_utils" + +module Reports + class FailedQualificationClaims + NAME = "Claims with failed qualification status" + HEADERS = [ + "Claim reference", + "Teacher reference number", + "Policy name", + "Decision date", + "Decision agent", + "Answered qualification", + "Answered ITT start year", + "Answered ITT subject", + "DQT ITT subjects", + "DQT ITT start year", + "DQT QTS award date", + "DQT qualification name" + ].freeze + + def initialize + @claims = Claim.includes(:tasks).where(tasks: {name: "qualifications", passed: false}).approved + end + + def to_csv + CSV.generate(write_headers: true, headers: HEADERS) do |csv| + @claims.each do |claim| + csv << row( + claim.reference, + claim.eligibility.teacher_reference_number, + claim.policy, + claim.latest_decision.created_at, + claim.latest_decision.created_by.full_name, + claim.eligibility.qualification, + claim.eligibility.itt_academic_year.start_year, + claim.eligibility.eligible_itt_subject, + dqt_itt_subjects(claim), + dqt_itt_start_date(claim), + dqt_qts_date(claim), + dqt_qts_qualification_name(claim) + ) + end + end + end + + private + + def row(*entries) + entries.map { |entry| ExcelUtils.escape_formulas(entry) } + end + + def dqt_itt_subjects(claim) + unless claim.dqt_teacher_status.empty? + claim.dqt_teacher_status["initial_teacher_training"].fetch_values("subject1", "subject2", "subject3").compact.join(",") + end + end + + def dqt_itt_start_date(claim) + unless claim.dqt_teacher_status.empty? + claim.dqt_teacher_status["initial_teacher_training"]["programme_start_date"] + end + end + + def dqt_qts_date(claim) + unless claim.dqt_teacher_status.empty? + claim.dqt_teacher_status["qualified_teacher_status"]["qts_date"] + end + end + + def dqt_qts_qualification_name(claim) + unless claim.dqt_teacher_status.empty? + claim.dqt_teacher_status["qualified_teacher_status"]["name"] + end + end + end +end diff --git a/app/views/admin/reports/index.html.erb b/app/views/admin/reports/index.html.erb new file mode 100644 index 000000000..bf9ddf816 --- /dev/null +++ b/app/views/admin/reports/index.html.erb @@ -0,0 +1,32 @@ +<% content_for(:page_title) { page_title("Download Reports") } %> + +<% content_for :back_link do %> + <%= govuk_back_link href: admin_root_path %> +<% end %> + +
Name | +Created At | +Number of rows | +
---|---|---|
<%= govuk_link_to report.name, admin_report_path(report, format: :csv) %> | +<%= l(report.created_at) %> | +<%= report.number_of_rows %> | +