-
Notifications
You must be signed in to change notification settings - Fork 16
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
[CAPT-1797] Ops reports spike #3284
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class Report < ApplicationRecord | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -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) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
.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 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 %> | ||
|
||
<div class="govuk-grid-row"> | ||
<div class="govuk-grid-column-full"> | ||
<h1 class="govuk-heading-xl"> | ||
Reports | ||
</h1> | ||
|
||
<table class="govuk-table"> | ||
<thead class="govuk-table__head"> | ||
<tr class="govuk-table__row"> | ||
<th scope="col" class="govuk-table__header">Name</th> | ||
<th scope="col" class="govuk-table__header">Created At</th> | ||
<th scope="col" class="govuk-table__header">Number of rows</th> | ||
</tr> | ||
</thead> | ||
<tbody class="govuk-table__body"> | ||
<% @reports.each do |report| %> | ||
<tr class="govuk-table__row"> | ||
<td class="govuk-table__cell"><%= govuk_link_to report.name, admin_report_path(report, format: :csv) %></td> | ||
<td class="govuk-table__cell"><%= l(report.created_at) %></td> | ||
<td class="govuk-table__cell"><%= report.number_of_rows %></td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
</div> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class CreateReports < ActiveRecord::Migration[7.0] | ||
def change | ||
create_table :reports, id: :uuid do |t| | ||
t.string :name | ||
t.text :csv | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice approach 👍, very simple and gets the job done! |
||
t.integer :number_of_rows | ||
|
||
t.timestamps | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we want to include
decisions
too or if it's less work to filter first and make the additional trips to the db