From a71315b7a7227a8810ff8c74fd8d62f4d5d89637 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 11:14:14 +0000 Subject: [PATCH 01/17] Inline concerns Part of refactoring to remove ECP. These concerns are only used in these classes, inlining them to make tracking the difference between ECP and LUP easier. --- .../early_career_payments/eligible.rb | 94 ------------------- .../levelling_up_premium_payments/eligible.rb | 87 ----------------- .../policy_eligibility_checker.rb | 90 +++++++++++++++++- .../policy_eligibility_checker.rb | 83 +++++++++++++++- 4 files changed, 171 insertions(+), 183 deletions(-) delete mode 100644 app/models/concerns/policies/early_career_payments/eligible.rb delete mode 100644 app/models/concerns/policies/levelling_up_premium_payments/eligible.rb diff --git a/app/models/concerns/policies/early_career_payments/eligible.rb b/app/models/concerns/policies/early_career_payments/eligible.rb deleted file mode 100644 index 6899541abb..0000000000 --- a/app/models/concerns/policies/early_career_payments/eligible.rb +++ /dev/null @@ -1,94 +0,0 @@ -module Policies - module EarlyCareerPayments - module Eligible - def policy - Policies::EarlyCareerPayments - end - - def induction_not_completed? - !induction_completed.nil? && !induction_completed? - end - - def ecp_only_school? - Policies::EarlyCareerPayments::SchoolEligibility.new(current_school).eligible? && - !Policies::LevellingUpPremiumPayments::SchoolEligibility.new(current_school).eligible? - end - - def calculate_award_amount - return 0 if eligible_itt_subject.blank? - - args = {policy_year: claim_year, itt_year: itt_academic_year, subject_symbol: eligible_itt_subject.to_sym, school: current_school} - - if args.values.any?(&:blank?) - 0 - else - Policies::EarlyCareerPayments::AwardAmountCalculator.new(**args).amount_in_pounds - end - end - - private - - def specific_eligible_now_attributes? - induction_completed? && itt_subject_eligible_now? - end - - def itt_subject_eligible_now? - itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case - return false if itt_subject.blank? - return false if itt_subject_none_of_the_above? - - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) - end - - def specific_ineligible_attributes? - trainee_teacher? || (induction_not_completed? && !any_future_policy_years?) || itt_subject_ineligible_now_and_in_the_future? - end - - def itt_subject_ineligible_now_and_in_the_future? - itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case - return false if itt_subject.blank? - return true if itt_subject_none_of_the_above? - - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - !itt_subject.to_sym.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) - end - - def specific_eligible_later_attributes? - newly_qualified_teacher? && ((induction_not_completed? && any_future_policy_years?) || (!itt_subject_eligible_now? && itt_subject_eligible_later?)) - end - - def itt_subject_eligible_later? - itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case - return false if itt_subject.blank? - return false if itt_subject_none_of_the_above? - - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - itt_subject.to_sym.in?(itt_subject_checker.future_subject_symbols(policy)) - end - - # TODO: Is this used anywhere? - def itt_subject_ineligible? - return false if claim_year.blank? - - itt_subject_other_than_those_eligible_now_or_in_the_future? - end - - def itt_subject_other_than_those_eligible_now_or_in_the_future? - itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case - return false if itt_subject.blank? - - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.any?(&:blank?) - # can still rule some out - itt_subject_none_of_the_above? - else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - itt_subject_symbol = itt_subject.to_sym - !itt_subject_symbol.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) - end - end - end - end -end diff --git a/app/models/concerns/policies/levelling_up_premium_payments/eligible.rb b/app/models/concerns/policies/levelling_up_premium_payments/eligible.rb deleted file mode 100644 index 6ca6bbb858..0000000000 --- a/app/models/concerns/policies/levelling_up_premium_payments/eligible.rb +++ /dev/null @@ -1,87 +0,0 @@ -module Policies - module LevellingUpPremiumPayments - module Eligible - def policy - Policies::LevellingUpPremiumPayments - end - - def indicated_ineligible_itt_subject? - return false if eligible_itt_subject.blank? - - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.values.any?(&:blank?) - # trainee teacher who won't have given their ITT year - eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) - else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) - end - end - - def calculate_award_amount - premium_payment_award&.award_amount - end - - private - - def premium_payment_award - return unless current_school.present? - - current_school.levelling_up_premium_payments_awards.find_by( - academic_year: claim_year.to_s - ) - end - - def indicated_ecp_only_itt_subject? - eligible_itt_subject.present? && (eligible_itt_subject.to_sym == :foreign_languages) - end - - def specific_eligible_now_attributes? - eligible_itt_subject_or_relevant_degree? - end - - def eligible_itt_subject_or_relevant_degree? - good_itt_subject? || eligible_degree? - end - - def good_itt_subject? - return false if eligible_itt_subject.blank? - - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.values.any?(&:blank?) - # trainee teacher who won't have given their ITT year - eligible_itt_subject.present? && eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) - else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) - end - end - - def eligible_degree? - eligible_degree_subject? - end - - def specific_ineligible_attributes? - indicated_ecp_only_itt_subject? || trainee_teacher_with_ineligible_itt_subject? || ineligible_itt_subject_and_no_relevant_degree? - end - - def trainee_teacher_with_ineligible_itt_subject? - trainee_teacher? && indicated_ineligible_itt_subject? - end - - def ineligible_itt_subject_and_no_relevant_degree? - indicated_ineligible_itt_subject? && lacks_eligible_degree? - end - - def specific_eligible_later_attributes? - trainee_teacher? && eligible_itt_subject_or_relevant_degree? - end - - def lacks_eligible_degree? - eligible_degree_subject == false - end - end - end -end diff --git a/app/models/policies/early_career_payments/policy_eligibility_checker.rb b/app/models/policies/early_career_payments/policy_eligibility_checker.rb index d634e75ffb..f6420fe664 100644 --- a/app/models/policies/early_career_payments/policy_eligibility_checker.rb +++ b/app/models/policies/early_career_payments/policy_eligibility_checker.rb @@ -1,7 +1,6 @@ module Policies module EarlyCareerPayments class PolicyEligibilityChecker - include Eligible include EligibilityCheckable attr_reader :answers @@ -11,6 +10,95 @@ class PolicyEligibilityChecker def initialize(answers:) @answers = answers end + + def policy + Policies::EarlyCareerPayments + end + + def induction_not_completed? + !induction_completed.nil? && !induction_completed? + end + + def ecp_only_school? + Policies::EarlyCareerPayments::SchoolEligibility.new(current_school).eligible? && + !Policies::LevellingUpPremiumPayments::SchoolEligibility.new(current_school).eligible? + end + + def calculate_award_amount + return 0 if eligible_itt_subject.blank? + + args = {policy_year: claim_year, itt_year: itt_academic_year, subject_symbol: eligible_itt_subject.to_sym, school: current_school} + + if args.values.any?(&:blank?) + 0 + else + Policies::EarlyCareerPayments::AwardAmountCalculator.new(**args).amount_in_pounds + end + end + + private + + def specific_eligible_now_attributes? + induction_completed? && itt_subject_eligible_now? + end + + def itt_subject_eligible_now? + itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case + return false if itt_subject.blank? + return false if itt_subject_none_of_the_above? + + itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) + itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + end + + def specific_ineligible_attributes? + trainee_teacher? || (induction_not_completed? && !any_future_policy_years?) || itt_subject_ineligible_now_and_in_the_future? + end + + def itt_subject_ineligible_now_and_in_the_future? + itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case + return false if itt_subject.blank? + return true if itt_subject_none_of_the_above? + + itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) + !itt_subject.to_sym.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) + end + + def specific_eligible_later_attributes? + newly_qualified_teacher? && ((induction_not_completed? && any_future_policy_years?) || (!itt_subject_eligible_now? && itt_subject_eligible_later?)) + end + + def itt_subject_eligible_later? + itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case + return false if itt_subject.blank? + return false if itt_subject_none_of_the_above? + + itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) + itt_subject.to_sym.in?(itt_subject_checker.future_subject_symbols(policy)) + end + + # TODO: Is this used anywhere? + def itt_subject_ineligible? + return false if claim_year.blank? + + itt_subject_other_than_those_eligible_now_or_in_the_future? + end + + def itt_subject_other_than_those_eligible_now_or_in_the_future? + itt_subject = eligible_itt_subject # attribute name implies eligibility which isn't always the case + return false if itt_subject.blank? + + args = {claim_year: claim_year, itt_year: itt_academic_year} + + if args.any?(&:blank?) + # can still rule some out + itt_subject_none_of_the_above? + else + itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) + itt_subject_symbol = itt_subject.to_sym + !itt_subject_symbol.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) + end + end end end end diff --git a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb index 353173af08..f753ba0ee7 100644 --- a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb +++ b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb @@ -1,7 +1,6 @@ module Policies module LevellingUpPremiumPayments class PolicyEligibilityChecker - include Eligible include EligibilityCheckable attr_reader :answers @@ -11,6 +10,88 @@ class PolicyEligibilityChecker def initialize(answers:) @answers = answers end + + def policy + Policies::LevellingUpPremiumPayments + end + + def indicated_ineligible_itt_subject? + return false if eligible_itt_subject.blank? + + args = {claim_year: claim_year, itt_year: itt_academic_year} + + if args.values.any?(&:blank?) + # trainee teacher who won't have given their ITT year + eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) + else + itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) + eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + end + end + + def calculate_award_amount + premium_payment_award&.award_amount + end + + private + + def premium_payment_award + return unless current_school.present? + + current_school.levelling_up_premium_payments_awards.find_by( + academic_year: claim_year.to_s + ) + end + + def indicated_ecp_only_itt_subject? + eligible_itt_subject.present? && (eligible_itt_subject.to_sym == :foreign_languages) + end + + def specific_eligible_now_attributes? + eligible_itt_subject_or_relevant_degree? + end + + def eligible_itt_subject_or_relevant_degree? + good_itt_subject? || eligible_degree? + end + + def good_itt_subject? + return false if eligible_itt_subject.blank? + + args = {claim_year: claim_year, itt_year: itt_academic_year} + + if args.values.any?(&:blank?) + # trainee teacher who won't have given their ITT year + eligible_itt_subject.present? && eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) + else + itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) + eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + end + end + + def eligible_degree? + eligible_degree_subject? + end + + def specific_ineligible_attributes? + indicated_ecp_only_itt_subject? || trainee_teacher_with_ineligible_itt_subject? || ineligible_itt_subject_and_no_relevant_degree? + end + + def trainee_teacher_with_ineligible_itt_subject? + trainee_teacher? && indicated_ineligible_itt_subject? + end + + def ineligible_itt_subject_and_no_relevant_degree? + indicated_ineligible_itt_subject? && lacks_eligible_degree? + end + + def specific_eligible_later_attributes? + trainee_teacher? && eligible_itt_subject_or_relevant_degree? + end + + def lacks_eligible_degree? + eligible_degree_subject == false + end end end end From 2cf0f5e7a212e81fb877bb5b0a88c25a618ccaf8 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 11:39:45 +0000 Subject: [PATCH 02/17] Inline trainee_teacher? method This was the only method EligibilityCheckable was being pulled in for. While we're duplicating the definition of a trainee teacher, inlining the method here will make splitting up the EligibilityCheckable policy easier. --- .../nqt_in_academic_year_after_itt_form.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/forms/journeys/additional_payments_for_teaching/nqt_in_academic_year_after_itt_form.rb b/app/forms/journeys/additional_payments_for_teaching/nqt_in_academic_year_after_itt_form.rb index c851cee4ed..7e3ecb013b 100644 --- a/app/forms/journeys/additional_payments_for_teaching/nqt_in_academic_year_after_itt_form.rb +++ b/app/forms/journeys/additional_payments_for_teaching/nqt_in_academic_year_after_itt_form.rb @@ -1,8 +1,6 @@ module Journeys module AdditionalPaymentsForTeaching class NqtInAcademicYearAfterIttForm < Form - include EligibilityCheckable - attribute :nqt_in_academic_year_after_itt, :boolean validates :nqt_in_academic_year_after_itt, inclusion: {in: [true, false], message: i18n_error_message(:inclusion)} @@ -23,6 +21,10 @@ def save private + def trainee_teacher? + nqt_in_academic_year_after_itt == false + end + def determine_induction_answer_from_dqt_record return unless passed_details_check_with_teacher_id? # We can derive the induction_completed value for current_claim using the From ac18ee74cf297af98bec1faca41226dcaac3db53 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 14:23:41 +0000 Subject: [PATCH 03/17] Use POLICY_END_YEAR FINAL_LUP_POLICY_YEAR is a dupe of Lup::POLICY_END_YEAR. We should have updated Lup::POLICY_END_YEAR to 2025 as part of capt-1832 --- app/models/concerns/eligibility_checkable.rb | 1 - app/models/journeys/additional_payments_for_teaching.rb | 9 +-------- app/models/policies/levelling_up_premium_payments.rb | 2 +- spec/lib/ineligibility_reason_checker_spec.rb | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index b5decfc117..77cd0f2dda 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -3,7 +3,6 @@ module EligibilityCheckable FIRST_COMBINED_ECP_AND_LUP_POLICY_YEAR = AcademicYear.new(2022) FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR = AcademicYear.new(2024) - FINAL_LUP_POLICY_YEAR = AcademicYear.new(2025) COMBINED_ECP_AND_LUP_POLICY_YEARS = FIRST_COMBINED_ECP_AND_LUP_POLICY_YEAR..FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR = FIRST_COMBINED_ECP_AND_LUP_POLICY_YEAR...FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR diff --git a/app/models/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index 83c2dbafb6..a217a6abf4 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -30,16 +30,9 @@ module AdditionalPaymentsForTeaching } }.freeze - def final_policy_year(policy) - { - Policies::EarlyCareerPayments => EligibilityCheckable::FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR, - Policies::LevellingUpPremiumPayments => EligibilityCheckable::FINAL_LUP_POLICY_YEAR - }[policy] - end - def set_a_reminder?(itt_academic_year:, policy:) policy_year = configuration.current_academic_year - return false if policy_year >= final_policy_year(policy) + return false if policy_year >= policy::POLICY_END_YEAR next_year = policy_year + 1 eligible_itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(next_year) diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 6926875a2f..3679b8c1a4 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -27,7 +27,7 @@ module LevellingUpPremiumPayments SEARCHABLE_ELIGIBILITY_ATTRIBUTES = %w[teacher_reference_number].freeze POLICY_START_YEAR = AcademicYear.new(2022).freeze - POLICY_END_YEAR = AcademicYear.new(2024).freeze + POLICY_END_YEAR = AcademicYear.new(2025).freeze # Percentage of claims to QA MIN_QA_THRESHOLD = 10 diff --git a/spec/lib/ineligibility_reason_checker_spec.rb b/spec/lib/ineligibility_reason_checker_spec.rb index d2c19ada0a..4547608848 100644 --- a/spec/lib/ineligibility_reason_checker_spec.rb +++ b/spec/lib/ineligibility_reason_checker_spec.rb @@ -278,7 +278,7 @@ :additional_payments_answers, :ecp_and_lup_eligible, :trainee_teacher, - academic_year: AcademicYear.new(2024), + academic_year: AcademicYear.new(2025), current_school_id: school.id ) end From 5bec77a36c4307f0529940ff99baebee30f9a9c5 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 16:13:31 +0000 Subject: [PATCH 04/17] Remove method This method is only used in the specs. Inline the method to where it's used and remove the method and it's tests. One less thing to keep track off! --- lib/journey_subject_eligibility_checker.rb | 11 - ...in_claim_tasks_update_with_dqt_api_spec.rb | 17 +- ...ourney_subject_eligibility_checker_spec.rb | 202 ------------------ 3 files changed, 12 insertions(+), 218 deletions(-) diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb index e1f527a33d..82a2fb82a3 100644 --- a/lib/journey_subject_eligibility_checker.rb +++ b/lib/journey_subject_eligibility_checker.rb @@ -62,17 +62,6 @@ def self.fixed_lup_subject_symbols [:chemistry, :computing, :mathematics, :physics] end - # NOTE: ONLY used by specs - def self.first_eligible_itt_year_for_subject(policy:, claim_year:, subject_symbol:) - raise "[#{subject_symbol}] is not a symbol" unless subject_symbol.is_a?(Symbol) - itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(claim_year) - - itt_years.detect do |itt_year| - checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_year) - subject_symbol.in?(checker.current_subject_symbols(policy)) - end - end - def current_and_future_subject_symbols(policy) (current_subject_symbols(policy) + future_subject_symbols(policy)).uniq end diff --git a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb index 77639b8b7f..ad1925536a 100644 --- a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb +++ b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb @@ -139,11 +139,18 @@ def task_outcome end let(:first_eligible_itt_academic_year) { - JourneySubjectEligibilityChecker.first_eligible_itt_year_for_subject( - policy: claim.eligibility.policy, - claim_year: Journeys.for_policy(claim.eligibility.policy).configuration.current_academic_year, - subject_symbol: claim.eligibility.eligible_itt_subject.to_sym - ) + subject_symbol = claim.eligibility.eligible_itt_subject.to_sym + + policy = claim.eligibility.policy + + claim_year = Journeys.for_policy(policy).configuration.current_academic_year + + itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(claim_year) + + itt_years.detect do |itt_year| + checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_year) + subject_symbol.in?(checker.current_subject_symbols(policy)) + end } context "with EarlyCareerPayments policy" do diff --git a/spec/lib/journey_subject_eligibility_checker_spec.rb b/spec/lib/journey_subject_eligibility_checker_spec.rb index ca4f792b69..9bf76d9aa4 100644 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ b/spec/lib/journey_subject_eligibility_checker_spec.rb @@ -980,208 +980,6 @@ end end - describe ".first_eligible_itt_year_for_subject" do - subject { described_class.first_eligible_itt_year_for_subject(policy: policy, claim_year: claim_year, subject_symbol: subject_symbol) } - - context "string instead of symbol" do - specify { expect { described_class.first_eligible_itt_year_for_subject(policy: Policies::EarlyCareerPayments, claim_year: AcademicYear.new(2022), subject_symbol: "mathematics") }.to raise_error "[mathematics] is not a symbol" } - end - - context "ECP" do - let(:policy) { Policies::EarlyCareerPayments } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2019)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "computing" do - let(:subject_symbol) { :computing } - - it { is_expected.to be_nil } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2018)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "computing" do - let(:subject_symbol) { :computing } - - it { is_expected.to be_nil } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2019)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - - context "computing" do - let(:subject_symbol) { :computing } - - it { is_expected.to be_nil } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to eq(AcademicYear.new(2020)) } - end - end - end - - context "LUP" do - let(:policy) { Policies::LevellingUpPremiumPayments } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2017)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2017)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2017)) } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to be_nil } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2018)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2018)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2018)) } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to be_nil } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "mathematics" do - let(:subject_symbol) { :mathematics } - - it { is_expected.to eq(AcademicYear.new(2019)) } - end - - context "physics" do - let(:subject_symbol) { :physics } - - it { is_expected.to eq(AcademicYear.new(2019)) } - end - - context "chemistry" do - let(:subject_symbol) { :chemistry } - - it { is_expected.to eq(AcademicYear.new(2019)) } - end - - context "languages" do - let(:subject_symbol) { :foreign_languages } - - it { is_expected.to be_nil } - end - end - end - end - describe ".fixed_lup_subject_symbols" do specify { expect(described_class.fixed_lup_subject_symbols).to contain_exactly(:chemistry, :computing, :mathematics, :physics) } end From 2afe1bf52ab5f8c3059401446e062fb511eda161 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 16:45:03 +0000 Subject: [PATCH 05/17] Split subject symbols by policy Splits this method by policy so it's easier to break out LUP into it's own journey. --- app/models/academic_year.rb | 6 +++ app/models/policies/early_career_payments.rb | 25 +++++++++++ .../policies/levelling_up_premium_payments.rb | 12 ++++++ lib/journey_subject_eligibility_checker.rb | 41 +------------------ 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/app/models/academic_year.rb b/app/models/academic_year.rb index a0588564e7..52180578b1 100644 --- a/app/models/academic_year.rb +++ b/app/models/academic_year.rb @@ -67,6 +67,12 @@ def for(date) new(date.year) end end + + def wrap(value) + return value if value.is_a? AcademicYear + + new(value) + end end def initialize(year_or_academic_year_or_string = nil) diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index 203b3475e4..554f466a2e 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -109,5 +109,30 @@ def payment_and_deductions_info_url def auto_check_student_loan_plan_task? true end + + def subject_symbols(claim_year:, itt_year:) + case AcademicYear.wrap(claim_year) + when AcademicYear.new(2022), AcademicYear.new(2024) + case AcademicYear.wrap(itt_year) + when AcademicYear.new(2019) + [:mathematics] + when AcademicYear.new(2020) + [:chemistry, :foreign_languages, :mathematics, :physics] + else + [] + end + when AcademicYear.new(2023) + case AcademicYear.wrap(itt_year) + when AcademicYear.new(2018) + [:mathematics] + when AcademicYear.new(2020) + [:chemistry, :foreign_languages, :mathematics, :physics] + else + [] + end + else + [] + end + end end end diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 3679b8c1a4..fb990dd6d8 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -99,5 +99,17 @@ def payroll_file_name def auto_check_student_loan_plan_task? true end + + def subject_symbols(claim_year:, itt_year:) + return [] unless (POLICY_START_YEAR..POLICY_END_YEAR).cover?(claim_year) + + previous_five_years = (claim_year - 5)...claim_year + + if previous_five_years.cover?(itt_year) + [:chemistry, :computing, :mathematics, :physics] + else + [] + end + end end end diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb index 82a2fb82a3..0b432b03e0 100644 --- a/lib/journey_subject_eligibility_checker.rb +++ b/lib/journey_subject_eligibility_checker.rb @@ -115,45 +115,6 @@ def none_of_the_above?(itt_year) def subject_symbols(policy:, claim_year:, itt_year:) raise "Unsupported policy: #{policy}" unless policy.in?(Journeys::AdditionalPaymentsForTeaching::POLICIES) - case policy - when Policies::EarlyCareerPayments - year = claim_year.is_a?(AcademicYear) ? claim_year : AcademicYear.new(claim_year) - case year - when AcademicYear.new(2022), AcademicYear.new(2024) - case itt_year - when AcademicYear.new(2019) - [:mathematics] - when AcademicYear.new(2020) - [:chemistry, :foreign_languages, :mathematics, :physics] - else - [] - end - when AcademicYear.new(2023) - case itt_year - when AcademicYear.new(2018) - [:mathematics] - when AcademicYear.new(2020) - [:chemistry, :foreign_languages, :mathematics, :physics] - else - [] - end - else - [] - end - when Policies::LevellingUpPremiumPayments - case claim_year - when EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS - year = itt_year.is_a?(AcademicYear) ? itt_year : AcademicYear.new(itt_year) - - case year - when (claim_year - 5)...claim_year - [:chemistry, :computing, :mathematics, :physics] - else - [] - end - else - [] - end - end + policy.subject_symbols(claim_year: claim_year, itt_year: itt_year) end end From f94942a4e4e0d2083bec4dc8bcb7a7353257bac5 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Mon, 18 Nov 2024 16:58:14 +0000 Subject: [PATCH 06/17] Move selectable_subject_symbols into the journey. There was a lot of duplicated business rules in this method. We were explicity checking for `nqt_in_academic_year_after_itt`, and if it was absent we were falling back to only the lup subjects. The ECP policy is ineligible for non `nqt_in_academic_year_after_itt` claims so it will be filtered out when we check for `potentially_still_eligible_policies`. We returned an empty array if the `current_academic_year` was outside the lup policy dates, however the LUP#subject_symbols method already returns an empty array of available subjects for years outside the policy. There's some weirdness in the `AdditionalPaymentsForTeaching.selectable_subject_symbols` method. If we're dealing with a trainee teacher, we return a hard coded list of subjects, however trainee teachers won't be eligible as the `EligibilityCheckable#common_ineligible_attributes?` checks if the claimant is a trainee teacher, and is thus ineligible. It seems weird to return a list of subjects if the claimant is ineligible. This was the existing behaviour so I've kept it in place but this likely needs revisiting. --- .../eligible_itt_subject_form.rb | 2 +- app/models/academic_year.rb | 6 +- app/models/concerns/eligibility_checkable.rb | 19 +- .../additional_payments_for_teaching.rb | 20 ++ .../answers_presenter.rb | 10 +- app/models/journeys/eligibility_checker.rb | 8 + app/models/journeys/page_sequence.rb | 2 +- app/models/policies/early_career_payments.rb | 35 +++ .../early_career_payments/dqt_record.rb | 7 +- .../policy_eligibility_checker.rb | 25 +- .../policies/levelling_up_premium_payments.rb | 41 +++- .../policy_eligibility_checker.rb | 2 +- lib/ineligibility_reason_checker.rb | 4 +- lib/journey_subject_eligibility_checker.rb | 22 +- .../eligible_itt_subject_form_spec.rb | 17 +- ...ourney_subject_eligibility_checker_spec.rb | 225 ------------------ spec/models/early_career_payments_spec.rb | 111 +++++++++ .../additional_payments_for_teaching_spec.rb | 198 +++++++++++++++ .../levelling_up_premium_payments_spec.rb | 109 +++++++++ .../early_career_payments/dqt_record_spec.rb | 6 +- 20 files changed, 593 insertions(+), 276 deletions(-) diff --git a/app/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form.rb b/app/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form.rb index 1904af7ab6..199a069f0a 100644 --- a/app/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form.rb +++ b/app/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form.rb @@ -50,7 +50,7 @@ def chemistry_or_physics_available? def subject_symbols @subject_symbols ||= - JourneySubjectEligibilityChecker.selectable_subject_symbols(answers) + AdditionalPaymentsForTeaching.selectable_subject_symbols(journey_session) end def save diff --git a/app/models/academic_year.rb b/app/models/academic_year.rb index 52180578b1..6aca6d23d8 100644 --- a/app/models/academic_year.rb +++ b/app/models/academic_year.rb @@ -107,8 +107,12 @@ def eql?(other) to_s == other.to_s end + def none? + [start_year, end_year].include? nil + end + def to_s(format = :default) - return "None" if [start_year, end_year].include? nil + return "None" if none? if format == :long "#{start_year} to #{end_year}" diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index 77cd0f2dda..c513a88fc6 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -49,7 +49,15 @@ def trainee_teacher? private def common_ineligible_attributes? - [indicated_ineligible_school?, trainee_teacher?, supply_teacher_lacking_either_long_contract_or_direct_employment?, poor_performance?, no_selectable_subjects?, ineligible_cohort?, insufficient_teaching?].any? + [ + indicated_ineligible_school?, + trainee_teacher?, + supply_teacher_lacking_either_long_contract_or_direct_employment?, + poor_performance?, + no_selectable_subjects?, + ineligible_cohort?, + insufficient_teaching? + ].any? end def indicated_ineligible_school? @@ -65,12 +73,13 @@ def poor_performance? end def no_selectable_subjects? - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.values.any?(&:blank?) + if claim_year.blank? || itt_academic_year.blank? false else - JourneySubjectEligibilityChecker.new(**args).current_and_future_subject_symbols(policy).empty? + policy.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).empty? end end diff --git a/app/models/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index a217a6abf4..5395dd4a04 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -42,5 +42,25 @@ def set_a_reminder?(itt_academic_year:, policy:) def requires_student_loan_details? true end + + def selectable_subject_symbols(journey_session) + return [] if journey_session.answers.itt_academic_year&.none? + + if journey_session.answers.nqt_in_academic_year_after_itt + EligibilityChecker.new(journey_session: journey_session) + .potentially_still_eligible.map do |policy| + policy.current_and_future_subject_symbols( + claim_year: journey_session.answers.policy_year, + itt_year: journey_session.answers.itt_academic_year + ) + end.flatten.uniq + elsif journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) + # they get the standard, unchanging LUP subject set because they won't have qualified in time for ECP by 2022/2023 + # and they won't have given an ITT year + Policies::LevellingUpPremiumPayments.fixed_subject_symbols + else + [] + end + end end end diff --git a/app/models/journeys/additional_payments_for_teaching/answers_presenter.rb b/app/models/journeys/additional_payments_for_teaching/answers_presenter.rb index 3e38d921f1..ba7c80d881 100644 --- a/app/models/journeys/additional_payments_for_teaching/answers_presenter.rb +++ b/app/models/journeys/additional_payments_for_teaching/answers_presenter.rb @@ -157,10 +157,11 @@ def itt_academic_year def text_for_subject_answer policy = eligibility.policy - subjects = JourneySubjectEligibilityChecker.new( + + subjects = policy.current_and_future_subject_symbols( claim_year: Journeys.for_policy(policy).configuration.current_academic_year, itt_year: journey_session.answers.itt_academic_year - ).current_and_future_subject_symbols(policy) + ) if subjects.many? t("additional_payments.forms.eligible_itt_subject.answers.#{journey_session.answers.eligible_itt_subject}") @@ -173,7 +174,10 @@ def text_for_subject_answer private def subject_symbols - @subject_symbols ||= JourneySubjectEligibilityChecker.current_and_future_subject_symbols(answers) + @subject_symbols ||= answers.policy.subject_symbols( + claim_year: answers.policy_year, + itt_year: answers.itt_academic_year + ) end def claim_submission_form diff --git a/app/models/journeys/eligibility_checker.rb b/app/models/journeys/eligibility_checker.rb index 7e5b8efc59..1d81576813 100644 --- a/app/models/journeys/eligibility_checker.rb +++ b/app/models/journeys/eligibility_checker.rb @@ -63,6 +63,14 @@ def policies_eligible_now_and_sorted policies_eligible_now_with_award_amount_and_sorted.map { |policy_with_award_amount| policy_with_award_amount.policy } end + def potentially_still_eligible + policies.select do |policy| + policy::PolicyEligibilityChecker.new( + answers: @journey_session.answers + ).status != :ineligible + end + end + private def policies_eligible_now_with_award_amount diff --git a/app/models/journeys/page_sequence.rb b/app/models/journeys/page_sequence.rb index 3bd345d712..7502598ff5 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -104,7 +104,7 @@ def handle_trainee_teacher @journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) ? "eligible-itt-subject" : "ineligible" end when "eligible-itt-subject" - if answers.eligible_itt_subject.to_sym.in? JourneySubjectEligibilityChecker.fixed_lup_subject_symbols + if answers.eligible_itt_subject.to_sym.in? Policies::LevellingUpPremiumPayments.fixed_subject_symbols "future-eligibility" else "eligible-degree-subject" diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index 554f466a2e..f5231c9cb3 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -110,6 +110,29 @@ def auto_check_student_loan_plan_task? true end + def current_subject_symbols(claim_year:, itt_year:) + subject_symbols(claim_year: claim_year, itt_year: itt_year) + end + + def future_subject_symbols(claim_year:, itt_year:) + future_years(claim_year).flat_map do |year| + subject_symbols(claim_year: year, itt_year: itt_year) + end + end + + def current_and_future_subject_symbols(claim_year:, itt_year:) + [ + *current_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ), + *future_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + ].uniq + end + def subject_symbols(claim_year:, itt_year:) case AcademicYear.wrap(claim_year) when AcademicYear.new(2022), AcademicYear.new(2024) @@ -134,5 +157,17 @@ def subject_symbols(claim_year:, itt_year:) [] end end + + def current_and_future_years(year) + fail "year before policy start year" if year < POLICY_START_YEAR + + [year] + future_years(year) + end + + def future_years(year) + fail "year before policy start year" if year < POLICY_START_YEAR + + year + 1..POLICY_END_YEAR + end end end diff --git a/app/models/policies/early_career_payments/dqt_record.rb b/app/models/policies/early_career_payments/dqt_record.rb index 24432f5cea..48d4ffe41d 100644 --- a/app/models/policies/early_career_payments/dqt_record.rb +++ b/app/models/policies/early_career_payments/dqt_record.rb @@ -49,10 +49,11 @@ def eligible_itt_subject_for_claim return :none_of_the_above if itt_subject_groups.empty? || !year - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: current_academic_year, itt_year: year) - itt_subject_groups.delete_if do |itt_subject_group| - !itt_subject_group.in?(itt_subject_checker.current_and_future_subject_symbols(EarlyCareerPayments)) + EarlyCareerPayments.current_and_future_subject_symbols( + claim_year: current_academic_year, + itt_year: year + ).exclude?(itt_subject_group) end.first.to_sym rescue # JourneySubjectEligibilityChecker can also raise an exception if itt_year is out of eligible range :none_of_the_above diff --git a/app/models/policies/early_career_payments/policy_eligibility_checker.rb b/app/models/policies/early_career_payments/policy_eligibility_checker.rb index f6420fe664..30ba961afc 100644 --- a/app/models/policies/early_career_payments/policy_eligibility_checker.rb +++ b/app/models/policies/early_career_payments/policy_eligibility_checker.rb @@ -47,8 +47,10 @@ def itt_subject_eligible_now? return false if itt_subject.blank? return false if itt_subject_none_of_the_above? - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + EarlyCareerPayments.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(itt_subject.to_sym) end def specific_ineligible_attributes? @@ -60,8 +62,10 @@ def itt_subject_ineligible_now_and_in_the_future? return false if itt_subject.blank? return true if itt_subject_none_of_the_above? - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - !itt_subject.to_sym.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) + EarlyCareerPayments.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).exclude?(itt_subject.to_sym) end def specific_eligible_later_attributes? @@ -73,8 +77,10 @@ def itt_subject_eligible_later? return false if itt_subject.blank? return false if itt_subject_none_of_the_above? - itt_subject_checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_academic_year) - itt_subject.to_sym.in?(itt_subject_checker.future_subject_symbols(policy)) + EarlyCareerPayments.future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(itt_subject.to_sym) end # TODO: Is this used anywhere? @@ -94,9 +100,10 @@ def itt_subject_other_than_those_eligible_now_or_in_the_future? # can still rule some out itt_subject_none_of_the_above? else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - itt_subject_symbol = itt_subject.to_sym - !itt_subject_symbol.in?(itt_subject_checker.current_and_future_subject_symbols(policy)) + EarlyCareerPayments.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).exclude?(itt_subject_symbol) end end end diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index fb990dd6d8..04e2d468d8 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -100,16 +100,55 @@ def auto_check_student_loan_plan_task? true end + def current_subject_symbols(claim_year:, itt_year:) + subject_symbols(claim_year: claim_year, itt_year: itt_year) + end + + def future_subject_symbols(claim_year:, itt_year:) + future_years(claim_year).flat_map do |year| + subject_symbols(claim_year: year, itt_year: itt_year) + end + end + + def current_and_future_subject_symbols(claim_year:, itt_year:) + [ + *current_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ), + *future_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + ].uniq + end + + def fixed_subject_symbols + [:chemistry, :computing, :mathematics, :physics] + end + def subject_symbols(claim_year:, itt_year:) return [] unless (POLICY_START_YEAR..POLICY_END_YEAR).cover?(claim_year) previous_five_years = (claim_year - 5)...claim_year if previous_five_years.cover?(itt_year) - [:chemistry, :computing, :mathematics, :physics] + fixed_subject_symbols else [] end end + + def current_and_future_years(year) + fail "year before policy start year" if year < POLICY_START_YEAR + + [year] + future_years(year) + end + + def future_years(year) + fail "year before policy start year" if year < POLICY_START_YEAR + + year + 1..POLICY_END_YEAR + end end end diff --git a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb index f753ba0ee7..3a0285a1cb 100644 --- a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb +++ b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb @@ -22,7 +22,7 @@ def indicated_ineligible_itt_subject? if args.values.any?(&:blank?) # trainee teacher who won't have given their ITT year - eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) + eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(policy.fixed_subject_symbols) else itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) diff --git a/lib/ineligibility_reason_checker.rb b/lib/ineligibility_reason_checker.rb index 8362bbf821..20b34c42ea 100644 --- a/lib/ineligibility_reason_checker.rb +++ b/lib/ineligibility_reason_checker.rb @@ -154,10 +154,10 @@ def subject_invalid_for_ecp? end def ecp_subject_options - JourneySubjectEligibilityChecker.new( + Policies::EarlyCareerPayments.current_and_future_subject_symbols( claim_year: @answers.policy_year, itt_year: @answers.itt_academic_year - ).current_and_future_subject_symbols(Policies::EarlyCareerPayments) + ) end def bad_itt_year_for_ecp? diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb index 0b432b03e0..3c94c59f7f 100644 --- a/lib/journey_subject_eligibility_checker.rb +++ b/lib/journey_subject_eligibility_checker.rb @@ -41,20 +41,6 @@ def self.selectable_itt_years_for_claim_year(claim_year) (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a end - def self.current_and_future_subject_symbols(answers) - return [] if answers.itt_academic_year.blank? - - if answers.nqt_in_academic_year_after_itt - JourneySubjectEligibilityChecker.new(claim_year: answers.policy_year, itt_year: answers.itt_academic_year).current_and_future_subject_symbols(answers.policy) - elsif answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) - # they get the standard, unchanging LUP subject set because they won't have qualified in time for ECP by 2022/2023 - # and they won't have given an ITT year - JourneySubjectEligibilityChecker.fixed_lup_subject_symbols - else - [] - end.sort - end - # Ideally we wouldn't have this method at all. Unfortunately it was hardcoded like # this before we realised trainee teachers weren't as special a case as we # thought. @@ -62,6 +48,7 @@ def self.fixed_lup_subject_symbols [:chemistry, :computing, :mathematics, :physics] end + # FIXME RL - should be able to delete all the methods using this def current_and_future_subject_symbols(policy) (current_subject_symbols(policy) + future_subject_symbols(policy)).uniq end @@ -70,7 +57,11 @@ def current_subject_symbols(policy) if none_of_the_above_or_blank?(@itt_year) [] else - subject_symbols(policy: policy, claim_year: @claim_year, itt_year: @itt_year) + subject_symbols( + policy: policy, + claim_year: @claim_year, + itt_year: @itt_year + ) end end @@ -92,6 +83,7 @@ def selectable_subject_symbols(answers) private + # Move this def potentially_still_eligible_policies(answers) Journeys::AdditionalPaymentsForTeaching::POLICIES.select do |policy| policy::PolicyEligibilityChecker.new(answers: answers).status != :ineligible diff --git a/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb b/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb index 01ae9565a3..a6df607692 100644 --- a/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb +++ b/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb @@ -18,7 +18,10 @@ :additional_payments_answers, trainee_teacher, itt_academic_year: itt_academic_year, - current_school_id: create(:school, :early_career_payments_eligible).id + current_school_id: create( + :school, + :early_career_payments_eligible + ).id ) ) end @@ -160,8 +163,8 @@ context "when the subject list contains chemistry" do before do - allow(JourneySubjectEligibilityChecker).to( - receive(:fixed_lup_subject_symbols).and_return([:chemistry]) + allow(Policies::LevellingUpPremiumPayments).to( + receive(:fixed_subject_symbols).and_return([:chemistry]) ) end @@ -170,8 +173,8 @@ context "when the subject list contains physics" do before do - allow(JourneySubjectEligibilityChecker).to( - receive(:fixed_lup_subject_symbols).and_return([:physics]) + allow(Policies::LevellingUpPremiumPayments).to( + receive(:fixed_subject_symbols).and_return([:physics]) ) end @@ -180,8 +183,8 @@ context "when the subject list does not contain chemistry or physics" do before do - allow(JourneySubjectEligibilityChecker).to( - receive(:fixed_lup_subject_symbols).and_return([:mathematics]) + allow(Policies::LevellingUpPremiumPayments).to( + receive(:fixed_subject_symbols).and_return([:mathematics]) ) end diff --git a/spec/lib/journey_subject_eligibility_checker_spec.rb b/spec/lib/journey_subject_eligibility_checker_spec.rb index 9bf76d9aa4..5f3f22aa18 100644 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ b/spec/lib/journey_subject_eligibility_checker_spec.rb @@ -559,231 +559,6 @@ end end - describe "#current_and_future_subject_symbols" do - subject { described_class.new(claim_year: claim_year, itt_year: itt_year).current_and_future_subject_symbols(policy) } - - context "ECP" do - let(:policy) { Policies::EarlyCareerPayments } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "None of the above ITT year" do - let(:itt_year) { AcademicYear.new } - - it { is_expected.to be_empty } - end - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to be_empty } - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - - context "2023 ITT year" do - let(:itt_year) { AcademicYear.new(2023) } - - it { is_expected.to be_empty } - end - end - end - - context "LUP" do - let(:policy) { Policies::LevellingUpPremiumPayments } - let(:the_constant_lup_subjects) { [:chemistry, :computing, :mathematics, :physics] } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - end - end - - context "unsupported policy" do - let(:policy) { Policies::StudentLoans } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - specify { expect { described_class.new(claim_year: claim_year, itt_year: itt_year).future_subject_symbols(policy) }.to raise_error("Unsupported policy: StudentLoans") } - end - end - end - end - describe "#selectable_subject_symbols" do subject do described_class.new( diff --git a/spec/models/early_career_payments_spec.rb b/spec/models/early_career_payments_spec.rb index 40f6498a9a..a73fe9c1a1 100644 --- a/spec/models/early_career_payments_spec.rb +++ b/spec/models/early_career_payments_spec.rb @@ -31,4 +31,115 @@ subject(:payroll_file_name) { described_class.payroll_file_name } it { is_expected.to eq("EarlyCareerPayments") } end + + describe ".current_and_future_subject_symbols" do + subject(:current_and_future_subject_symbols) do + described_class.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + end + + context "2022 claim year" do + let(:claim_year) { AcademicYear.new(2022) } + + context "None of the above ITT year" do + let(:itt_year) { AcademicYear.new } + + it { is_expected.to be_empty } + end + + context "2017 ITT year" do + let(:itt_year) { AcademicYear.new(2017) } + + it { is_expected.to be_empty } + end + + context "2018 ITT year" do + let(:itt_year) { AcademicYear.new(2018) } + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } + end + end + + context "2023 claim year" do + let(:claim_year) { AcademicYear.new(2023) } + + context "2018 ITT year" do + let(:itt_year) { AcademicYear.new(2018) } + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + it { is_expected.to be_empty } + end + + context "2022 ITT year" do + let(:itt_year) { AcademicYear.new(2022) } + + it { is_expected.to be_empty } + end + end + + context "2024 claim year" do + let(:claim_year) { AcademicYear.new(2024) } + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + it { is_expected.to be_empty } + end + + context "2022 ITT year" do + let(:itt_year) { AcademicYear.new(2022) } + + it { is_expected.to be_empty } + end + + context "2023 ITT year" do + let(:itt_year) { AcademicYear.new(2023) } + + it { is_expected.to be_empty } + end + end + end end diff --git a/spec/models/journeys/additional_payments_for_teaching_spec.rb b/spec/models/journeys/additional_payments_for_teaching_spec.rb index f9be210508..dead026cd4 100644 --- a/spec/models/journeys/additional_payments_for_teaching_spec.rb +++ b/spec/models/journeys/additional_payments_for_teaching_spec.rb @@ -128,4 +128,202 @@ end end end + + describe ".selectable_subject_symbols" do + subject { described_class.selectable_subject_symbols(journey_session) } + + context "when academic year is 2022" do + before { create(:journey_configuration, :additional_payments, current_academic_year: claim_year) } + + context "2022 claim year" do + let(:claim_year) { AcademicYear.new(2022) } + + context "None of the above ITT year" do + let(:itt_year) { AcademicYear.new } + + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to be_empty } + end + + context "2017 ITT year" do + let(:itt_year) { AcademicYear.new(2017) } + + context "ineligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to be_empty } + end + + context "eligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_and_lup_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + end + + context "2018 ITT year" do + let(:itt_year) { AcademicYear.new(2018) } + + context "ineligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "eligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_and_lup_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + end + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + context "ineligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:mathematics) } + end + + context "eligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_and_lup_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + context "ineligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } + end + + context "eligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_and_lup_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :computing, :foreign_languages, :mathematics, :physics) } + end + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + context "ineligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to be_empty } + end + + context "eligible LUP" do + let(:journey_session) do + create( + :additional_payments_session, + answers: attributes_for( + :additional_payments_answers, + :ecp_and_lup_eligible, + itt_academic_year: itt_year + ) + ) + end + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + end + end + end + end end diff --git a/spec/models/levelling_up_premium_payments_spec.rb b/spec/models/levelling_up_premium_payments_spec.rb index 702123cab7..2f3e8c93db 100644 --- a/spec/models/levelling_up_premium_payments_spec.rb +++ b/spec/models/levelling_up_premium_payments_spec.rb @@ -29,4 +29,113 @@ subject(:payroll_file_name) { described_class.payroll_file_name } it { is_expected.to eq("SchoolsLUP") } end + + describe ".current_and_future_subject_symbols" do + subject(:current_and_future_subject_symbols) do + described_class.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + end + + let(:the_constant_lup_subjects) do + [:chemistry, :computing, :mathematics, :physics] + end + + context "2022 claim year" do + let(:claim_year) { AcademicYear.new(2022) } + + context "2017 ITT year" do + let(:itt_year) { AcademicYear.new(2017) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + + context "2018 ITT year" do + let(:itt_year) { AcademicYear.new(2018) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + end + + context "2023 claim year" do + let(:claim_year) { AcademicYear.new(2023) } + + context "2018 ITT year" do + let(:itt_year) { AcademicYear.new(2018) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + + context "2022 ITT year" do + let(:itt_year) { AcademicYear.new(2022) } + + it { is_expected.to contain_exactly(*the_constant_lup_subjects) } + end + end + + context "2024 claim year" do + let(:claim_year) { AcademicYear.new(2024) } + + context "2019 ITT year" do + let(:itt_year) { AcademicYear.new(2019) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + + context "2020 ITT year" do + let(:itt_year) { AcademicYear.new(2020) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + + context "2021 ITT year" do + let(:itt_year) { AcademicYear.new(2021) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + + context "2022 ITT year" do + let(:itt_year) { AcademicYear.new(2022) } + + it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } + end + end + end end diff --git a/spec/models/policies/early_career_payments/dqt_record_spec.rb b/spec/models/policies/early_career_payments/dqt_record_spec.rb index 24ddbc1e97..cc293c6786 100644 --- a/spec/models/policies/early_career_payments/dqt_record_spec.rb +++ b/spec/models/policies/early_career_payments/dqt_record_spec.rb @@ -2176,8 +2176,10 @@ context "with a valid ITT year" do before do - allow(JourneySubjectEligibilityChecker).to receive(:new) - .and_return(double(current_and_future_subject_symbols: eligible_subjects)) + allow(Policies::EarlyCareerPayments).to( + receive(:current_and_future_subject_symbols) + .and_return(eligible_subjects) + ) end let(:claim_academic_year) { AcademicYear.new(2023) } From f46a8667b3985ac7247934213f1d6b55ad2145ac Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Tue, 19 Nov 2024 12:32:08 +0000 Subject: [PATCH 07/17] Move selectable_itt_years_for_claim_year from lib As part of the refactor to remove ECP we want to move the policy specific functionality into the respective polices. This commit moves the `selectable_itt_years_for_claim_year` out of the lib class and into each policy, with the journey delegating this method to any potentially_still_eligible policies. --- .../itt_academic_year_form.rb | 2 +- app/models/concerns/eligibility_checkable.rb | 4 +- .../additional_payments_for_teaching.rb | 8 +++- app/models/policies/early_career_payments.rb | 4 ++ .../early_career_payments/dqt_record.rb | 2 +- .../policies/levelling_up_premium_payments.rb | 4 ++ .../dqt_record.rb | 2 +- lib/journey_subject_eligibility_checker.rb | 10 +---- ...in_claim_tasks_update_with_dqt_api_spec.rb | 2 +- ...urney_with_teacher_id_check_mobile_spec.rb | 2 +- ...cher_claim_journey_with_teacher_id_spec.rb | 2 +- .../ineligible_student_loans_claims_spec.rb | 2 +- ...tslr_claim_journey_with_teacher_id_spec.rb | 2 +- ...ourney_subject_eligibility_checker_spec.rb | 40 ------------------- spec/models/early_career_payments_spec.rb | 20 ++++++++++ .../additional_payments_for_teaching_spec.rb | 4 +- .../levelling_up_premium_payments_spec.rb | 20 ++++++++++ .../early_career_payments/dqt_record_spec.rb | 5 ++- .../dqt_record_spec.rb | 5 ++- 19 files changed, 74 insertions(+), 66 deletions(-) diff --git a/app/forms/journeys/additional_payments_for_teaching/itt_academic_year_form.rb b/app/forms/journeys/additional_payments_for_teaching/itt_academic_year_form.rb index 0226d9a6ab..f07c26c4a1 100644 --- a/app/forms/journeys/additional_payments_for_teaching/itt_academic_year_form.rb +++ b/app/forms/journeys/additional_payments_for_teaching/itt_academic_year_form.rb @@ -28,7 +28,7 @@ def qualification_is?(*symbols) end def selectable_itt_years_for_claim_year - JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year( + AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year( journey.configuration.current_academic_year ) end diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index c513a88fc6..b20c041331 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -86,7 +86,7 @@ def no_selectable_subjects? def ineligible_cohort? return false if itt_academic_year.nil? - eligible_itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(claim_year) + eligible_itt_years = policy.selectable_itt_years_for_claim_year(claim_year) !itt_academic_year.in? eligible_itt_years end @@ -121,7 +121,7 @@ def good_performance? def eligible_cohort? return false if itt_academic_year.nil? - eligible_itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(claim_year) + eligible_itt_years = policy.selectable_itt_years_for_claim_year(claim_year) itt_academic_year.in? eligible_itt_years end diff --git a/app/models/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index 5395dd4a04..b471564547 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -35,7 +35,7 @@ def set_a_reminder?(itt_academic_year:, policy:) return false if policy_year >= policy::POLICY_END_YEAR next_year = policy_year + 1 - eligible_itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(next_year) + eligible_itt_years = selectable_itt_years_for_claim_year(next_year) eligible_itt_years.include?(itt_academic_year) end @@ -62,5 +62,11 @@ def selectable_subject_symbols(journey_session) [] end end + + def selectable_itt_years_for_claim_year(claim_year) + POLICIES.flat_map do |policy| + policy.selectable_itt_years_for_claim_year(claim_year) + end.uniq + end end end diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index f5231c9cb3..a0289b1ffd 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -169,5 +169,9 @@ def future_years(year) year + 1..POLICY_END_YEAR end + + def selectable_itt_years_for_claim_year(claim_year) + (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a + end end end diff --git a/app/models/policies/early_career_payments/dqt_record.rb b/app/models/policies/early_career_payments/dqt_record.rb index 48d4ffe41d..4f7b7dbd24 100644 --- a/app/models/policies/early_career_payments/dqt_record.rb +++ b/app/models/policies/early_career_payments/dqt_record.rb @@ -63,7 +63,7 @@ def itt_academic_year_for_claim return nil unless academic_date year = AcademicYear.for(academic_date) - eligible_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(current_academic_year) + eligible_years = EarlyCareerPayments.selectable_itt_years_for_claim_year(current_academic_year) eligible_years.include?(year) ? year : AcademicYear.new end diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 04e2d468d8..62b7cc5e36 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -150,5 +150,9 @@ def future_years(year) year + 1..POLICY_END_YEAR end + + def selectable_itt_years_for_claim_year(claim_year) + (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a + end end end diff --git a/app/models/policies/levelling_up_premium_payments/dqt_record.rb b/app/models/policies/levelling_up_premium_payments/dqt_record.rb index 5146d94889..69ec93512e 100644 --- a/app/models/policies/levelling_up_premium_payments/dqt_record.rb +++ b/app/models/policies/levelling_up_premium_payments/dqt_record.rb @@ -110,7 +110,7 @@ def no_invalid_subject_codes? end def itt_year_within_allowed_range?(year = itt_year) - eligible_itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(current_academic_year) + eligible_itt_years = LevellingUpPremiumPayments.selectable_itt_years_for_claim_year(current_academic_year) eligible_itt_years.include?(year) end end diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb index 3c94c59f7f..e7f58cda81 100644 --- a/lib/journey_subject_eligibility_checker.rb +++ b/lib/journey_subject_eligibility_checker.rb @@ -18,10 +18,6 @@ def future_claim_years end end - def selectable_itt_years - JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(@claim_year) - end - def self.selectable_subject_symbols(answers) if answers.nqt_in_academic_year_after_itt new( @@ -37,10 +33,6 @@ def self.selectable_subject_symbols(answers) end.sort end - def self.selectable_itt_years_for_claim_year(claim_year) - (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a - end - # Ideally we wouldn't have this method at all. Unfortunately it was hardcoded like # this before we realised trainee teachers weren't as special a case as we # thought. @@ -92,7 +84,7 @@ def potentially_still_eligible_policies(answers) def validate_itt_year(itt_year) unless none_of_the_above_or_blank?(itt_year) - raise "ITT year #{itt_year} is outside the window for claim year #{@claim_year}" unless itt_year.in?(selectable_itt_years) + raise "ITT year #{itt_year} is outside the window for claim year #{@claim_year}" unless itt_year.in?(Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(@claim_year)) end end diff --git a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb index ad1925536a..5bf497afa5 100644 --- a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb +++ b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb @@ -145,7 +145,7 @@ def task_outcome claim_year = Journeys.for_policy(policy).configuration.current_academic_year - itt_years = JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(claim_year) + itt_years = policy.selectable_itt_years_for_claim_year(claim_year) itt_years.detect do |itt_year| checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_year) diff --git a/spec/features/combined_teacher_claim_journey_with_teacher_id_check_mobile_spec.rb b/spec/features/combined_teacher_claim_journey_with_teacher_id_check_mobile_spec.rb index 7614e4ddb2..0570495d19 100644 --- a/spec/features/combined_teacher_claim_journey_with_teacher_id_check_mobile_spec.rb +++ b/spec/features/combined_teacher_claim_journey_with_teacher_id_check_mobile_spec.rb @@ -6,7 +6,7 @@ let!(:journey_configuration) { create(:journey_configuration, :additional_payments) } let!(:school) { create(:school, :combined_journey_eligibile_for_all) } - let(:eligible_itt_years) { JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } + let(:eligible_itt_years) { Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } let(:academic_date) { Date.new(eligible_itt_years.first.start_year, 12, 1) } let(:itt_year) { AcademicYear.for(academic_date) } let(:trn) { 1234567 } diff --git a/spec/features/combined_teacher_claim_journey_with_teacher_id_spec.rb b/spec/features/combined_teacher_claim_journey_with_teacher_id_spec.rb index e916b675eb..32c040bd6e 100644 --- a/spec/features/combined_teacher_claim_journey_with_teacher_id_spec.rb +++ b/spec/features/combined_teacher_claim_journey_with_teacher_id_spec.rb @@ -7,7 +7,7 @@ let!(:journey_configuration) { create(:journey_configuration, :additional_payments, current_academic_year: AcademicYear.new(2023)) } let!(:school) { create(:school, :combined_journey_eligibile_for_all) } - let(:eligible_itt_years) { JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } + let(:eligible_itt_years) { Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } let(:academic_date) { Date.new(eligible_itt_years.first.start_year, 12, 1) } let(:itt_year) { AcademicYear.for(academic_date) } let(:trn) { 1234567 } diff --git a/spec/features/ineligible_student_loans_claims_spec.rb b/spec/features/ineligible_student_loans_claims_spec.rb index abe4dfa63e..a0641f4e36 100644 --- a/spec/features/ineligible_student_loans_claims_spec.rb +++ b/spec/features/ineligible_student_loans_claims_spec.rb @@ -9,7 +9,7 @@ let!(:ineligible_school) { create(:school, :student_loans_ineligible) } let(:import_zero_amount_slc_data) { create(:student_loans_data, nino:, date_of_birth:, plan_type_of_deduction: 1, amount: 0) } let(:import_no_data_slc_data) { create(:student_loans_data, nino:, date_of_birth:, plan_type_of_deduction: nil, amount: 0) } - let(:eligible_itt_years) { JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } + let(:eligible_itt_years) { Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } let(:academic_date) { Date.new(eligible_itt_years.first.start_year, 12, 1) } let(:itt_year) { AcademicYear.for(academic_date) } let(:trn) { 1234567 } diff --git a/spec/features/tslr/tslr_claim_journey_with_teacher_id_spec.rb b/spec/features/tslr/tslr_claim_journey_with_teacher_id_spec.rb index fea19293ad..0b1fc8bbec 100644 --- a/spec/features/tslr/tslr_claim_journey_with_teacher_id_spec.rb +++ b/spec/features/tslr/tslr_claim_journey_with_teacher_id_spec.rb @@ -6,7 +6,7 @@ let!(:journey_configuration) { create(:journey_configuration, :student_loans) } let!(:school) { create(:school, :student_loans_eligible) } - let(:eligible_itt_years) { JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } + let(:eligible_itt_years) { Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(journey_configuration.current_academic_year) } let(:academic_date) { Date.new(eligible_itt_years.first.start_year, 12, 1) } let(:itt_year) { AcademicYear.for(academic_date) } let(:trn) { 1234567 } diff --git a/spec/lib/journey_subject_eligibility_checker_spec.rb b/spec/lib/journey_subject_eligibility_checker_spec.rb index 5f3f22aa18..f8133d7862 100644 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ b/spec/lib/journey_subject_eligibility_checker_spec.rb @@ -50,46 +50,6 @@ end end - describe "#selectable_itt_years" do - context "2022/2023 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new(2021)).selectable_itt_years } - - it { is_expected.to contain_exactly(AcademicYear.new(2017), AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021)) } - end - - context "2023/2024 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2023), itt_year: AcademicYear.new(2022)).selectable_itt_years } - - it { is_expected.to contain_exactly(AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022)) } - end - - context "2024/2025 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2024), itt_year: AcademicYear.new(2023)).selectable_itt_years } - - it { is_expected.to contain_exactly(AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022), AcademicYear.new(2023)) } - end - end - - describe ".selectable_itt_years_for_view" do - context "2022/2023 claim year" do - subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2022)) } - - it { is_expected.to eq([AcademicYear.new(2017), AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021)]) } - end - - context "2023/2024 claim year" do - subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2023)) } - - it { is_expected.to eq([AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022)]) } - end - - context "2024/2025 claim year" do - subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2024)) } - - it { is_expected.to eq([AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022), AcademicYear.new(2023)]) } - end - end - describe "#current_subject_symbols" do subject { described_class.new(claim_year: claim_year, itt_year: itt_year).current_subject_symbols(policy) } diff --git a/spec/models/early_career_payments_spec.rb b/spec/models/early_career_payments_spec.rb index a73fe9c1a1..180a47247a 100644 --- a/spec/models/early_career_payments_spec.rb +++ b/spec/models/early_career_payments_spec.rb @@ -142,4 +142,24 @@ end end end + + describe ".selectable_itt_years_for_view" do + context "2022/2023 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2022)) } + + it { is_expected.to eq([AcademicYear.new(2017), AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021)]) } + end + + context "2023/2024 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2023)) } + + it { is_expected.to eq([AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022)]) } + end + + context "2024/2025 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2024)) } + + it { is_expected.to eq([AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022), AcademicYear.new(2023)]) } + end + end end diff --git a/spec/models/journeys/additional_payments_for_teaching_spec.rb b/spec/models/journeys/additional_payments_for_teaching_spec.rb index dead026cd4..3d111ccb4b 100644 --- a/spec/models/journeys/additional_payments_for_teaching_spec.rb +++ b/spec/models/journeys/additional_payments_for_teaching_spec.rb @@ -68,7 +68,7 @@ end shared_examples "true for years" do |start_years_range, policy_year| - JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(policy_year).each do |itt_academic_year| + Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(policy_year).each do |itt_academic_year| context "ITT year #{itt_academic_year}" do let(:itt_academic_year) { itt_academic_year } @@ -82,7 +82,7 @@ end shared_examples "false for all years" do |policy_year| - JourneySubjectEligibilityChecker.selectable_itt_years_for_claim_year(policy_year).each do |itt_academic_year| + Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(policy_year).each do |itt_academic_year| context "ITT year #{itt_academic_year}" do let(:itt_academic_year) { itt_academic_year } diff --git a/spec/models/levelling_up_premium_payments_spec.rb b/spec/models/levelling_up_premium_payments_spec.rb index 2f3e8c93db..46dfc3e105 100644 --- a/spec/models/levelling_up_premium_payments_spec.rb +++ b/spec/models/levelling_up_premium_payments_spec.rb @@ -138,4 +138,24 @@ end end end + + describe ".selectable_itt_years_for_view" do + context "2022/2023 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2022)) } + + it { is_expected.to eq([AcademicYear.new(2017), AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021)]) } + end + + context "2023/2024 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2023)) } + + it { is_expected.to eq([AcademicYear.new(2018), AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022)]) } + end + + context "2024/2025 claim year" do + subject { described_class.selectable_itt_years_for_claim_year(AcademicYear.new(2024)) } + + it { is_expected.to eq([AcademicYear.new(2019), AcademicYear.new(2020), AcademicYear.new(2021), AcademicYear.new(2022), AcademicYear.new(2023)]) } + end + end end diff --git a/spec/models/policies/early_career_payments/dqt_record_spec.rb b/spec/models/policies/early_career_payments/dqt_record_spec.rb index cc293c6786..641eca89ed 100644 --- a/spec/models/policies/early_career_payments/dqt_record_spec.rb +++ b/spec/models/policies/early_career_payments/dqt_record_spec.rb @@ -2263,8 +2263,9 @@ describe "#itt_academic_year_for_claim" do before do - allow(JourneySubjectEligibilityChecker).to receive(:new) - .and_return(double(selectable_itt_years_for_claim_year: eligible_years)) + allow(Policies::EarlyCareerPayments).to( + receive(:selectable_itt_years_for_claim_year).and_return(eligible_years) + ) end let(:record) do diff --git a/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb b/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb index dbdcb9e24f..4138fc5cd0 100644 --- a/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb +++ b/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb @@ -340,8 +340,9 @@ describe "#itt_academic_year_for_claim" do before do - allow(JourneySubjectEligibilityChecker).to receive(:new) - .and_return(double(selectable_itt_years_for_claim_year: eligible_years)) + allow(Policies::LevellingUpPremiumPayments).to( + receive(:selectable_itt_years_for_claim_year).and_return(eligible_years) + ) end let(:record) do From d267f6bee9254e7d9fa38baf46e80ba67932fe6f Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Tue, 19 Nov 2024 16:40:24 +0000 Subject: [PATCH 08/17] Move fixed_subject_symbols Move fixed_lup_subject_symbols of off JourneySubjectEligibilityChecker and onto LevellingUpPremiumPayments policy as this method is policy specific. --- app/helpers/claims/itt_subject_helper.rb | 2 +- .../policies/levelling_up_premium_payments.rb | 3 + .../policy_eligibility_checker.rb | 2 +- .../claims/eligible_degree_subject.html.erb | 2 +- lib/journey_subject_eligibility_checker.rb | 30 --- .../early_career_payments_helper_spec.rb | 2 +- ...ourney_subject_eligibility_checker_spec.rb | 200 ------------------ .../dqt_record_spec.rb | 2 +- 8 files changed, 8 insertions(+), 235 deletions(-) diff --git a/app/helpers/claims/itt_subject_helper.rb b/app/helpers/claims/itt_subject_helper.rb index 5cd55a0fda..79e057a780 100644 --- a/app/helpers/claims/itt_subject_helper.rb +++ b/app/helpers/claims/itt_subject_helper.rb @@ -4,7 +4,7 @@ module Claims module IttSubjectHelper def subjects_to_sentence_for_hint_text(answers) all_ecp_subjects = [:chemistry, :foreign_languages, :mathematics, :physics] - all_lup_subjects = JourneySubjectEligibilityChecker.fixed_lup_subject_symbols + all_lup_subjects = Policies::LevellingUpPremiumPayments.fixed_subject_symbols hint_subject_symbols = Set[] diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 62b7cc5e36..d7cec6ec7d 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -123,6 +123,9 @@ def current_and_future_subject_symbols(claim_year:, itt_year:) ].uniq end + # Ideally we wouldn't have this method at all. Unfortunately it was hardcoded like + # this before we realised trainee teachers weren't as special a case as we + # thought. def fixed_subject_symbols [:chemistry, :computing, :mathematics, :physics] end diff --git a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb index 3a0285a1cb..c3d86f1c6d 100644 --- a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb +++ b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb @@ -62,7 +62,7 @@ def good_itt_subject? if args.values.any?(&:blank?) # trainee teacher who won't have given their ITT year - eligible_itt_subject.present? && eligible_itt_subject.to_sym.in?(JourneySubjectEligibilityChecker.fixed_lup_subject_symbols) + eligible_itt_subject.present? && eligible_itt_subject.to_sym.in?(Policies::LevellingUpPremiumPayments.fixed_subject_symbols) else itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) diff --git a/app/views/additional_payments/claims/eligible_degree_subject.html.erb b/app/views/additional_payments/claims/eligible_degree_subject.html.erb index bae29a44c3..1a292e2ff3 100644 --- a/app/views/additional_payments/claims/eligible_degree_subject.html.erb +++ b/app/views/additional_payments/claims/eligible_degree_subject.html.erb @@ -18,7 +18,7 @@
This can be an undergraduate or postgraduate degree in - <%= JourneySubjectEligibilityChecker.fixed_lup_subject_symbols.to_sentence(last_word_connector: ' or ') %>. + <%= Policies::LevellingUpPremiumPayments.fixed_subject_symbols.to_sentence(last_word_connector: ' or ') %>.
<%= errors_tag f.object, :eligible_degree_subject %> diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb index e7f58cda81..a1048c9c87 100644 --- a/lib/journey_subject_eligibility_checker.rb +++ b/lib/journey_subject_eligibility_checker.rb @@ -18,28 +18,6 @@ def future_claim_years end end - def self.selectable_subject_symbols(answers) - if answers.nqt_in_academic_year_after_itt - new( - claim_year: answers.policy_year, - itt_year: answers.itt_academic_year - ).selectable_subject_symbols(answers) - elsif answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) - # they get the standard, unchanging LUP subject set because they won't have qualified in time for ECP by 2022/2023 - # and they won't have given an ITT year - fixed_lup_subject_symbols - else - [] - end.sort - end - - # Ideally we wouldn't have this method at all. Unfortunately it was hardcoded like - # this before we realised trainee teachers weren't as special a case as we - # thought. - def self.fixed_lup_subject_symbols - [:chemistry, :computing, :mathematics, :physics] - end - # FIXME RL - should be able to delete all the methods using this def current_and_future_subject_symbols(policy) (current_subject_symbols(policy) + future_subject_symbols(policy)).uniq @@ -65,14 +43,6 @@ def future_subject_symbols(policy) end end - def selectable_subject_symbols(answers) - return [] if answers.itt_academic_year.blank? - - potentially_still_eligible_policies(answers).map do |policy| - current_and_future_subject_symbols(policy) - end.flatten.uniq - end - private # Move this diff --git a/spec/helpers/early_career_payments_helper_spec.rb b/spec/helpers/early_career_payments_helper_spec.rb index df975b10eb..7a02816854 100644 --- a/spec/helpers/early_career_payments_helper_spec.rb +++ b/spec/helpers/early_career_payments_helper_spec.rb @@ -29,7 +29,7 @@ subject do helper.eligible_itt_subject_translation( journey_session.answers, - JourneySubjectEligibilityChecker.selectable_subject_symbols(journey_session.answers) + Journeys::AdditionalPaymentsForTeaching.selectable_subject_symbols(journey_session) ) end diff --git a/spec/lib/journey_subject_eligibility_checker_spec.rb b/spec/lib/journey_subject_eligibility_checker_spec.rb index f8133d7862..c4daf1fb00 100644 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ b/spec/lib/journey_subject_eligibility_checker_spec.rb @@ -518,204 +518,4 @@ end end end - - describe "#selectable_subject_symbols" do - subject do - described_class.new( - claim_year: claim_year, itt_year: itt_year - ).selectable_subject_symbols(journey_session.answers) - end - - context "when academic year is 2022" do - before { create(:journey_configuration, :additional_payments, current_academic_year: AcademicYear.new(2022)) } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "None of the above ITT year" do - let(:itt_year) { AcademicYear.new } - - let(:journey_session) do - create(:additional_payments_session) - end - - it { is_expected.to be_empty } - end - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - context "ineligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to be_empty } - end - - context "eligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_and_lup_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - context "ineligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "eligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_and_lup_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - context "ineligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "eligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_and_lup_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - context "ineligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "eligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_and_lup_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :computing, :foreign_languages, :mathematics, :physics) } - end - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - context "ineligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to be_empty } - end - - context "eligible LUP" do - let(:journey_session) do - create( - :additional_payments_session, - answers: attributes_for( - :additional_payments_answers, - :ecp_and_lup_eligible, - itt_academic_year: itt_year - ) - ) - end - - it { is_expected.to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end - end - end - end - end - - describe ".fixed_lup_subject_symbols" do - specify { expect(described_class.fixed_lup_subject_symbols).to contain_exactly(:chemistry, :computing, :mathematics, :physics) } - end end diff --git a/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb b/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb index 4138fc5cd0..e84cccaaa9 100644 --- a/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb +++ b/spec/models/policies/levelling_up_premium_payments/dqt_record_spec.rb @@ -289,7 +289,7 @@ let(:eligible_subjects) { [:computing] } before do - allow(JourneySubjectEligibilityChecker).to receive(:fixed_lup_subject_symbols) + allow(Policies::LevellingUpPremiumPayments).to receive(:fixed_subject_symbols) .and_return(eligible_subjects) end From 68e5f5ec8c9c3e361f438e0731a05a274829de26 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Tue, 19 Nov 2024 16:47:30 +0000 Subject: [PATCH 09/17] Remove JourneySubjectEligibilityChecker This class is no longer needed --- app/helpers/claims/itt_subject_helper.rb | 2 - .../dqt_record.rb | 2 - .../policy_eligibility_checker.rb | 22 +- lib/journey_subject_eligibility_checker.rb | 74 --- ...in_claim_tasks_update_with_dqt_api_spec.rb | 8 +- .../eligible_itt_subject_form_spec.rb | 2 +- ...ourney_subject_eligibility_checker_spec.rb | 521 ------------------ .../early_career_payments/dqt_record_spec.rb | 2 +- 8 files changed, 19 insertions(+), 614 deletions(-) delete mode 100644 lib/journey_subject_eligibility_checker.rb delete mode 100644 spec/lib/journey_subject_eligibility_checker_spec.rb diff --git a/app/helpers/claims/itt_subject_helper.rb b/app/helpers/claims/itt_subject_helper.rb index 79e057a780..2a6a4253e7 100644 --- a/app/helpers/claims/itt_subject_helper.rb +++ b/app/helpers/claims/itt_subject_helper.rb @@ -1,5 +1,3 @@ -require "journey_subject_eligibility_checker" - module Claims module IttSubjectHelper def subjects_to_sentence_for_hint_text(answers) diff --git a/app/models/policies/levelling_up_premium_payments/dqt_record.rb b/app/models/policies/levelling_up_premium_payments/dqt_record.rb index 69ec93512e..235f2e85f9 100644 --- a/app/models/policies/levelling_up_premium_payments/dqt_record.rb +++ b/app/models/policies/levelling_up_premium_payments/dqt_record.rb @@ -1,5 +1,3 @@ -require "journey_subject_eligibility_checker" - module Policies module LevellingUpPremiumPayments class DqtRecord diff --git a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb index c3d86f1c6d..4361b67e76 100644 --- a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb +++ b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb @@ -18,14 +18,14 @@ def policy def indicated_ineligible_itt_subject? return false if eligible_itt_subject.blank? - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.values.any?(&:blank?) + if claim_year.blank? || itt_academic_year.blank? # trainee teacher who won't have given their ITT year - eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(policy.fixed_subject_symbols) + eligible_itt_subject.present? && LevellingUpPremiumPayments.fixed_subject_symbols.exclude?(eligible_itt_subject.to_sym) else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - eligible_itt_subject.present? && !eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + LevellingUpPremiumPayments.subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).exclude?(eligible_itt_subject.to_sym) end end @@ -58,14 +58,14 @@ def eligible_itt_subject_or_relevant_degree? def good_itt_subject? return false if eligible_itt_subject.blank? - args = {claim_year: claim_year, itt_year: itt_academic_year} - - if args.values.any?(&:blank?) + if claim_year.blank? || itt_academic_year.blank? # trainee teacher who won't have given their ITT year eligible_itt_subject.present? && eligible_itt_subject.to_sym.in?(Policies::LevellingUpPremiumPayments.fixed_subject_symbols) else - itt_subject_checker = JourneySubjectEligibilityChecker.new(**args) - eligible_itt_subject.to_sym.in?(itt_subject_checker.current_subject_symbols(policy)) + LevellingUpPremiumPayments.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(eligible_itt_subject.to_sym) end end diff --git a/lib/journey_subject_eligibility_checker.rb b/lib/journey_subject_eligibility_checker.rb deleted file mode 100644 index a1048c9c87..0000000000 --- a/lib/journey_subject_eligibility_checker.rb +++ /dev/null @@ -1,74 +0,0 @@ -# TODO: Move this into an additional-payments journey specific namespace -# -class JourneySubjectEligibilityChecker - def initialize(claim_year:, itt_year:) - raise "Claim year #{claim_year} is after ECP and LUP both ended" if claim_year > EligibilityCheckable::FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR - - @claim_year = claim_year - - validate_itt_year(itt_year) - @itt_year = itt_year - end - - def future_claim_years - if none_of_the_above_or_blank?(@itt_year) - [] - else - ((@claim_year + 1)..EligibilityCheckable::FINAL_COMBINED_ECP_AND_LUP_POLICY_YEAR).to_a - end - end - - # FIXME RL - should be able to delete all the methods using this - def current_and_future_subject_symbols(policy) - (current_subject_symbols(policy) + future_subject_symbols(policy)).uniq - end - - def current_subject_symbols(policy) - if none_of_the_above_or_blank?(@itt_year) - [] - else - subject_symbols( - policy: policy, - claim_year: @claim_year, - itt_year: @itt_year - ) - end - end - - def future_subject_symbols(policy) - if none_of_the_above_or_blank?(@itt_year) - [] - else - future_claim_years.collect { |future_year| subject_symbols(policy: policy, claim_year: future_year, itt_year: @itt_year) }.flatten.uniq - end - end - - private - - # Move this - def potentially_still_eligible_policies(answers) - Journeys::AdditionalPaymentsForTeaching::POLICIES.select do |policy| - policy::PolicyEligibilityChecker.new(answers: answers).status != :ineligible - end - end - - def validate_itt_year(itt_year) - unless none_of_the_above_or_blank?(itt_year) - raise "ITT year #{itt_year} is outside the window for claim year #{@claim_year}" unless itt_year.in?(Journeys::AdditionalPaymentsForTeaching.selectable_itt_years_for_claim_year(@claim_year)) - end - end - - def none_of_the_above_or_blank?(itt_year) - itt_year.blank? || none_of_the_above?(itt_year) - end - - def none_of_the_above?(itt_year) - itt_year.in? [AcademicYear.new, "None"] - end - - def subject_symbols(policy:, claim_year:, itt_year:) - raise "Unsupported policy: #{policy}" unless policy.in?(Journeys::AdditionalPaymentsForTeaching::POLICIES) - - policy.subject_symbols(claim_year: claim_year, itt_year: itt_year) - end -end diff --git a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb index 5bf497afa5..8b1c18edc9 100644 --- a/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb +++ b/spec/features/admin/admin_claim_tasks_update_with_dqt_api_spec.rb @@ -148,8 +148,12 @@ def task_outcome itt_years = policy.selectable_itt_years_for_claim_year(claim_year) itt_years.detect do |itt_year| - checker = JourneySubjectEligibilityChecker.new(claim_year: claim_year, itt_year: itt_year) - subject_symbol.in?(checker.current_subject_symbols(policy)) + subject_symbol.in?( + policy.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + ) end } diff --git a/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb b/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb index a6df607692..b6792241c6 100644 --- a/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb +++ b/spec/forms/journeys/additional_payments_for_teaching/eligible_itt_subject_form_spec.rb @@ -53,7 +53,7 @@ context "when single subject available" do before do - allow(JourneySubjectEligibilityChecker).to receive(:selectable_subject_symbols).and_return([:mathematics]) + allow(Journeys::AdditionalPaymentsForTeaching).to receive(:selectable_subject_symbols).and_return([:mathematics]) end let(:answers) do diff --git a/spec/lib/journey_subject_eligibility_checker_spec.rb b/spec/lib/journey_subject_eligibility_checker_spec.rb deleted file mode 100644 index c4daf1fb00..0000000000 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ /dev/null @@ -1,521 +0,0 @@ -require "rails_helper" -require "journey_subject_eligibility_checker" - -RSpec.describe JourneySubjectEligibilityChecker do - describe ".new" do - context "claim year validation" do - context "after LUP and ECP" do - specify { expect { described_class.new(claim_year: AcademicYear.new(2025), itt_year: AcademicYear.new(2024)) }.to raise_error("Claim year 2025/2026 is after ECP and LUP both ended") } - end - end - - context "ITT year validation" do - context "inside window" do - specify { expect { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new(2017)) }.not_to raise_error } - end - - context "outside window" do - specify { expect { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new(2016)) }.to raise_error("ITT year 2016/2017 is outside the window for claim year 2022/2023") } - end - - context "None of the above" do - specify { expect { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new) }.not_to raise_error } - end - end - end - - describe "#future_claim_years" do - context "2022/2023 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new(2021)) } - - specify { expect(subject.future_claim_years).to contain_exactly(AcademicYear.new(2023), AcademicYear.new(2024)) } - end - - context "2023/2024 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2023), itt_year: AcademicYear.new(2022)) } - - specify { expect(subject.future_claim_years).to contain_exactly(AcademicYear.new(2024)) } - end - - context "2024/2025 claim year" do - subject { described_class.new(claim_year: AcademicYear.new(2024), itt_year: AcademicYear.new(2023)) } - - specify { expect(subject.future_claim_years).to be_empty } - end - - context "None of the above ITT year" do - subject { described_class.new(claim_year: AcademicYear.new(2022), itt_year: AcademicYear.new) } - - specify { expect(subject.future_claim_years).to be_empty } - end - end - - describe "#current_subject_symbols" do - subject { described_class.new(claim_year: claim_year, itt_year: itt_year).current_subject_symbols(policy) } - - context "ECP" do - let(:policy) { Policies::EarlyCareerPayments } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "None of the above ITT year" do - let(:itt_year) { AcademicYear.new } - - it { is_expected.to be_empty } - end - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to be_empty } - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to be_empty } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to be_empty } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - - context "2023 ITT year" do - let(:itt_year) { AcademicYear.new(2023) } - - it { is_expected.to be_empty } - end - end - end - - context "LUP" do - let(:policy) { Policies::LevellingUpPremiumPayments } - let(:the_constant_lup_subjects) { [:chemistry, :computing, :mathematics, :physics] } - - context "claim year before 2022" do - let(:claim_year) { AcademicYear.new(2021) } - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to be_empty } - end - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 itt year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2018 itt year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2019 itt year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 itt year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 itt year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 itt year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2019 itt year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 itt year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 itt year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2022 itt year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 itt year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 itt year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 itt year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2022 itt year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2023 itt year" do - let(:itt_year) { AcademicYear.new(2023) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - end - - context "unsupported policy" do - let(:policy) { Policies::StudentLoans } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - specify { expect { described_class.new(claim_year: claim_year, itt_year: itt_year).current_subject_symbols(policy) }.to raise_error("Unsupported policy: StudentLoans") } - end - end - end - end - - describe "#future_subject_symbols" do - subject { described_class.new(claim_year: claim_year, itt_year: itt_year).future_subject_symbols(policy) } - - context "ECP" do - let(:policy) { Policies::EarlyCareerPayments } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "None of the above ITT year" do - let(:itt_year) { AcademicYear.new } - - it { is_expected.to be_empty } - end - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to be_empty } - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to be_empty } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(:mathematics) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(:chemistry, :foreign_languages, :mathematics, :physics) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to be_empty } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to be_empty } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - - context "2023 ITT year" do - let(:itt_year) { AcademicYear.new(2023) } - - it { is_expected.to be_empty } - end - end - end - - context "LUP" do - let(:policy) { Policies::LevellingUpPremiumPayments } - let(:the_constant_lup_subjects) { [:chemistry, :computing, :mathematics, :physics] } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - it { is_expected.to be_empty } - end - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2023 claim year" do - let(:claim_year) { AcademicYear.new(2023) } - - context "2018 ITT year" do - let(:itt_year) { AcademicYear.new(2018) } - - it { is_expected.to be_empty } - end - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to contain_exactly(*the_constant_lup_subjects) } - end - end - - context "2024 claim year" do - let(:claim_year) { AcademicYear.new(2024) } - - context "2019 ITT year" do - let(:itt_year) { AcademicYear.new(2019) } - - it { is_expected.to be_empty } - end - - context "2020 ITT year" do - let(:itt_year) { AcademicYear.new(2020) } - - it { is_expected.to be_empty } - end - - context "2021 ITT year" do - let(:itt_year) { AcademicYear.new(2021) } - - it { is_expected.to be_empty } - end - - context "2022 ITT year" do - let(:itt_year) { AcademicYear.new(2022) } - - it { is_expected.to be_empty } - end - end - end - - context "unsupported policy" do - let(:policy) { Policies::StudentLoans } - - context "2022 claim year" do - let(:claim_year) { AcademicYear.new(2022) } - - context "2017 ITT year" do - let(:itt_year) { AcademicYear.new(2017) } - - specify { expect { described_class.new(claim_year: claim_year, itt_year: itt_year).future_subject_symbols(policy) }.to raise_error("Unsupported policy: StudentLoans") } - end - end - end - end -end diff --git a/spec/models/policies/early_career_payments/dqt_record_spec.rb b/spec/models/policies/early_career_payments/dqt_record_spec.rb index 641eca89ed..c30fb04b2f 100644 --- a/spec/models/policies/early_career_payments/dqt_record_spec.rb +++ b/spec/models/policies/early_career_payments/dqt_record_spec.rb @@ -2251,7 +2251,7 @@ let(:itt_subjects) { ["mathematics"] } before do - allow(JourneySubjectEligibilityChecker).to receive(:new) + allow(Policies::EarlyCareerPayments).to receive(:current_and_future_subject_symbols) .and_raise(StandardError.new("ITT year")) end From 3e3173500b76faaebe9f670ddf8bc7c1b56f84aa Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 20 Nov 2024 13:29:25 +0000 Subject: [PATCH 10/17] Rename some methods Just making the code a little easier to follow --- .../additional_payments_for_teaching/slug_sequence.rb | 4 ++-- app/models/journeys/page_sequence.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb b/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb index 24871f9f85..730ef87c1d 100644 --- a/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb +++ b/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb @@ -133,7 +133,7 @@ def slugs end if answers.trainee_teacher? - trainee_teacher_slugs(sequence) + trainee_teacher_slugs!(sequence) sequence.delete("eligible-degree-subject") unless lup_eligibility_checker.indicated_ineligible_itt_subject? else sequence.delete("ineligible") unless [:ineligible, :eligible_later].include?(overall_eligibility_status) @@ -192,7 +192,7 @@ def replace_ecp_only_induction_not_completed_slugs(sequence) # This method swaps out the entire slug sequence and replaces it with this tiny # journey. - def trainee_teacher_slugs(sequence) + def trainee_teacher_slugs!(sequence) trainee_slugs = %w[ current-school nqt-in-academic-year-after-itt diff --git a/app/models/journeys/page_sequence.rb b/app/models/journeys/page_sequence.rb index 7502598ff5..ce2c27b95a 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -88,10 +88,10 @@ def can_skip_next_slug? end def lup_policy_and_trainee_teacher_at_lup_school? - journey == Journeys::AdditionalPaymentsForTeaching && lup_teacher_at_lup_school + journey == Journeys::AdditionalPaymentsForTeaching && lup_trainee_at_lup_school end - def lup_teacher_at_lup_school + def lup_trainee_at_lup_school answers.nqt_in_academic_year_after_itt == false && Policies::LevellingUpPremiumPayments::SchoolEligibility.new(answers.current_school).eligible? end From be3526375693abcde0c04cc4b0a156c3bdd7ddfd Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 20 Nov 2024 13:48:43 +0000 Subject: [PATCH 11/17] Remove this conditional branch This branch can't get hit as this method is only called when the claimant is a trainee teacher, ie `nqt_in_academic_year_after_itt` is `false`. --- app/models/journeys/page_sequence.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/journeys/page_sequence.rb b/app/models/journeys/page_sequence.rb index ce2c27b95a..48c313e810 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -98,11 +98,7 @@ def lup_trainee_at_lup_school def handle_trainee_teacher case current_slug when "nqt-in-academic-year-after-itt" - if answers.nqt_in_academic_year_after_itt? - "supply-teacher" - else - @journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) ? "eligible-itt-subject" : "ineligible" - end + @journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) ? "eligible-itt-subject" : "ineligible" when "eligible-itt-subject" if answers.eligible_itt_subject.to_sym.in? Policies::LevellingUpPremiumPayments.fixed_subject_symbols "future-eligibility" From 6ec0f04aef99dee737c975d597a2521de677cfe8 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 20 Nov 2024 14:36:11 +0000 Subject: [PATCH 12/17] Remove trainee_teacher from common_ineligible_attributes ECP `specific_ineligible_attributes?` already checks if `trainee_teacher?` is set. For LUP trainee teachers can still be eligible later, so we want to make sure we don't return ineligible in that case. This previously hasn't surfaced as an issue due to how the code was called (a short circut specific to trainee teachers in the page sequence) but we want to move some of the code around which exposes this bug. --- app/models/concerns/eligibility_checkable.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index b20c041331..2e1d12cbc6 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -51,7 +51,6 @@ def trainee_teacher? def common_ineligible_attributes? [ indicated_ineligible_school?, - trainee_teacher?, supply_teacher_lacking_either_long_contract_or_direct_employment?, poor_performance?, no_selectable_subjects?, From f93f6f656de5002ed9f0acd97f473b487fa56415 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 20 Nov 2024 15:27:34 +0000 Subject: [PATCH 13/17] Remove more branches from trainee journey Removes the ineligiblity branches from the special case trainee teacher journey. We want all eligibility checking to happen in one place (the policy eligibility checker). This commit updates the mini trainee journey to not check eligibility. This also surfaced a bug in the policy eligiblity checker, a trainee teacher with an ineligible itt subject is not yet ineligible, they may still be eligible later, we don't know until they've entered their degree subject (at least according to the logic in `spec/features/trainee_teacher_subjourney_for_lup_schools_spec.rb:59`) --- app/models/journeys/page_sequence.rb | 12 ++++-------- .../policy_eligibility_checker.rb | 6 +----- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/app/models/journeys/page_sequence.rb b/app/models/journeys/page_sequence.rb index 48c313e810..96a494ead3 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -20,12 +20,12 @@ def slugs end def next_slug + return "ineligible" if journey_ineligible? + if lup_policy_and_trainee_teacher_at_lup_school? return handle_trainee_teacher end - return "ineligible" if journey_ineligible? - if claim_submittable? return "student-loan-amount" if updating_personal_details? && in_sequence?("student-loan-amount") return "check-your-answers" @@ -98,7 +98,7 @@ def lup_trainee_at_lup_school def handle_trainee_teacher case current_slug when "nqt-in-academic-year-after-itt" - @journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) ? "eligible-itt-subject" : "ineligible" + "eligible-itt-subject" when "eligible-itt-subject" if answers.eligible_itt_subject.to_sym.in? Policies::LevellingUpPremiumPayments.fixed_subject_symbols "future-eligibility" @@ -106,11 +106,7 @@ def handle_trainee_teacher "eligible-degree-subject" end when "eligible-degree-subject" - if @journey_session.answers.eligible_degree_subject? - "future-eligibility" - else - "ineligible" - end + "future-eligibility" end end diff --git a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb index 4361b67e76..9eb213964a 100644 --- a/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb +++ b/app/models/policies/levelling_up_premium_payments/policy_eligibility_checker.rb @@ -74,11 +74,7 @@ def eligible_degree? end def specific_ineligible_attributes? - indicated_ecp_only_itt_subject? || trainee_teacher_with_ineligible_itt_subject? || ineligible_itt_subject_and_no_relevant_degree? - end - - def trainee_teacher_with_ineligible_itt_subject? - trainee_teacher? && indicated_ineligible_itt_subject? + indicated_ecp_only_itt_subject? || ineligible_itt_subject_and_no_relevant_degree? end def ineligible_itt_subject_and_no_relevant_degree? From 8a7f1fe067e3450440943eefeb11902f9b63085f Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Wed, 20 Nov 2024 15:49:15 +0000 Subject: [PATCH 14/17] Remove AP specifc logic from page sequence Previously the page sequence contained specific logic for handling an additional payments sub journey (traniee teacher), and rather than modifying the slug sequence just overwrote what is returned. Additionally there was a condition in the slug sequence that caused the whole thing to be swapped out if we were dealing with a trainee teacher. This commit removes the additional payments specific handling from the page sequence, leaving it journey agnostic, and updates the additional payments slug sequence to move the trainee teacher sub journey branching to the top level. --- .../slug_sequence.rb | 53 ++++++++++--------- app/models/journeys/page_sequence.rb | 27 ---------- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb b/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb index 730ef87c1d..500a5075a7 100644 --- a/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb +++ b/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb @@ -73,6 +73,15 @@ class SlugSequence RESULTS_SLUGS ).freeze + TRAINEE_TEACHER_SLUGS = %w[ + current-school + nqt-in-academic-year-after-itt + eligible-itt-subject + eligible-degree-subject + future-eligibility + ineligible + ] + attr_reader :journey_session delegate :answers, to: :journey_session @@ -81,9 +90,15 @@ def initialize(journey_session) @journey_session = journey_session end - # Even though we are inside the ECP namespace, this method can modify the - # slug sequence of both LUP and ECP claims def slugs + if answers.trainee_teacher? && Policies::LevellingUpPremiumPayments::SchoolEligibility.new(answers.current_school).eligible? + lup_trainee_journey_slugs + else + non_trainee_journey_slugs + end + end + + def non_trainee_journey_slugs SLUGS.dup.tap do |sequence| if !Journeys::AdditionalPaymentsForTeaching.configuration.teacher_id_enabled? sequence.delete("sign-in-or-continue") @@ -132,14 +147,9 @@ def slugs sequence.delete("mobile-verification") end - if answers.trainee_teacher? - trainee_teacher_slugs!(sequence) - sequence.delete("eligible-degree-subject") unless lup_eligibility_checker.indicated_ineligible_itt_subject? - else - sequence.delete("ineligible") unless [:ineligible, :eligible_later].include?(overall_eligibility_status) - sequence.delete("future-eligibility") - sequence.delete("eligible-degree-subject") unless ecp_eligibility_checker.status == :ineligible && lup_eligibility_checker.indicated_ineligible_itt_subject? - end + sequence.delete("ineligible") unless [:ineligible, :eligible_later].include?(overall_eligibility_status) + sequence.delete("future-eligibility") + sequence.delete("eligible-degree-subject") unless ecp_eligibility_checker.status == :ineligible && lup_eligibility_checker.indicated_ineligible_itt_subject? sequence.delete("induction-completed") unless induction_question_required? @@ -164,6 +174,14 @@ def slugs end end + def lup_trainee_journey_slugs + TRAINEE_TEACHER_SLUGS.dup.tap do |sequence| + if lup_eligibility_checker.status == :eligible_later && answers.eligible_degree_subject.nil? + sequence.delete("eligible-degree-subject") + end + end + end + def self.start_page_url Rails.application.routes.url_helpers.landing_page_path("additional-payments") end @@ -190,21 +208,6 @@ def replace_ecp_only_induction_not_completed_slugs(sequence) sequence.replace(slugs) end - # This method swaps out the entire slug sequence and replaces it with this tiny - # journey. - def trainee_teacher_slugs!(sequence) - trainee_slugs = %w[ - current-school - nqt-in-academic-year-after-itt - eligible-itt-subject - eligible-degree-subject - future-eligibility - ineligible - ] - - [sequence.dup - trainee_slugs].flatten.each { |slug| sequence.delete(slug) } - end - def induction_question_required? # Induction question is not required if an ECP-eligible school is not selected. return false unless ecp_school_selected? diff --git a/app/models/journeys/page_sequence.rb b/app/models/journeys/page_sequence.rb index 96a494ead3..6d1a85feee 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -22,10 +22,6 @@ def slugs def next_slug return "ineligible" if journey_ineligible? - if lup_policy_and_trainee_teacher_at_lup_school? - return handle_trainee_teacher - end - if claim_submittable? return "student-loan-amount" if updating_personal_details? && in_sequence?("student-loan-amount") return "check-your-answers" @@ -87,29 +83,6 @@ def can_skip_next_slug? true if current_slug == "select-home-address" && answers.postcode.present? end - def lup_policy_and_trainee_teacher_at_lup_school? - journey == Journeys::AdditionalPaymentsForTeaching && lup_trainee_at_lup_school - end - - def lup_trainee_at_lup_school - answers.nqt_in_academic_year_after_itt == false && Policies::LevellingUpPremiumPayments::SchoolEligibility.new(answers.current_school).eligible? - end - - def handle_trainee_teacher - case current_slug - when "nqt-in-academic-year-after-itt" - "eligible-itt-subject" - when "eligible-itt-subject" - if answers.eligible_itt_subject.to_sym.in? Policies::LevellingUpPremiumPayments.fixed_subject_symbols - "future-eligibility" - else - "eligible-degree-subject" - end - when "eligible-degree-subject" - "future-eligibility" - end - end - def current_slug_index slugs.index(current_slug) || 0 end From 54191e15f0e78b427414173423bb5e3e5210c8cf Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Thu, 21 Nov 2024 15:59:32 +0000 Subject: [PATCH 15/17] Use LUP policy date range for lup claims LUP will extend past ECP, so we can't use the combined end date when deciding what subjects to show for nqts who haven't entered an itt, otherwise we render an empty list on the itt subject screen. --- app/models/journeys/additional_payments_for_teaching.rb | 2 +- app/models/policies/levelling_up_premium_payments.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index b471564547..3b5ad6b6a3 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -54,7 +54,7 @@ def selectable_subject_symbols(journey_session) itt_year: journey_session.answers.itt_academic_year ) end.flatten.uniq - elsif journey_session.answers.policy_year.in?(EligibilityCheckable::COMBINED_ECP_AND_LUP_POLICY_YEARS_BEFORE_FINAL_YEAR) + elsif journey_session.answers.policy_year.in?(Policies::LevellingUpPremiumPayments::POLICY_RANGE) # they get the standard, unchanging LUP subject set because they won't have qualified in time for ECP by 2022/2023 # and they won't have given an ITT year Policies::LevellingUpPremiumPayments.fixed_subject_symbols diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index d7cec6ec7d..9a3ab6331e 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -28,6 +28,7 @@ module LevellingUpPremiumPayments POLICY_START_YEAR = AcademicYear.new(2022).freeze POLICY_END_YEAR = AcademicYear.new(2025).freeze + POLICY_RANGE = POLICY_START_YEAR..POLICY_END_YEAR # Percentage of claims to QA MIN_QA_THRESHOLD = 10 @@ -131,7 +132,7 @@ def fixed_subject_symbols end def subject_symbols(claim_year:, itt_year:) - return [] unless (POLICY_START_YEAR..POLICY_END_YEAR).cover?(claim_year) + return [] unless POLICY_RANGE.cover?(claim_year) previous_five_years = (claim_year - 5)...claim_year From e60be77f8ba71ff18696f136751811edca4f1ee6 Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Tue, 3 Dec 2024 15:01:39 +0000 Subject: [PATCH 16/17] Fix hint text Previously the hint text was showing all subjects to claimants, even if they were not eligible for those subjects, instead only show subjects the claimant is eligible for. If the claimant is not eligible for any subjects they will have been kicked out of the journey prior to this screen. --- app/helpers/claims/itt_subject_helper.rb | 5 ++++- spec/helpers/claims/itt_subject_helper_spec.rb | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/helpers/claims/itt_subject_helper.rb b/app/helpers/claims/itt_subject_helper.rb index 2a6a4253e7..07ad7d2d31 100644 --- a/app/helpers/claims/itt_subject_helper.rb +++ b/app/helpers/claims/itt_subject_helper.rb @@ -1,7 +1,10 @@ module Claims module IttSubjectHelper def subjects_to_sentence_for_hint_text(answers) - all_ecp_subjects = [:chemistry, :foreign_languages, :mathematics, :physics] + all_ecp_subjects = Policies::EarlyCareerPayments.subject_symbols( + claim_year: answers.policy_year, + itt_year: answers.itt_academic_year + ) all_lup_subjects = Policies::LevellingUpPremiumPayments.fixed_subject_symbols hint_subject_symbols = Set[] diff --git a/spec/helpers/claims/itt_subject_helper_spec.rb b/spec/helpers/claims/itt_subject_helper_spec.rb index 77ac2364c0..3c1c4b4ff3 100644 --- a/spec/helpers/claims/itt_subject_helper_spec.rb +++ b/spec/helpers/claims/itt_subject_helper_spec.rb @@ -94,7 +94,8 @@ build( :additional_payments_answers, :lup_ineligible, - :ecp_eligible_later + :ecp_eligible_later, + itt_academic_year: AcademicYear.new(2020) ) end From 5650863cd8e0775c09e31964ec0f3f14df8c2f5b Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Thu, 5 Dec 2024 14:12:04 +0000 Subject: [PATCH 17/17] ECP is ineligible if policy is closed This is additional functionality, so may want splitting out into a separate PR, but it was requested as part of this ticket. If the current acadmic year is after the ECP policy close date, then selecting an ECP only school should show the claimant the ineligible screen. There's a slight bit of trickyness, the ECP::Eligibility model has an enum for itt academic year, that only allows values for dates within the ECP policy, or nil, adding a date outside this range throws an error. The page sequences calls the claim submission form which constructs an eligibility to check if the journey is completed, if the user chooses an itt date that's outside the ECP policy range (possible for future academic years) constructing the ecp eligibility throws an error. To avoid this we're using the new `validate` option on enum, so rather than throw an error when adding a date out side the range it now generates a validation error. Some of the tests needed updating to add a valid itt academic year as now ecp eligibility isn't valid if it's missing the itt year. --- app/models/concerns/eligibility_checkable.rb | 5 ++ app/models/policies/early_career_payments.rb | 4 + .../early_career_payments/eligibility.rb | 2 +- .../policies/levelling_up_premium_payments.rb | 4 + ...ineligibility_ecp_only_ecp_closed.html.erb | 17 ++++ lib/ineligibility_reason_checker.rb | 13 ++- .../early_career_payments/eligibilities.rb | 4 + .../combined_teacher_claim_journey_spec.rb | 86 ++++++++++++++++++- .../early_career_payments/eligibility_spec.rb | 28 +++--- 9 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index 2e1d12cbc6..f2b769667f 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -50,6 +50,7 @@ def trainee_teacher? def common_ineligible_attributes? [ + policy_closed?, indicated_ineligible_school?, supply_teacher_lacking_either_long_contract_or_direct_employment?, poor_performance?, @@ -59,6 +60,10 @@ def common_ineligible_attributes? ].any? end + def policy_closed? + policy.closed?(claim_year) + end + def indicated_ineligible_school? current_school.present? && !policy::SchoolEligibility.new(current_school).eligible? end diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index a0289b1ffd..bc5f165769 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -173,5 +173,9 @@ def future_years(year) def selectable_itt_years_for_claim_year(claim_year) (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a end + + def closed?(claim_year) + claim_year > POLICY_END_YEAR + end end end diff --git a/app/models/policies/early_career_payments/eligibility.rb b/app/models/policies/early_career_payments/eligibility.rb index 43e768c20d..eb182254de 100644 --- a/app/models/policies/early_career_payments/eligibility.rb +++ b/app/models/policies/early_career_payments/eligibility.rb @@ -34,7 +34,7 @@ def policy hsh[year] = AcademicYear::Type.new.serialize(year) end.merge({AcademicYear.new => AcademicYear::Type.new.serialize(AcademicYear.new)}) - enum :itt_academic_year, ITT_ACADEMIC_YEARS + enum :itt_academic_year, ITT_ACADEMIC_YEARS, validate: true enum :qualification, { postgraduate_itt: 0, diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 9a3ab6331e..e2a41761a7 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -158,5 +158,9 @@ def future_years(year) def selectable_itt_years_for_claim_year(claim_year) (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a end + + def closed?(claim_year) + claim_year > POLICY_END_YEAR + end end end diff --git a/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb b/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb new file mode 100644 index 0000000000..7931af3f8b --- /dev/null +++ b/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb @@ -0,0 +1,17 @@ +

+ You are not eligible for the + <%= link_to("early-career payment (opens in new tab)", Policies::EarlyCareerPayments.eligibility_criteria_url, class: "govuk-link", target: "_blank") %> + because the policy has now closed. +

+

+ You are not eligible for the + <%= link_to("#{I18n.t("levelling_up_premium_payments.policy_short_name").downcase} (opens in new tab)", Policies::LevellingUpPremiumPayments.eligibility_criteria_url, class: "govuk-link", target: "_blank") %> + because the school you teach in is not eligible. <%= I18n.t("levelling_up_premium_payments.policy_short_name").capitalize.pluralize %> are offered in schools identified as having a higher need for teachers. +

+ +

+ For more information, check the eligibility criteria for + <%= link_to("early-career payments", Policies::EarlyCareerPayments.eligibility_criteria_url, class: "govuk-link") %> + and + <%= link_to(I18n.t("levelling_up_premium_payments.policy_short_name").downcase.pluralize, Policies::LevellingUpPremiumPayments.eligibility_criteria_url, class: "govuk-link") %>. +

diff --git a/lib/ineligibility_reason_checker.rb b/lib/ineligibility_reason_checker.rb index 20b34c42ea..e2889067e1 100644 --- a/lib/ineligibility_reason_checker.rb +++ b/lib/ineligibility_reason_checker.rb @@ -4,7 +4,9 @@ def initialize(answers) end def reason - if current_school? + if ecp_only_and_ecp_closed? + :ecp_only_ecp_closed + elsif current_school? :current_school elsif dqt_data_ineligible? :dqt_data_ineligible @@ -41,6 +43,15 @@ def reason private + def ecp_only_and_ecp_closed? + school = @answers.current_school + + [ + Policies::EarlyCareerPayments::SchoolEligibility.new(school).eligible?, + !Policies::LevellingUpPremiumPayments::SchoolEligibility.new(school).eligible? + ].all? && Policies::EarlyCareerPayments.closed?(@answers.policy_year) + end + def current_school? school = @answers.current_school diff --git a/spec/factories/policies/early_career_payments/eligibilities.rb b/spec/factories/policies/early_career_payments/eligibilities.rb index dfcccd38df..f23e0b12cf 100644 --- a/spec/factories/policies/early_career_payments/eligibilities.rb +++ b/spec/factories/policies/early_career_payments/eligibilities.rb @@ -2,6 +2,10 @@ factory :early_career_payments_eligibility, class: "Policies::EarlyCareerPayments::Eligibility" do award_amount { 5000.0 } + itt_academic_year do + Journeys.for_policy(Policies::EarlyCareerPayments).configuration.current_academic_year - 3 + end + trait :eligible do teacher_reference_number { generate(:teacher_reference_number) } eligible_now diff --git a/spec/features/combined_teacher_claim_journey_spec.rb b/spec/features/combined_teacher_claim_journey_spec.rb index 42e6229cf1..53c08457d7 100644 --- a/spec/features/combined_teacher_claim_journey_spec.rb +++ b/spec/features/combined_teacher_claim_journey_spec.rb @@ -6,9 +6,9 @@ end let(:eligibility) { claim.eligibility } - before { create(:journey_configuration, :additional_payments, current_academic_year: AcademicYear.new(2023)) } - scenario "Eligible for both" do + create(:journey_configuration, :additional_payments, current_academic_year: AcademicYear.new(2023)) + school = create(:school, :combined_journey_eligibile_for_all) visit new_claim_path(Journeys::AdditionalPaymentsForTeaching::ROUTING_NAME) @@ -243,6 +243,8 @@ end scenario "Eligible for only one" do + create(:journey_configuration, :additional_payments, current_academic_year: AcademicYear.new(2023)) + school = create(:school, :early_career_payments_uplifted) visit new_claim_path(Journeys::AdditionalPaymentsForTeaching::ROUTING_NAME) @@ -323,4 +325,84 @@ expect(page).not_to have_selector('input[type="radio"]') expect(page).to have_button("Apply now") end + + context "when ECP is closed" do + before do + create( + :journey_configuration, + :additional_payments, + current_academic_year: AcademicYear.new(2025) + ) + end + + scenario "choosing an ecp only school is ineligible" do + school = create(:school, :early_career_payments_eligible) + + visit new_claim_path(Journeys::AdditionalPaymentsForTeaching::ROUTING_NAME) + + click_on "Continue without signing" + + choose_school school + + expect(page).to have_content "You are not eligible" + expect(page).to have_content "the policy has now closed" + end + + scenario "choosing a lup eligible school allows completing the journey" do + school = create(:school, :combined_journey_eligibile_for_all) + + visit new_claim_path(Journeys::AdditionalPaymentsForTeaching::ROUTING_NAME) + + click_on "Continue without signing" + + choose_school school + click_on "Continue" + + # - Have you started your first year as a newly qualified teacher? + choose "Yes" + click_on "Continue" + + # - Have you completed your induction as an early-career teacher? + choose "Yes" + click_on "Continue" + + # - Are you currently employed as a supply teacher + choose "No" + click_on "Continue" + + # - Poor performance + within all(".govuk-fieldset")[0] do + choose("No") + end + within all(".govuk-fieldset")[1] do + choose("No") + end + click_on "Continue" + + # - What route into teaching did you take? + choose("Undergraduate initial teacher training (ITT)") + click_on "Continue" + + # - In which academic year did you complete your undergraduate ITT? + choose("2024 to 2025") + click_on "Continue" + + # - Which subject did you do your undergraduate ITT in + choose "Mathematics" + click_on "Continue" + + # Do you spend at least half of your contracted hours teaching eligible + # subjects? + choose "Yes" + click_on "Continue" + + # Check your answers + click_on "Continue" + + expect(page).to have_content("You’re eligible for an additional payment") + expect(page).to have_content( + "you can apply for a school targeted retention incentive" + ) + end + end end diff --git a/spec/models/policies/early_career_payments/eligibility_spec.rb b/spec/models/policies/early_career_payments/eligibility_spec.rb index c4e7f008a3..4afb7a0527 100644 --- a/spec/models/policies/early_career_payments/eligibility_spec.rb +++ b/spec/models/policies/early_career_payments/eligibility_spec.rb @@ -3,6 +3,14 @@ require "rails_helper" RSpec.describe Policies::EarlyCareerPayments::Eligibility, type: :model do + let(:academic_year) do + Policies::EarlyCareerPayments::Eligibility::ITT_ACADEMIC_YEARS.keys.first + end + + before do + create(:journey_configuration, :additional_payments) + end + describe "#policy" do let(:early_career_payments_eligibility) { build(:early_career_payments_eligibility) } @@ -16,7 +24,7 @@ context "current_school not set and school_somewhere_else is not set return one is required error" do it "returns an error" do - eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: nil, school_somewhere_else: nil) + eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: nil, school_somewhere_else: nil, itt_academic_year: academic_year) expect(eligibility).not_to be_valid(:"correct-school") expect(eligibility.errors.messages[:current_school]).to eq(["Select the school you teach at or choose somewhere else"]) @@ -25,7 +33,7 @@ context "selects a school suggested from TPS" do it "sets current_school and sets school_somewhere_else to false" do - eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: school, school_somewhere_else: false) + eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: school, school_somewhere_else: false, itt_academic_year: academic_year) expect(eligibility).to be_valid(:"correct-school") end @@ -33,14 +41,14 @@ context "selects somewhere else and not the suggested school" do it "sets school_somewhere_else to true and current_school stays nil" do - eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: nil, school_somewhere_else: true) + eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: nil, school_somewhere_else: true, itt_academic_year: academic_year) expect(eligibility).to be_valid(:"correct-school") end # e.g. the teacher presses the backlink a school is already set it "sets school_somewhere_else to true and current_school stays remains if already set" do - eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: school, school_somewhere_else: true) + eligibility = Policies::EarlyCareerPayments::Eligibility.new(current_school: school, school_somewhere_else: true, itt_academic_year: academic_year) expect(eligibility).to be_valid(:"correct-school") end @@ -108,18 +116,18 @@ end it "validates that award_amount is a positive number" do - expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: -1_000)).not_to be_valid - expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: 2_500)).to be_valid + expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: -1_000, itt_academic_year: academic_year)).not_to be_valid + expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: 2_500, itt_academic_year: academic_year)).to be_valid end it "validates that award_amount can be zero" do - expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: 0)).to be_valid + expect(Policies::EarlyCareerPayments::Eligibility.new(award_amount: 0, itt_academic_year: academic_year)).to be_valid end it "validates that the award_amount is less than £7,500 when amending a claim" do - expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_501)).not_to be_valid(:amendment) - expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_500)).to be_valid(:amendment) - expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_499)).to be_valid(:amendment) + expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_501, itt_academic_year: academic_year)).not_to be_valid(:amendment) + expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_500, itt_academic_year: academic_year)).to be_valid(:amendment) + expect(Policies::EarlyCareerPayments::Eligibility.new(teacher_reference_number: "1234567", award_amount: 7_499, itt_academic_year: academic_year)).to be_valid(:amendment) end end end