From e8b4dee626aa568b486d50a01df34b1dacce9084 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 28 Aug 2024 15:22:04 +0100 Subject: [PATCH] WIP - add provider verification task Adds the task for the provider to verify the claim. This commit is a work in progress as there's still a few things outstanding: * various admin localisations * updating the task presenter so submitting the task form doesn't error when redirecting to the next page * Handling different rows for variable hours contracts I mostly wanted to check that how we're storing the verification worked reasonably when we wanted to render the information on the admin task side. This task isn't automatically approved, admins need to go in and manually confirm that the provider verification looks correct. I think this makes sense from and MVP approach and we can itterate towards automatic approval. The designs for the pending task page haven't been completed so expect that to change, currently we just say the task is pending and show an email link. As the verification table in the ui requires stiching together data from the verification and the eligibility we've introduced a separate presenter object that the task presenter just calls. Mixing in the verification presenter logic in the task verifier would be a bit much once all the other tasks were added. Maybe a separate "Verification" record would make this easier to work with. This commit should be cleaned up and the message rewritten before merging. --- app/models/base_policy.rb | 4 + app/models/claim_checking_tasks.rb | 3 + ...in_provider_verification_task_presenter.rb | 100 ++++++++++++ .../admin_tasks_presenter.rb | 31 ++++ .../eligibility_admin_answers_presenter.rb | 17 ++ app/models/task.rb | 1 + .../tasks/provider_verification.html.erb | 75 +++++++++ config/locales/en.yml | 35 +++++ .../eligibilities.rb | 9 ++ ...n_claim_further_education_payments_spec.rb | 147 ++++++++++++++++++ 10 files changed, 422 insertions(+) create mode 100644 app/models/policies/further_education_payments/admin_provider_verification_task_presenter.rb create mode 100644 app/models/policies/further_education_payments/admin_tasks_presenter.rb create mode 100644 app/models/policies/further_education_payments/eligibility_admin_answers_presenter.rb create mode 100644 app/views/admin/tasks/provider_verification.html.erb create mode 100644 spec/features/admin/admin_claim_further_education_payments_spec.rb diff --git a/app/models/base_policy.rb b/app/models/base_policy.rb index a9a327a0be..7ce56a6c5d 100644 --- a/app/models/base_policy.rb +++ b/app/models/base_policy.rb @@ -50,4 +50,8 @@ def searchable_eligibility_attributes def international_relocation_payments? to_s == "InternationalRelocationPayments" end + + def further_education_payments? + to_s == "FurtherEducationPayments" + end end diff --git a/app/models/claim_checking_tasks.rb b/app/models/claim_checking_tasks.rb index d46d0491ea..8a8e1f1261 100644 --- a/app/models/claim_checking_tasks.rb +++ b/app/models/claim_checking_tasks.rb @@ -31,6 +31,9 @@ def applicable_task_names task_names.delete("subject") task_names.delete("teaching_hours") end + unless claim.policy.further_education_payments? + task_names.delete("provider_verification") + end end end diff --git a/app/models/policies/further_education_payments/admin_provider_verification_task_presenter.rb b/app/models/policies/further_education_payments/admin_provider_verification_task_presenter.rb new file mode 100644 index 0000000000..c9e71b115f --- /dev/null +++ b/app/models/policies/further_education_payments/admin_provider_verification_task_presenter.rb @@ -0,0 +1,100 @@ +module Policies + module FurtherEducationPayments + class AdminProviderVerificationTaskPresenter + class Row < Struct.new( + :label, + :claimant_answer, + :provider_answer, + keyword_init: true + ); end + + ROWS = [ + ["contract_type", "contract_type", "contract_type"], + ["teaching_responsibilities", "teaching_responsibilities", "teaching_responsibilities"], + ["further_education_teaching_start_year", "further_education_teaching_start_year", "further_education_teaching_start_year"], + ["teaching_hours_per_week", "teaching_hours_per_week", "teaching_hours_per_week"], + ["half_teaching_hours", "half_teaching_hours", "half_teaching_hours"], + ["subjects_taught", "subjects_taught", "subjects_taught"], + ["courses_taught", "courses_taught", "subjects_taught"] + ] + + attr_reader :claim + + def initialize(claim) + @claim = claim + end + + def rows + ROWS.map do |label_key, claimant_key, provider_key| + Row.new( + label: label(label_key), + claimant_answer: claimant_answer(claimant_key), + provider_answer: provider_answer(provider_key) + ) + end + end + + private + + def label(key) + I18n.t( + [ + "further_education_payments", + "admin", + "task_questions", + "provider_verification", + key, + "label" + ].join(".") + ) + end + + def claimant_answer(key) + case key + when "subjects_taught" + subjects_taught + when "courses_taught" + courses_taught + when "further_education_teaching_start_year" + "September #{claim.eligibility.further_education_teaching_start_year} to August #{claim.eligibility.further_education_teaching_start_year.to_i + 1}" + else + I18n.t( + [ + "further_education_payments", + "admin", + "task_questions", + "provider_verification", + key, + "claimant_answers", + claim.eligibility.send(key) + ].join(".") + ) + end + end + + def provider_answer(key) + claim.eligibility.verification.fetch("assertions").find do |assertion| + assertion["name"] == key + end.fetch("outcome") ? "Yes" : "No" + end + + def subjects_taught + claim.eligibility.subjects_taught.map do |subject| + I18n.t( + [ + "further_education_payments", + "forms", + "subjects_taught", + "options", + subject + ].join(".") + ) + end + end + + def courses_taught + claim.eligibility.courses_taught.map(&:description) + end + end + end +end diff --git a/app/models/policies/further_education_payments/admin_tasks_presenter.rb b/app/models/policies/further_education_payments/admin_tasks_presenter.rb new file mode 100644 index 0000000000..950524c42c --- /dev/null +++ b/app/models/policies/further_education_payments/admin_tasks_presenter.rb @@ -0,0 +1,31 @@ +module Policies + module FurtherEducationPayments + class AdminTasksPresenter + include Admin::PresenterMethods + + attr_reader :claim + + def initialize(claim) + @claim = claim + end + + def provider_verification + AdminProviderVerificationTaskPresenter.new(claim).rows + end + + def provider_name + [verifier.fetch("first_name"), verifier.fetch("last_name")].join(" ") + end + + def provider_verification_submitted? + claim.eligibility.verification.present? + end + + private + + def verifier + @verifier ||= claim.eligibility.verification.fetch("verifier") + end + end + end +end diff --git a/app/models/policies/further_education_payments/eligibility_admin_answers_presenter.rb b/app/models/policies/further_education_payments/eligibility_admin_answers_presenter.rb new file mode 100644 index 0000000000..5494eb3b02 --- /dev/null +++ b/app/models/policies/further_education_payments/eligibility_admin_answers_presenter.rb @@ -0,0 +1,17 @@ +module Policies + module FurtherEducationPayments + class EligibilityAdminAnswersPresenter + include Admin::PresenterMethods + + attr_reader :eligibility + + def initialize(eligibility) + @eligibility = eligibility + end + + def answers + [] + end + end + end +end diff --git a/app/models/task.rb b/app/models/task.rb index ecfff3e220..fe3d9d7af5 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -9,6 +9,7 @@ class Task < ApplicationRecord NAMES = %w[ identity_confirmation + provider_verification visa arrival_date qualifications diff --git a/app/views/admin/tasks/provider_verification.html.erb b/app/views/admin/tasks/provider_verification.html.erb new file mode 100644 index 0000000000..9fe6a6faf9 --- /dev/null +++ b/app/views/admin/tasks/provider_verification.html.erb @@ -0,0 +1,75 @@ +<% content_for(:page_title) { page_title("Claim #{@claim.reference} provider verification check for# {@claim.policy.short_name}") } %> +<%= link_to "Back", admin_claim_tasks_path(claim_id: @claim.id), class: "govuk-back-link" %> +<%= render "shared/error_summary", instance: @task, errored_field_id_overrides: { "passed": "task_passed_true" } if @task.errors.any? %> + +
+ + <%= render "claim_summary", claim: @claim, heading: "Provider verification" %> + +
+

<%= @current_task_name.humanize %>

+ + <% if @tasks_presenter.provider_verification_submitted? %> +

+ This task was verified by the provider + (<%= @tasks_presenter.provider_name %>). +

+ + + + + + + + + + + + <% @tasks_presenter.provider_verification.each do |row| %> + + + + + + <% end %> + +
+ <%= @current_task_name.humanize %> +
+ Eligibility check + + Claimant submitted + + Provider response +
+ <%= row.label %> + + <%= Array.wrap(row.claimant_answer).join("

").html_safe %> +
+ <%= row.provider_answer %> +
+ <% else %> +

+ This task is pending verification by the provider +

+

+ Provider verification link <%= govuk_link_to( + Journeys::FurtherEducationPayments::Provider::SlugSequence.verify_claim_url(@claim), + Journeys::FurtherEducationPayments::Provider::SlugSequence.verify_claim_url(@claim) + ) %> +

+ <% end %> +
+ + <% if @tasks_presenter.provider_verification_submitted? %> +
+ <% if @task.persisted? %> + <%= render "task_outcome", task: @task, notes: @notes %> + <% else %> + <%= render "form", task_name: "provider_verification", claim: @claim %> + <% end %> + + <%= render partial: "admin/task_pagination" %> +
+ <% end %> +
diff --git a/config/locales/en.yml b/config/locales/en.yml index 9001a8786d..df73a689c7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -138,6 +138,7 @@ en: employment: "Check employment information" matching_details: "Review matching details from other claims" identity_confirmation: "Confirm the claimant made the claim" + provider_verification: "Confirm the provider verification" payroll_gender: "Add a payroll gender for HMRC" student_loan_amount: "Check student loan amount" student_loan_plan: "Check student loan plan" @@ -149,6 +150,8 @@ en: employment_start: "Check employment start date" subject: "Check subject" teaching_hours: "Check teaching hours" + provider_verification: "Confirm the provider verification" + undo_decision: approved: "Undo approval" rejected: "Undo rejection" @@ -827,6 +830,38 @@ en: feedback_email: "FE-Levellingup.PremiumPayments@education.gov.uk" support_email_address: "FE-Levellingup.PremiumPayments@education.gov.uk" claim_subject: "Further education payment" + admin: + task_questions: + provider_verification: + title: "Has the provider confirmed the claimant's employment?" + contract_type: + label: "Contract of employment" + claimant_answers: + permanent: "Permanent" + fixed_term: "Fixed term" + variable_hours: "Variable hours" + teaching_responsibilities: + label: "Teaching responsibilities" + claimant_answers: + true: "Yes" + false: "No" + further_education_teaching_start_year: + label: "First 5 years of teaching" + teaching_hours_per_week: + label: "Timetabled teaching hours" + claimant_answers: + more_than_12: "More than 12 hours per week" + between_2_5_and_12: "Between 2.5 and 12 hours per week" + less_than_2_5: "Less than 2.5 hours per week" + half_teaching_hours: + label: "Age range taught" + claimant_answers: + true: "Yes" + false: "No" + subjects_taught: + label: "Subject" + courses_taught: + label: "Course" forms: ineligible: courses: diff --git a/spec/factories/policies/further_education_payments/eligibilities.rb b/spec/factories/policies/further_education_payments/eligibilities.rb index 478ca85c5c..7232301333 100644 --- a/spec/factories/policies/further_education_payments/eligibilities.rb +++ b/spec/factories/policies/further_education_payments/eligibilities.rb @@ -7,6 +7,15 @@ end trait :verified do + contract_type { "permanent" } + teaching_responsibilities { true } + further_education_teaching_start_year { "2023" } + teaching_hours_per_week { "more_than_12" } + hours_teaching_eligible_subjects { false } + half_teaching_hours { true } + subjects_taught { ["maths", "physics"] } + maths_courses { ["approved_level_321_maths", "gcse_maths"] } + physics_courses { ["gcse_physics"] } verification do { "assertions" => [ diff --git a/spec/features/admin/admin_claim_further_education_payments_spec.rb b/spec/features/admin/admin_claim_further_education_payments_spec.rb new file mode 100644 index 0000000000..b2fe6d84f7 --- /dev/null +++ b/spec/features/admin/admin_claim_further_education_payments_spec.rb @@ -0,0 +1,147 @@ +require "rails_helper" + +RSpec.feature "Admin claim further education payments" do + before do + create(:journey_configuration, :further_education_payments_provider) + sign_in_as_service_operator + end + + describe "Tasks" do + describe "provider verification task" do + context "when the provider is yet to verify the claim" do + it "shows the task as pending" do + fe_provider = create(:school, :further_education, name: "Springfield A and M") + + claim = create( + :claim, + first_name: "Edna", + surname: "Krabappel", + date_of_birth: Date.new(1945, 7, 3), + reference: "AB123456", + created_at: DateTime.new(2024, 8, 1, 9, 0, 0), + submitted_at: DateTime.new(2024, 8, 1, 9, 0, 0) + ) + + create( + :further_education_payments_eligibility, + contract_type: "fixed_term", + claim: claim, + school: fe_provider, + award_amount: 1500 + ) + + visit admin_claim_path(claim) + + click_on "View tasks" + + click_on "Confirm the provider verification" + + expect(page).to have_content( + "This task is pending verification by the provider" + ) + end + end + + context "when the provider has verified the claim" do + context "when the claim is for a fixed term contract" do + it "shows the verification information and allows the admin to complete the task" do + fe_provider = create(:school, :further_education, name: "Springfield A and M") + + claim = create( + :claim, + first_name: "Edna", + surname: "Krabappel", + date_of_birth: Date.new(1945, 7, 3), + reference: "AB123456", + created_at: DateTime.new(2024, 8, 1, 9, 0, 0), + submitted_at: DateTime.new(2024, 8, 1, 9, 0, 0) + ) + + create( + :further_education_payments_eligibility, + :verified, + contract_type: "fixed_term", + claim: claim, + school: fe_provider, + award_amount: 1500 + ) + + visit admin_claim_path(claim) + + click_on "View tasks" + + click_on "Confirm the provider verification" + + expect(page).to have_content( + "This task was verified by the provider (Seymoure Skinner)" + ) + + within_table_row("Contract of employment") do |claimant, provider| + expect(claimant).to have_text("Fixed term") + expect(provider).to have_text("Yes") + end + + within_table_row("Teaching responsibilities") do |claimant, provider| + expect(claimant).to have_text("Yes") + expect(provider).to have_text("Yes") + end + + within_table_row("First 5 years of teaching") do |claimant, provider| + expect(claimant).to have_text "September 2023 to August 2024" + expect(provider).to have_text "Yes" + end + + within_table_row("Timetabled teaching hours") do |claimant, provider| + expect(claimant).to have_text("More than 12 hours per week") + expect(provider).to have_text("Yes") + end + + within_table_row("Age range taught") do |claimant, provider| + expect(claimant).to have_text("Yes") + expect(provider).to have_text("No") + end + + within_table_row("Subject") do |claimant, provider| + expect(claimant).to have_text("Maths") + expect(claimant).to have_text("Physics") + expect(provider).to have_text("No") + end + + within_table_row("Course") do |claimant, provider| + expect(claimant).to have_content( + "Qualifications approved for funding at level 3 and below in " \ + "the mathematics and statistics (opens in new tab) sector subject area" \ + "GCSE in maths, functional skills qualifications and other " \ + "maths qualifications (opens in new tab) approved for teaching " \ + "to 16 to 19-year-olds who meet the condition of funding" \ + "GCSE physics" + ) + + expect(provider).to have_text("No") + end + + within_fieldset("Has the provider confirmed the claimant's employment?") do + choose "Yes" + end + + # FIXME RL: temp disabbling this as the task presenter hasn't been + # updated for the next page. + # click_on "Save and continue" + end + end + + context "when the claim is for a varible hours contract" do + end + end + end + end + + def within_table_row(label, &block) + within(find("tr", text: label)) do + claimant_answer = find("td:first-of-type") + provider_answer = find("td:last-of-type") + + yield(claimant_answer, provider_answer) + end + end +end