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