Skip to content

Commit

Permalink
Merge pull request #2948 from DFE-Digital/CAPT-1546/qa-irp-task
Browse files Browse the repository at this point in the history
CAPT 1546/qa irp task
  • Loading branch information
rjlynch authored Jul 2, 2024
2 parents 4f53a8c + 1f53e01 commit 519e8f8
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 45 deletions.
53 changes: 26 additions & 27 deletions app/models/claim.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

class Claim < ApplicationRecord
MIN_QA_THRESHOLD = 10
NO_STUDENT_LOAN = "not_applicable"
STUDENT_LOAN_PLAN_OPTIONS = StudentLoan::PLANS.dup << NO_STUDENT_LOAN
ADDRESS_ATTRIBUTES = %w[address_line_1 address_line_2 address_line_3 address_line_4 postcode].freeze
Expand Down Expand Up @@ -181,31 +180,6 @@ class Claim < ApplicationRecord
scope :awaiting_qa, -> { approved.qa_required.where(qa_completed_at: nil) }
scope :qa_required, -> { where(qa_required: true) }

# This method's intention is to help make a decision on whether a claim should
# be flagged for QA or not. These criteria need to be met for each academic year:
#
# 1. the first claim to be approved should always be flagged for QA
# 2. subsequently approved claims should be flagged for QA, 1 in 100/MIN_QA_THRESHOLD.
#
# This method should be used every time a new approval decision is being made;
# when used retrospectively, i.e. when several claims have been approved,
# the method returns:
#
# 1. `true` if none of then claims have been flagged for QA
# 2. `true` if some claims have been flagged for QA using a lower MIN_QA_THRESHOLD
# 3. `false` if some claims have been flagged for QA using a higher MIN_QA_THRESHOLD
#
# Newly approved claims should not be flagged for QA for as long as the method
# returns `false`; they should be flagged for QA otherwise.
def self.below_min_qa_threshold?
return false if MIN_QA_THRESHOLD.zero?

claims_approved_so_far = current_academic_year.approved.count
return true if claims_approved_so_far.zero?

(current_academic_year.approved.qa_required.count.to_f / claims_approved_so_far) * 100 <= MIN_QA_THRESHOLD
end

def hold!(reason:, user:)
if holdable? && !held?
self.class.transaction do
Expand Down Expand Up @@ -245,7 +219,32 @@ def holdable?
end

def flaggable_for_qa?
decision_made? && latest_decision.approved? && Claim.below_min_qa_threshold? && !awaiting_qa? && !qa_completed?
decision_made? && latest_decision.approved? && below_min_qa_threshold? && !awaiting_qa? && !qa_completed?
end

# This method's intention is to help make a decision on whether a claim should
# be flagged for QA or not. These criteria need to be met for each academic year:
#
# 1. the first claim to be approved should always be flagged for QA
# 2. subsequently approved claims should be flagged for QA, 1 in 100/MIN_QA_THRESHOLD.
#
# This method should be used every time a new approval decision is being made;
# when used retrospectively, i.e. when several claims have been approved,
# the method returns:
#
# 1. `true` if none of then claims have been flagged for QA
# 2. `true` if some claims have been flagged for QA using a lower MIN_QA_THRESHOLD
# 3. `false` if some claims have been flagged for QA using a higher MIN_QA_THRESHOLD
#
# Newly approved claims should not be flagged for QA for as long as the method
# returns `false`; they should be flagged for QA otherwise.
def below_min_qa_threshold?
return false if policy::MIN_QA_THRESHOLD.zero?

claims_approved_so_far = Claim.by_policy(policy).current_academic_year.approved.count
return true if claims_approved_so_far.zero?

(Claim.by_policy(policy).current_academic_year.approved.qa_required.count.to_f / claims_approved_so_far) * 100 <= policy::MIN_QA_THRESHOLD
end

def qa_completed?
Expand Down
3 changes: 3 additions & 0 deletions app/models/policies/early_career_payments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module EarlyCareerPayments

SEARCHABLE_ELIGIBILITY_ATTRIBUTES = %w[teacher_reference_number].freeze

# Percentage of claims to QA
MIN_QA_THRESHOLD = 10

def eligibility_page_url
"https://www.gov.uk/guidance/early-career-payments-guidance-for-teachers-and-schools"
end
Expand Down
2 changes: 2 additions & 0 deletions app/models/policies/further_education_payments.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module Policies
module FurtherEducationPayments
# Percentage of claims to QA
MIN_QA_THRESHOLD = 10
end
end
3 changes: 3 additions & 0 deletions app/models/policies/international_relocation_payments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ module InternationalRelocationPayments
ELIGIBILITY_MATCHING_ATTRIBUTES = [["passport_number"]].freeze
OTHER_CLAIMABLE_POLICIES = []

# Percentage of claims to QA
MIN_QA_THRESHOLD = 100

# NOTE RL: currently IRP only has a single reply to address, so notify
# doesn't show the address id
def notify_reply_to_id
Expand Down
3 changes: 3 additions & 0 deletions app/models/policies/levelling_up_premium_payments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ module LevellingUpPremiumPayments
POLICY_START_YEAR = AcademicYear.new(2022).freeze
POLICY_END_YEAR = AcademicYear.new(2024).freeze

# Percentage of claims to QA
MIN_QA_THRESHOLD = 10

def notify_reply_to_id
"03ece7eb-2a5b-461b-9c91-6630d0051aa6"
end
Expand Down
3 changes: 3 additions & 0 deletions app/models/policies/student_loans.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module StudentLoans

SEARCHABLE_ELIGIBILITY_ATTRIBUTES = %w[teacher_reference_number].freeze

# Percentage of claims to QA
MIN_QA_THRESHOLD = 10

def eligibility_page_url
"https://www.gov.uk/guidance/teachers-claim-back-your-student-loan-repayments"
end
Expand Down
180 changes: 163 additions & 17 deletions spec/models/claim_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -371,15 +371,15 @@

context "when above the min QA threshold" do
before do
allow(Claim).to receive(:below_min_qa_threshold?).and_return(false)
stub_const("Policies::#{claim.policy}::MIN_QA_THRESHOLD", 0)
end

it { is_expected.to eq(false) }
end

context "when below the min QA threshold" do
before do
allow(Claim).to receive(:below_min_qa_threshold?).and_return(true)
stub_const("Policies::#{claim.policy}::MIN_QA_THRESHOLD", 100)
end

it { is_expected.to eq(true) }
Expand Down Expand Up @@ -597,63 +597,209 @@
end
end

describe ".below_min_qa_threshold?" do
subject { described_class.below_min_qa_threshold? }
describe "#below_min_qa_threshold?" do
let(:policy) { Policies::EarlyCareerPayments }
let(:other_policy) { Policies::POLICIES.detect { |p| p != policy } }

subject { build(:claim, policy: policy).below_min_qa_threshold? }

context "when the MIN_QA_THRESHOLD is set to zero" do
before do
stub_const("Claim::MIN_QA_THRESHOLD", 0)
stub_const("Policies::#{policy}::MIN_QA_THRESHOLD", 0)
end

it { is_expected.to eq(false) }
end

context "when the MIN_QA_THRESHOLD is set to 10" do
before do
stub_const("Claim::MIN_QA_THRESHOLD", 10) unless described_class::MIN_QA_THRESHOLD == 10
stub_const("Policies::#{policy}::MIN_QA_THRESHOLD", 10)
end

context "with no previously approved claims" do
let!(:claims_for_other_policy) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: other_policy,
academic_year: AcademicYear.current
)
end
it { is_expected.to eq(true) }
end

context "with 1 previously approved claim (1 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 1, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(false) }
end

context "with 2 previously approved claims (1 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 1, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_not_flagged_for_qa) { create_list(:claim, 1, :approved, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_not_flagged_for_qa) do
create_list(
:claim,
1,
:approved,
policy: policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(false) }
end

context "with 9 previously approved claims (1 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 1, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_not_flagged_for_qa) { create_list(:claim, 8, :approved, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end

let!(:claims_not_flagged_for_qa) do
create_list(
:claim,
8,
:approved,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_for_other_policy) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: other_policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(false) }
end

context "with 10 previously approved claims (1 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 1, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_not_flagged_for_qa) { create_list(:claim, 9, :approved, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_not_flagged_for_qa) do
create_list(
:claim,
9,
:approved,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_for_other_policy) do
create_list(
:claim,
1,
:approved,
:flagged_for_qa,
policy: other_policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(true) }
end

context "with 11 previously approved claims (2 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 2, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_not_flagged_for_qa) { create_list(:claim, 10, :approved, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
2,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_not_flagged_for_qa) do
create_list(
:claim,
10,
:approved,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_for_other_policy) do
create_list(
:claim,
2,
:approved,
policy: other_policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(false) }
end

context "with 21 previously approved claims (2 flagged for QA)" do
let!(:claims_flagged_for_qa) { create_list(:claim, 2, :approved, :flagged_for_qa, academic_year: AcademicYear.current) }
let!(:claims_not_flagged_for_qa) { create_list(:claim, 19, :approved, academic_year: AcademicYear.current) }
let!(:claims_flagged_for_qa) do
create_list(
:claim,
2,
:approved,
:flagged_for_qa,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_not_flagged_for_qa) do
create_list(
:claim,
19,
:approved,
policy: policy,
academic_year: AcademicYear.current
)
end
let!(:claims_for_other_policy) do
create_list(
:claim,
19,
:approved,
policy: other_policy,
academic_year: AcademicYear.current
)
end

it { is_expected.to eq(true) }
end
Expand Down
4 changes: 3 additions & 1 deletion spec/support/stubbing_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module StubbingHelpers
def disable_claim_qa_flagging
stub_const("Claim::MIN_QA_THRESHOLD", 0)
Policies::POLICIES.each do |policy|
stub_const("Policies::#{policy}::MIN_QA_THRESHOLD", 0)
end
end

def stub_otp_verification(otp_code: "123456", valid: true)
Expand Down

0 comments on commit 519e8f8

Please sign in to comment.