From 5650863cd8e0775c09e31964ec0f3f14df8c2f5b Mon Sep 17 00:00:00 2001 From: Richard Lynch Date: Thu, 5 Dec 2024 14:12:04 +0000 Subject: [PATCH] ECP is ineligible if policy is closed This is additional functionality, so may want splitting out into a separate PR, but it was requested as part of this ticket. If the current acadmic year is after the ECP policy close date, then selecting an ECP only school should show the claimant the ineligible screen. There's a slight bit of trickyness, the ECP::Eligibility model has an enum for itt academic year, that only allows values for dates within the ECP policy, or nil, adding a date outside this range throws an error. The page sequences calls the claim submission form which constructs an eligibility to check if the journey is completed, if the user chooses an itt date that's outside the ECP policy range (possible for future academic years) constructing the ecp eligibility throws an error. To avoid this we're using the new `validate` option on enum, so rather than throw an error when adding a date out side the range it now generates a validation error. Some of the tests needed updating to add a valid itt academic year as now ecp eligibility isn't valid if it's missing the itt year. --- app/models/concerns/eligibility_checkable.rb | 5 ++ app/models/policies/early_career_payments.rb | 4 + .../early_career_payments/eligibility.rb | 2 +- .../policies/levelling_up_premium_payments.rb | 4 + ...ineligibility_ecp_only_ecp_closed.html.erb | 17 ++++ lib/ineligibility_reason_checker.rb | 13 ++- .../early_career_payments/eligibilities.rb | 4 + .../combined_teacher_claim_journey_spec.rb | 86 ++++++++++++++++++- .../early_career_payments/eligibility_spec.rb | 28 +++--- 9 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb diff --git a/app/models/concerns/eligibility_checkable.rb b/app/models/concerns/eligibility_checkable.rb index 2e1d12cbc6..f2b769667f 100644 --- a/app/models/concerns/eligibility_checkable.rb +++ b/app/models/concerns/eligibility_checkable.rb @@ -50,6 +50,7 @@ def trainee_teacher? def common_ineligible_attributes? [ + policy_closed?, indicated_ineligible_school?, supply_teacher_lacking_either_long_contract_or_direct_employment?, poor_performance?, @@ -59,6 +60,10 @@ def common_ineligible_attributes? ].any? end + def policy_closed? + policy.closed?(claim_year) + end + def indicated_ineligible_school? current_school.present? && !policy::SchoolEligibility.new(current_school).eligible? end diff --git a/app/models/policies/early_career_payments.rb b/app/models/policies/early_career_payments.rb index a0289b1ffd..bc5f165769 100644 --- a/app/models/policies/early_career_payments.rb +++ b/app/models/policies/early_career_payments.rb @@ -173,5 +173,9 @@ def future_years(year) def selectable_itt_years_for_claim_year(claim_year) (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a end + + def closed?(claim_year) + claim_year > POLICY_END_YEAR + end end end diff --git a/app/models/policies/early_career_payments/eligibility.rb b/app/models/policies/early_career_payments/eligibility.rb index 43e768c20d..eb182254de 100644 --- a/app/models/policies/early_career_payments/eligibility.rb +++ b/app/models/policies/early_career_payments/eligibility.rb @@ -34,7 +34,7 @@ def policy hsh[year] = AcademicYear::Type.new.serialize(year) end.merge({AcademicYear.new => AcademicYear::Type.new.serialize(AcademicYear.new)}) - enum :itt_academic_year, ITT_ACADEMIC_YEARS + enum :itt_academic_year, ITT_ACADEMIC_YEARS, validate: true enum :qualification, { postgraduate_itt: 0, diff --git a/app/models/policies/levelling_up_premium_payments.rb b/app/models/policies/levelling_up_premium_payments.rb index 9a3ab6331e..e2a41761a7 100644 --- a/app/models/policies/levelling_up_premium_payments.rb +++ b/app/models/policies/levelling_up_premium_payments.rb @@ -158,5 +158,9 @@ def future_years(year) def selectable_itt_years_for_claim_year(claim_year) (AcademicYear.new(claim_year - 5)...AcademicYear.new(claim_year)).to_a end + + def closed?(claim_year) + claim_year > POLICY_END_YEAR + end end end diff --git a/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb b/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb new file mode 100644 index 0000000000..7931af3f8b --- /dev/null +++ b/app/views/additional_payments/claims/_ineligibility_ecp_only_ecp_closed.html.erb @@ -0,0 +1,17 @@ +

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

+

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

+ +

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

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