From e67efa1b94c8a9b7f7ad50a45c22f97f90175a39 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Tue, 3 Sep 2024 09:50:21 +0100 Subject: [PATCH] Autmoate admin task If the provider has verified all the information provider by the client we want to mark the task as passed. If the provider hasn't verified all the information from the client we want to mark the task as failed. Tasks are associated with a `DfeSignIn::User` so we need to create one of these for the provider. NOTE that the find_or_create includes the organisation check, we may have providers with multiple organisations, in such cases we'll create a duplicate record for them. The DfeSignIn::User only has a single organisation so if we want to record the organisation the user was logged in as we can't really avoid duplicate users here. --- .../provider/verify_claim_form.rb | 2 + .../claim_verifiers/provider_verification.rb | 64 ++++++ .../policies/further_education_payments.rb | 4 + .../provider/verify_claim_form_spec.rb | 26 ++- .../provider_verification_spec.rb | 202 ++++++++++++++++++ 5 files changed, 294 insertions(+), 4 deletions(-) create mode 100644 app/models/automated_checks/claim_verifiers/provider_verification.rb create mode 100644 spec/models/automated_checks/claim_verifiers/provider_verification_spec.rb diff --git a/app/forms/journeys/further_education_payments/provider/verify_claim_form.rb b/app/forms/journeys/further_education_payments/provider/verify_claim_form.rb index b0ee7ba205..7f6f0ae6aa 100644 --- a/app/forms/journeys/further_education_payments/provider/verify_claim_form.rb +++ b/app/forms/journeys/further_education_payments/provider/verify_claim_form.rb @@ -109,6 +109,8 @@ def save claim.save! + ClaimVerifierJob.perform_later(claim) + true end diff --git a/app/models/automated_checks/claim_verifiers/provider_verification.rb b/app/models/automated_checks/claim_verifiers/provider_verification.rb new file mode 100644 index 0000000000..fc643876f1 --- /dev/null +++ b/app/models/automated_checks/claim_verifiers/provider_verification.rb @@ -0,0 +1,64 @@ +module AutomatedChecks + module ClaimVerifiers + class ProviderVerification + TASK_NAME = "provider_verification".freeze + + def initialize(claim:) + @claim = claim + + unless claim.policy.further_education_payments? + raise ArgumentError, "Claim must be an Further Education claim" + end + end + + def perform + return unless claim.eligibility.verified? + return if task_exists? + + create_task! + end + + private + + attr_reader :claim + + def task_exists? + claim.tasks.where(name: TASK_NAME).exists? + end + + def create_task! + claim.tasks.create!( + name: TASK_NAME, + created_by: created_by, + manual: false, + passed: passed? + ) + end + + def passed? + verification.fetch("assertions").all? do |assertion| + assertion.fetch("outcome") == true + end + end + + def verification + @verification ||= claim.eligibility.verification + end + + def verifier + verification.fetch("verifier") + end + + def created_by + DfeSignIn::User.find_or_create_by!( + dfe_sign_in_id: verifier.fetch("dfe_sign_in_uid"), + given_name: verifier.fetch("first_name"), + family_name: verifier.fetch("last_name"), + email: verifier.fetch("email"), + organisation_name: verifier.fetch("dfe_sign_in_organisation_name"), + role_codes: verifier.fetch("dfe_sign_in_role_codes") + ) + end + end + end +end diff --git a/app/models/policies/further_education_payments.rb b/app/models/policies/further_education_payments.rb index bfe08cf440..ff6d8e82e0 100644 --- a/app/models/policies/further_education_payments.rb +++ b/app/models/policies/further_education_payments.rb @@ -11,6 +11,10 @@ module FurtherEducationPayments URL_SPREADSHEET_ELIGIBLE_PROVIDERS = "https://assets.publishing.service.gov.uk/media/667300fe64e554df3bd0db92/List_of_eligible_FE_providers_and_payment_value_for_levelling_up_premium.xlsx".freeze + VERIFIERS = [ + AutomatedChecks::ClaimVerifiers::ProviderVerification + ] + # Options shown to admins when rejecting a claim ADMIN_DECISION_REJECTED_REASONS = [ # FIXME RL: this `placeholder` is required to make the diff --git a/spec/forms/journeys/further_education_payments/provider/verify_claim_form_spec.rb b/spec/forms/journeys/further_education_payments/provider/verify_claim_form_spec.rb index 90a70a65dd..578560998c 100644 --- a/spec/forms/journeys/further_education_payments/provider/verify_claim_form_spec.rb +++ b/spec/forms/journeys/further_education_payments/provider/verify_claim_form_spec.rb @@ -36,7 +36,7 @@ answers: { claim_id: claim.id, dfe_sign_in_uid: "123", - dfe_sign_in_first_name: "Seymoure", + dfe_sign_in_first_name: "Seymour", dfe_sign_in_last_name: "Skinner", dfe_sign_in_email: "seymour.skinner@springfield-elementary.edu", dfe_sign_in_organisation_name: "Springfield Elementary", @@ -267,11 +267,19 @@ ) end - it "verifies the claim" do + before do + dqt_teacher_resource = instance_double(Dqt::TeacherResource, find: nil) + dqt_client = instance_double(Dqt::Client, teacher: dqt_teacher_resource) + allow(Dqt::Client).to receive(:new).and_return(dqt_client) + travel_to DateTime.new(2024, 1, 1, 12, 0, 0) do - form.save + perform_enqueued_jobs do + form.save + end end + end + it "verifies the claim" do expect(claim.reload.eligibility.verification).to match( { "assertions" => [ @@ -302,7 +310,7 @@ ], "verifier" => { "dfe_sign_in_uid" => "123", - "first_name" => "Seymoure", + "first_name" => "Seymour", "last_name" => "Skinner", "email" => "seymour.skinner@springfield-elementary.edu", "dfe_sign_in_organisation_name" => "Springfield Elementary", @@ -312,5 +320,15 @@ } ) end + + it "creates the provider verification task" do + task = claim.reload.tasks.last + + expect(task.name).to eq("provider_verification") + + expect(task.created_by.email).to eq( + "seymour.skinner@springfield-elementary.edu" + ) + end end end diff --git a/spec/models/automated_checks/claim_verifiers/provider_verification_spec.rb b/spec/models/automated_checks/claim_verifiers/provider_verification_spec.rb new file mode 100644 index 0000000000..73522cff3d --- /dev/null +++ b/spec/models/automated_checks/claim_verifiers/provider_verification_spec.rb @@ -0,0 +1,202 @@ +require "rails_helper" + +RSpec.describe AutomatedChecks::ClaimVerifiers::ProviderVerification do + describe "#initialize" do + context "with a non FE claim" do + it "errors" do + claim = create(:claim) + + expect { described_class.new(claim: claim) }.to( + raise_error(ArgumentError, "Claim must be an Further Education claim") + ) + end + end + end + + describe "#perform" do + context "when the claim has not been verified by the provider" do + let(:verification) { {} } + + it "doesn't create a task" do + claim = create( + :further_education_payments_eligibility, + verification: verification + ).claim + + expect { described_class.new(claim: claim).perform }.not_to( + change { claim.tasks.count } + ) + end + end + + context "when the claim has been verified by the provider" do + context "when the task has already been performed" do + it "does not alter the task or create a new one" do + claim = create( + :further_education_payments_eligibility, + :verified + ).claim + + task = create( + :task, + name: "provider_verification", + claim: claim, + passed: true + ) + + expect { described_class.new(claim: claim).perform }.to( + not_change { claim.tasks.count }.and( + not_change { task.reload.updated_at } + ) + ) + end + end + + context "when the task has not been performed" do + context "when the provider has not confirmed the claimants answers" do + it "fails the task" do + claim = create( + :further_education_payments_eligibility, + verification: { + assertions: [ + {name: "contract_type", outcome: false} + ], + verifier: { + dfe_sign_in_uid: "123", + first_name: "Seymour", + last_name: "Skinner", + email: "seymore.skinner@springfield-elementary.edu", + dfe_sign_in_organisation_name: "Springfield Elementary", + dfe_sign_in_role_codes: ["teacher_payments_claim_verifier"] + }, + created_at: Time.zone.now + } + ).claim + + expect { described_class.new(claim: claim).perform }.to( + change { claim.tasks.count }.from(0).to(1).and( + change(DfeSignIn::User, :count).from(0).to(1) + ) + ) + + task = claim.tasks.last + + expect(task.name).to eq("provider_verification") + expect(task.passed).to eq(false) + expect(task.manual).to eq(false) + + dfe_sign_in_user = task.created_by + + expect(dfe_sign_in_user.dfe_sign_in_id).to eq("123") + expect(dfe_sign_in_user.given_name).to eq("Seymour") + expect(dfe_sign_in_user.family_name).to eq("Skinner") + expect(dfe_sign_in_user.email).to eq( + "seymore.skinner@springfield-elementary.edu" + ) + expect(dfe_sign_in_user.organisation_name).to eq( + "Springfield Elementary" + ) + expect(dfe_sign_in_user.role_codes).to eq( + ["teacher_payments_claim_verifier"] + ) + end + end + + context "when the provider has confirmed the claimants answers" do + it "passes the task" do + claim = create( + :further_education_payments_eligibility, + verification: { + assertions: [ + {name: "contract_type", outcome: true} + ], + verifier: { + dfe_sign_in_uid: "123", + first_name: "Seymour", + last_name: "Skinner", + email: "seymore.skinner@springfield-elementary.edu", + dfe_sign_in_organisation_name: "Springfield Elementary", + dfe_sign_in_role_codes: ["teacher_payments_claim_verifier"] + }, + created_at: Time.zone.now + } + ).claim + + expect { described_class.new(claim: claim).perform }.to( + change { claim.tasks.count }.from(0).to(1).and( + change(DfeSignIn::User, :count).from(0).to(1) + ) + ) + + task = claim.tasks.last + + expect(task.name).to eq("provider_verification") + expect(task.passed).to eq(true) + expect(task.manual).to eq(false) + + dfe_sign_in_user = task.created_by + + expect(dfe_sign_in_user.dfe_sign_in_id).to eq("123") + expect(dfe_sign_in_user.given_name).to eq("Seymour") + expect(dfe_sign_in_user.family_name).to eq("Skinner") + expect(dfe_sign_in_user.email).to eq( + "seymore.skinner@springfield-elementary.edu" + ) + expect(dfe_sign_in_user.organisation_name).to eq( + "Springfield Elementary" + ) + expect(dfe_sign_in_user.role_codes).to eq( + ["teacher_payments_claim_verifier"] + ) + end + end + + context "when the verifier already exists" do + it "does not create a new verifier" do + dfe_sign_in_user = create( + :dfe_signin_user, + dfe_sign_in_id: "123", + given_name: "Seymour", + family_name: "Skinner", + email: "seymore.skinner@springfield-elementary.edu", + organisation_name: "Springfield Elementary", + role_codes: ["teacher_payments_claim_verifier"] + ) + + claim = create( + :further_education_payments_eligibility, + verification: { + assertions: [ + {name: "contract_type", outcome: true} + ], + verifier: { + dfe_sign_in_uid: "123", + first_name: "Seymour", + last_name: "Skinner", + email: "seymore.skinner@springfield-elementary.edu", + dfe_sign_in_organisation_name: "Springfield Elementary", + dfe_sign_in_role_codes: ["teacher_payments_claim_verifier"] + }, + created_at: Time.zone.now + } + ).claim + + expect { described_class.new(claim: claim).perform }.to( + change { claim.tasks.count }.from(0).to(1).and( + not_change(DfeSignIn::User, :count) + ) + ) + + task = claim.tasks.last + + expect(task.name).to eq("provider_verification") + expect(task.passed).to eq(true) + expect(task.manual).to eq(false) + + expect(task.created_by).to eq(dfe_sign_in_user) + end + end + end + end + end +end