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/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/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 diff --git a/app/helpers/claims/itt_subject_helper.rb b/app/helpers/claims/itt_subject_helper.rb index 5cd55a0fda..07ad7d2d31 100644 --- a/app/helpers/claims/itt_subject_helper.rb +++ b/app/helpers/claims/itt_subject_helper.rb @@ -1,10 +1,11 @@ -require "journey_subject_eligibility_checker" - 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_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/app/models/academic_year.rb b/app/models/academic_year.rb index a0588564e7..6aca6d23d8 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) @@ -101,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 b5decfc117..f2b769667f 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 @@ -50,7 +49,19 @@ 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? + [ + policy_closed?, + indicated_ineligible_school?, + supply_teacher_lacking_either_long_contract_or_direct_employment?, + poor_performance?, + no_selectable_subjects?, + ineligible_cohort?, + insufficient_teaching? + ].any? + end + + def policy_closed? + policy.closed?(claim_year) end def indicated_ineligible_school? @@ -66,19 +77,20 @@ 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 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 @@ -113,7 +125,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/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/journeys/additional_payments_for_teaching.rb b/app/models/journeys/additional_payments_for_teaching.rb index 83c2dbafb6..3b5ad6b6a3 100644 --- a/app/models/journeys/additional_payments_for_teaching.rb +++ b/app/models/journeys/additional_payments_for_teaching.rb @@ -30,24 +30,43 @@ 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) + eligible_itt_years = selectable_itt_years_for_claim_year(next_year) eligible_itt_years.include?(itt_academic_year) end 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?(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 + else + [] + 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/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/additional_payments_for_teaching/slug_sequence.rb b/app/models/journeys/additional_payments_for_teaching/slug_sequence.rb index 24871f9f85..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/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..6d1a85feee 100644 --- a/app/models/journeys/page_sequence.rb +++ b/app/models/journeys/page_sequence.rb @@ -20,10 +20,6 @@ def slugs end def next_slug - if lup_policy_and_trainee_teacher_at_lup_school? - return handle_trainee_teacher - end - return "ineligible" if journey_ineligible? if claim_submittable? @@ -87,37 +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_teacher_at_lup_school - end - - def lup_teacher_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" - 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 - when "eligible-itt-subject" - if answers.eligible_itt_subject.to_sym.in? JourneySubjectEligibilityChecker.fixed_lup_subject_symbols - "future-eligibility" - else - "eligible-degree-subject" - end - when "eligible-degree-subject" - if @journey_session.answers.eligible_degree_subject? - "future-eligibility" - else - "ineligible" - end - end - end - def current_slug_index slugs.index(current_slug) || 0 end diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index 203b3475e4..bc5f165769 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -109,5 +109,73 @@ def payment_and_deductions_info_url 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) + 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 + + 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 + + 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/dqt_record.rb b/app/models/policies/early_career_payments/dqt_record.rb index 24432f5cea..4f7b7dbd24 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 @@ -62,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/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/early_career_payments/policy_eligibility_checker.rb b/app/models/policies/early_career_payments/policy_eligibility_checker.rb index d634e75ffb..30ba961afc 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,102 @@ 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? + + EarlyCareerPayments.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(itt_subject.to_sym) + 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? + + 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? + 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? + + EarlyCareerPayments.future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(itt_subject.to_sym) + 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 + EarlyCareerPayments.current_and_future_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).exclude?(itt_subject_symbol) + end + 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 6926875a2f..e2a41761a7 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -27,7 +27,8 @@ 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 + POLICY_RANGE = POLICY_START_YEAR..POLICY_END_YEAR # Percentage of claims to QA MIN_QA_THRESHOLD = 10 @@ -99,5 +100,67 @@ def payroll_file_name 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 + + # 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 + + def subject_symbols(claim_year:, itt_year:) + return [] unless POLICY_RANGE.cover?(claim_year) + + previous_five_years = (claim_year - 5)...claim_year + + if previous_five_years.cover?(itt_year) + 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 + + 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/levelling_up_premium_payments/dqt_record.rb b/app/models/policies/levelling_up_premium_payments/dqt_record.rb index 5146d94889..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 @@ -110,7 +108,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/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..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 @@ -1,7 +1,6 @@ module Policies module LevellingUpPremiumPayments class PolicyEligibilityChecker - include Eligible include EligibilityCheckable attr_reader :answers @@ -11,6 +10,84 @@ 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? + + if claim_year.blank? || itt_academic_year.blank? + # trainee teacher who won't have given their ITT year + eligible_itt_subject.present? && LevellingUpPremiumPayments.fixed_subject_symbols.exclude?(eligible_itt_subject.to_sym) + else + LevellingUpPremiumPayments.subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).exclude?(eligible_itt_subject.to_sym) + 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? + + 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 + LevellingUpPremiumPayments.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_academic_year + ).include?(eligible_itt_subject.to_sym) + end + end + + def eligible_degree? + eligible_degree_subject? + end + + def specific_ineligible_attributes? + indicated_ecp_only_itt_subject? || ineligible_itt_subject_and_no_relevant_degree? + 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/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/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/ineligibility_reason_checker.rb b/lib/ineligibility_reason_checker.rb index 8362bbf821..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 @@ -154,10 +165,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 deleted file mode 100644 index e1f527a33d..0000000000 --- a/lib/journey_subject_eligibility_checker.rb +++ /dev/null @@ -1,170 +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 - - 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( - 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 - - 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. - 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 - - 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 - - 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 - - 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?(selectable_itt_years) - 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) - - 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 - end -end 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/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..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 @@ -139,11 +139,22 @@ 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 = policy.selectable_itt_years_for_claim_year(claim_year) + + itt_years.detect do |itt_year| + subject_symbol.in?( + policy.current_subject_symbols( + claim_year: claim_year, + itt_year: itt_year + ) + ) + end } context "with EarlyCareerPayments policy" do 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/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/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..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 @@ -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 @@ -50,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 @@ -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/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 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/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 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 ca4f792b69..0000000000 --- a/spec/lib/journey_subject_eligibility_checker_spec.rb +++ /dev/null @@ -1,1188 +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 "#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) } - - 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 - - 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( - 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 ".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 -end diff --git a/spec/models/early_career_payments_spec.rb b/spec/models/early_career_payments_spec.rb index 40f6498a9a..180a47247a 100644 --- a/spec/models/early_career_payments_spec.rb +++ b/spec/models/early_career_payments_spec.rb @@ -31,4 +31,135 @@ 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 + + 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 f9be210508..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 } @@ -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..46dfc3e105 100644 --- a/spec/models/levelling_up_premium_payments_spec.rb +++ b/spec/models/levelling_up_premium_payments_spec.rb @@ -29,4 +29,133 @@ 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 + + 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 24ddbc1e97..c30fb04b2f 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) } @@ -2249,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 @@ -2261,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/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 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..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 @@ -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