From 93b4ea581effa35e7ce51d17ea3eab9aa06321b1 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Tue, 10 Feb 2026 17:43:13 +0000 Subject: [PATCH 01/11] Add reuse seeds and helper --- db/seeds/lead_providers.rb | 9 +- db/seeds/reuse_choices_scenarios.rb | 7 + db/seeds/support/seeds/reuse_choices.rb | 387 ++++++++++++++++++ spec/seeds/reuse_choices_seed_spec.rb | 187 +++++++++ .../seeds/reuse_choices_seed_helpers.rb | 79 ++++ 5 files changed, 666 insertions(+), 3 deletions(-) create mode 100644 db/seeds/reuse_choices_scenarios.rb create mode 100644 db/seeds/support/seeds/reuse_choices.rb create mode 100644 spec/seeds/reuse_choices_seed_spec.rb create mode 100644 spec/support/seeds/reuse_choices_seed_helpers.rb diff --git a/db/seeds/lead_providers.rb b/db/seeds/lead_providers.rb index 5a93765138..9df230dc99 100644 --- a/db/seeds/lead_providers.rb +++ b/db/seeds/lead_providers.rb @@ -19,12 +19,15 @@ def describe_lead_provider(lead_provider, years) ] lead_providers_data.each do |data| - lead_provider = LeadProvider.find_or_create_by!(data.slice(:name, :vat_registered)) + lead_provider = LeadProvider.find_or_initialize_by(name: data.fetch(:name)) + lead_provider.vat_registered = data.fetch(:vat_registered) + lead_provider.ecf_id ||= SecureRandom.uuid if lead_provider.has_attribute?(:ecf_id) + lead_provider.save! - data[:years].each do |year| + data.fetch(:years).each do |year| contract_period = ContractPeriod.find_by!(year:) ActiveLeadProvider.find_or_create_by!(lead_provider:, contract_period:) end - describe_lead_provider(lead_provider, data[:years]) + describe_lead_provider(lead_provider, data.fetch(:years)) end diff --git a/db/seeds/reuse_choices_scenarios.rb b/db/seeds/reuse_choices_scenarios.rb new file mode 100644 index 0000000000..91895997eb --- /dev/null +++ b/db/seeds/reuse_choices_scenarios.rb @@ -0,0 +1,7 @@ +require Rails.root.join("db/seeds/support/seeds/reuse_choices") + +return unless Rails.env.staging? || Rails.env.development? || Rails.env.review? + +Rails.logger.debug "Seeding reuse choices scenario schools (staging only)" + +Seeds::ReuseChoices.new(contract_period_year: 2025).call diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb new file mode 100644 index 0000000000..d5091093e3 --- /dev/null +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -0,0 +1,387 @@ +module Seeds + class ReuseChoices + BASE_URN = 9_100_100 + SCHEDULE_IDENTIFIER = "ecf-standard-september" + + LEAD_PROVIDER_REUSABLE_NAME = + "Reuse – Lead Provider One" + + LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME = + "Reuse – Lead Provider X (not available in target year)" + + DELIVERY_PARTNER_REUSABLE_NAME = + "Reuse – Delivery Partner One" + + DELIVERY_PARTNER_NOT_REUSABLE_NAME = + "Reuse – Delivery Partner Two" + + APPROPRIATE_BODY_NAME = + "Reuse – Appropriate Body" + + def initialize(contract_period_year:) + @contract_period_year = contract_period_year + end + + def call + ensure_contract_periods! + ensure_schedules! + ensure_reference_data! + ensure_target_year_availability_for_reusable_lead_provider! + + seed_blank_control_school! + seed_reusable_previous_scenarios! + seed_not_reusable_previous_scenarios! + end + + private + + attr_reader :contract_period_year + + def ensure_contract_periods! + years.each do |year| + ContractPeriod.find_or_create_by!(year:) do |cp| + cp.started_on = Date.new(year, 6, 1) + cp.finished_on = Date.new(year + 1, 5, 31) + cp.enabled = true + end + end + end + + def ensure_schedules! + years.each do |year| + contract_period = ContractPeriod.find_by!(year:) + + Schedule.find_or_create_by!( + contract_period:, + identifier: SCHEDULE_IDENTIFIER + ) + end + end + + def ensure_reference_data! + LeadProvider.find_or_create_by!(name: LEAD_PROVIDER_REUSABLE_NAME) + LeadProvider.find_or_create_by!(name: LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + + DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_REUSABLE_NAME) + DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) + + AppropriateBody.find_or_create_by!( + name: APPROPRIATE_BODY_NAME, + body_type: "teaching_school_hub" + ) + end + + def ensure_target_year_availability_for_reusable_lead_provider! + ActiveLeadProvider.find_or_create_by!( + lead_provider: reusable_lead_provider, + contract_period: target_contract_period + ) + end + + def years + (2021..contract_period_year).to_a + end + + def target_contract_period + @target_contract_period ||= ContractPeriod.find_by!(year: contract_period_year) + end + + def reusable_lead_provider + @reusable_lead_provider ||= LeadProvider.find_by!(name: LEAD_PROVIDER_REUSABLE_NAME) + end + + def lead_provider_not_available_in_target_year + @lead_provider_not_available_in_target_year ||= + LeadProvider.find_by!(name: LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + end + + def reusable_delivery_partner + @reusable_delivery_partner ||= DeliveryPartner.find_by!(name: DELIVERY_PARTNER_REUSABLE_NAME) + end + + def not_reusable_delivery_partner + @not_reusable_delivery_partner ||= DeliveryPartner.find_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) + end + + def matrix_appropriate_body + @matrix_appropriate_body ||= AppropriateBody.find_by!(name: APPROPRIATE_BODY_NAME) + end + + # Scenario group 1 – blank slate school + def seed_blank_control_school! + school = ensure_scenario_school!( + offset: 0, + gias_name: "Reuse scenario – blank slate (no previous programme)", + set_provider_led_last_chosen: false, + last_chosen_lead_provider: nil + ) + + ensure_school_partnership!( + school:, + lead_provider: reusable_lead_provider, + delivery_partner: reusable_delivery_partner, + year: contract_period_year + ) + end + + # Scenario group 2 – previous programme reusable in target year + def seed_reusable_previous_scenarios! + scenarios = [ + { offset: 1, previous_year: 2024, type: :partnership }, + { offset: 2, previous_year: 2024, type: :eoi }, + { offset: 3, previous_year: 2023, type: :partnership }, + { offset: 4, previous_year: 2023, type: :eoi }, + { offset: 5, previous_year: 2022, type: :partnership }, + { offset: 6, previous_year: 2022, type: :eoi }, + { offset: 7, previous_year: 2021, type: :partnership }, + { offset: 8, previous_year: 2021, type: :eoi }, + ] + + scenarios.each { |scenario| seed_reusable_previous_scenario!(**scenario) } + end + + def seed_reusable_previous_scenario!(offset:, previous_year:, type:) + label = "Reuse scenario – #{previous_year} #{type_label(type)} (reusable)" + school = ensure_scenario_school!( + offset:, + gias_name: label, + set_provider_led_last_chosen: true, + last_chosen_lead_provider: reusable_lead_provider + ) + + seed_previous_teacher_and_training!( + school:, + previous_year:, + mode: type, + lead_provider: reusable_lead_provider, + delivery_partner_for_partnership: reusable_delivery_partner + ) + + case type + when :partnership + ensure_school_partnership!( + school:, + lead_provider: reusable_lead_provider, + delivery_partner: reusable_delivery_partner, + year: contract_period_year + ) + when :eoi + ActiveLeadProvider.find_or_create_by!( + lead_provider: reusable_lead_provider, + contract_period: target_contract_period + ) + else + raise ArgumentError, "Unknown type: #{type.inspect}" + end + end + + # Scenario group 3 – previous programme NOT reusable in target year + # + # Rules: + # - partnership NOT reusable: LP exists in target year BUT pairing does NOT + # - EOI NOT reusable: LP does NOT exist in target year (no ALP in target year) + def seed_not_reusable_previous_scenarios! + scenarios = [ + { offset: 9, previous_year: 2024, type: :partnership }, + { offset: 10, previous_year: 2024, type: :eoi }, + { offset: 11, previous_year: 2023, type: :partnership }, + { offset: 12, previous_year: 2023, type: :eoi }, + { offset: 13, previous_year: 2022, type: :partnership }, + { offset: 14, previous_year: 2022, type: :eoi }, + { offset: 15, previous_year: 2021, type: :partnership }, + { offset: 16, previous_year: 2021, type: :eoi }, + ] + + scenarios.each { |scenario| seed_not_reusable_previous_scenario!(**scenario) } + end + + def seed_not_reusable_previous_scenario!(offset:, previous_year:, type:) + label = "Reuse scenario – #{previous_year} #{type_label(type)} (not reusable)" + last_chosen_lead_provider = + (type == :partnership) ? reusable_lead_provider : lead_provider_not_available_in_target_year + + school = ensure_scenario_school!( + offset:, + gias_name: label, + set_provider_led_last_chosen: true, + last_chosen_lead_provider: + ) + + seed_previous_teacher_and_training!( + school:, + previous_year:, + mode: type, + lead_provider: last_chosen_lead_provider, + delivery_partner_for_partnership: not_reusable_delivery_partner + ) + + case type + when :partnership + ActiveLeadProvider.find_or_create_by!( + lead_provider: reusable_lead_provider, + contract_period: target_contract_period + ) + when :eoi + ActiveLeadProvider.where( + lead_provider: lead_provider_not_available_in_target_year, + contract_period: target_contract_period + ).delete_all + else + raise ArgumentError, "Unknown type: #{type.inspect}" + end + end + + def type_label(type) + case type + when :partnership then "partnership" + when :eoi then "expression of interest" + else type.to_s + end + end + + # ONE ECT + ONE TrainingPeriod per school (+ InductionPeriod) + def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_provider:, delivery_partner_for_partnership:) + previous_contract_period = ContractPeriod.find_by!(year: previous_year) + previous_schedule = Schedule.find_by!(contract_period: previous_contract_period, identifier: SCHEDULE_IDENTIFIER) + + teacher = FactoryBot.create(:teacher) + + ect_period = + FactoryBot.create( + :ect_at_school_period, + :finished, + school:, + teacher:, + started_on: Date.new(previous_year, 9, 1), + finished_on: Date.new(previous_year + 1, 7, 31), + school_reported_appropriate_body: matrix_appropriate_body + ) + + InductionPeriod.find_or_create_by!( + teacher: ect_period.teacher, + started_on: ect_period.started_on + ) do |ip| + ip.finished_on = ect_period.finished_on + ip.appropriate_body = matrix_appropriate_body + ip.induction_programme = "fip" + ip.training_programme = "provider_led" + ip.number_of_terms = 3 + end + + active_lead_provider = + ActiveLeadProvider.find_or_create_by!( + lead_provider:, + contract_period: previous_contract_period + ) + + school.update!( + last_chosen_training_programme: "provider_led", + last_chosen_lead_provider: active_lead_provider.lead_provider, + last_chosen_appropriate_body: matrix_appropriate_body + ) + + case mode + when :partnership + school_partnership = + ensure_school_partnership!( + school:, + lead_provider:, + delivery_partner: delivery_partner_for_partnership, + year: previous_year + ) + + TrainingPeriod.find_or_create_by!( + ect_at_school_period: ect_period, + mentor_at_school_period: nil, + started_on: ect_period.started_on + ) do |tp| + tp.training_programme = "provider_led" + tp.schedule = previous_schedule + tp.school_partnership = school_partnership + tp.expression_of_interest = nil + tp.finished_on = ect_period.finished_on + end + + when :eoi + TrainingPeriod.find_or_create_by!( + ect_at_school_period: ect_period, + mentor_at_school_period: nil, + started_on: ect_period.started_on + ) do |tp| + tp.training_programme = "provider_led" + tp.schedule = previous_schedule + tp.school_partnership = nil + tp.expression_of_interest = active_lead_provider + tp.finished_on = ect_period.finished_on + end + + else + raise ArgumentError, "Unknown mode: #{mode.inspect}" + end + end + + def ensure_scenario_school!(offset:, gias_name:, set_provider_led_last_chosen:, last_chosen_lead_provider:) + urn = BASE_URN + offset + + ensure_gias_school!(urn:, name: gias_name) + + school = School.find_or_initialize_by(urn:) + + school.induction_tutor_name ||= "Reuse Tutor" + school.induction_tutor_email ||= "reuse@example.com" + + if set_provider_led_last_chosen + school.last_chosen_training_programme = "provider_led" if school.has_attribute?(:last_chosen_training_programme) + school.last_chosen_lead_provider = last_chosen_lead_provider if school.respond_to?(:last_chosen_lead_provider=) + school.last_chosen_appropriate_body = matrix_appropriate_body if school.has_attribute?(:last_chosen_appropriate_body_id) + else + school.last_chosen_training_programme = nil if school.has_attribute?(:last_chosen_training_programme) + school.last_chosen_lead_provider_id = nil if school.has_attribute?(:last_chosen_lead_provider_id) + school.last_chosen_appropriate_body = nil if school.has_attribute?(:last_chosen_appropriate_body_id) + end + + school.save! + school + end + + def ensure_gias_school!(urn:, name:) + desired = { + name:, + status: "open", + type_name: "Community school", + local_authority_code: 999, + in_england: true, + eligible: true, + opened_on: Date.new(2000, 1, 1), + section_41_approved: false + } + + record = GIAS::School.find_or_initialize_by(urn:) + permitted = desired.select { |k, _| record.has_attribute?(k) } + record.assign_attributes(permitted) + record.save! + record + end + + def ensure_school_partnership!(school:, lead_provider:, delivery_partner:, year:) + contract_period = ContractPeriod.find_by!(year:) + + active_lead_provider = + ActiveLeadProvider.find_or_create_by!( + lead_provider:, + contract_period: + ) + + lead_provider_delivery_partnership = + LeadProviderDeliveryPartnership.find_or_create_by!( + active_lead_provider:, + delivery_partner: + ) + + SchoolPartnership.find_or_create_by!( + school:, + lead_provider_delivery_partnership: + ) + end + end +end diff --git a/spec/seeds/reuse_choices_seed_spec.rb b/spec/seeds/reuse_choices_seed_spec.rb new file mode 100644 index 0000000000..954a8027c8 --- /dev/null +++ b/spec/seeds/reuse_choices_seed_spec.rb @@ -0,0 +1,187 @@ +RSpec.describe "Reuse choices scenarios seed" do + include Seeds::ReuseChoicesSeedHelpers + + let(:target_contract_period_year) { 2025 } + + before do + run_reuse_choices_seed!(contract_period_year: target_contract_period_year) + end + + describe "reference data" do + it "creates the reference lead providers, delivery partners and appropriate body" do + expect { reuse_reference_lead_provider }.not_to raise_error + expect { reuse_reference_lead_provider_not_available }.not_to raise_error + expect { reuse_reference_delivery_partner }.not_to raise_error + expect { reuse_reference_delivery_partner_not_reusable }.not_to raise_error + expect { reuse_reference_appropriate_body }.not_to raise_error + end + + it "ensures the reusable lead provider is available in the target year" do + expect( + target_year_active_lead_provider_exists?( + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider + ) + ).to be(true) + end + end + + describe "scenario schools exist" do + it "creates 17 scenario schools (URNs BASE..BASE+16) with matching GIAS records" do + schools = School.where(urn: reuse_choices_urns).includes(:gias_school).order(:urn) + + expect(schools.size).to eq(17) + expect(schools.all? { |s| s.gias_school.present? }).to be(true) + end + end + + describe "blank slate scenario" do + it "creates the blank slate school with no last chosen programme choices" do + school = reuse_school(offset: 0) + + expect(school.last_chosen_training_programme).to be_nil + expect(school.last_chosen_lead_provider).to be_nil + expect(school.last_chosen_appropriate_body).to be_nil + end + + it "has at least one partnership option in the target year so the school can proceed" do + school = reuse_school(offset: 0) + + expect( + target_year_partnership_exists?( + school:, + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider, + delivery_partner: reuse_reference_delivery_partner + ) + ).to be(true) + end + end + + describe "reusable previous programme scenarios" do + scenarios = [ + { offset: 1, previous_year: 2024, type: :partnership }, + { offset: 2, previous_year: 2024, type: :eoi }, + { offset: 3, previous_year: 2023, type: :partnership }, + { offset: 4, previous_year: 2023, type: :eoi }, + { offset: 5, previous_year: 2022, type: :partnership }, + { offset: 6, previous_year: 2022, type: :eoi }, + { offset: 7, previous_year: 2021, type: :partnership }, + { offset: 8, previous_year: 2021, type: :eoi }, + ] + + scenarios.each do |scenario| + it "sets up #{scenario[:previous_year]} #{scenario[:type]} reusable (offset #{scenario[:offset]})" do + school = reuse_school(offset: scenario.fetch(:offset)) + previous_year = scenario.fetch(:previous_year) + type = scenario.fetch(:type) + + expect(school.last_chosen_training_programme).to eq("provider_led") + expect(school.last_chosen_lead_provider).to eq(reuse_reference_lead_provider) + expect(school.last_chosen_appropriate_body).to eq(reuse_reference_appropriate_body) + + ect_period = scenario_ect_period_for_school!(school:, previous_year:) + expect(ect_period.school_reported_appropriate_body).to eq(reuse_reference_appropriate_body) + + induction_period = ect_period.teacher.induction_periods.find_by!(started_on: ect_period.started_on) + expect(induction_period.appropriate_body).to eq(reuse_reference_appropriate_body) + expect(induction_period.number_of_terms).to be_present + + training_period = scenario_provider_led_training_period_for_school!(school:, previous_year:) + expect(training_period.schedule.identifier).to eq(reuse_choices_schedule_identifier) + + case type + when :partnership + expect(training_period.school_partnership).to be_present + expect(training_period.expression_of_interest).to be_nil + + expect( + target_year_partnership_exists?( + school:, + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider, + delivery_partner: reuse_reference_delivery_partner + ) + ).to be(true) + + when :eoi + expect(training_period.school_partnership).to be_nil + expect(training_period.expression_of_interest).to be_present + + expect( + target_year_active_lead_provider_exists?( + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider + ) + ).to be(true) + else + raise "Unexpected type: #{type.inspect}" + end + end + end + end + + describe "not reusable previous programme scenarios" do + scenarios = [ + { offset: 9, previous_year: 2024, type: :partnership }, + { offset: 10, previous_year: 2024, type: :eoi }, + { offset: 11, previous_year: 2023, type: :partnership }, + { offset: 12, previous_year: 2023, type: :eoi }, + { offset: 13, previous_year: 2022, type: :partnership }, + { offset: 14, previous_year: 2022, type: :eoi }, + { offset: 15, previous_year: 2021, type: :partnership }, + { offset: 16, previous_year: 2021, type: :eoi }, + ] + + scenarios.each do |scenario| + it "sets up #{scenario[:previous_year]} #{scenario[:type]} NOT reusable (offset #{scenario[:offset]})" do + school = reuse_school(offset: scenario.fetch(:offset)) + previous_year = scenario.fetch(:previous_year) + type = scenario.fetch(:type) + + expect(school.last_chosen_training_programme).to eq("provider_led") + expect(school.last_chosen_appropriate_body).to eq(reuse_reference_appropriate_body) + + ect_period = scenario_ect_period_for_school!(school:, previous_year:) + induction_period = ect_period.teacher.induction_periods.find_by!(started_on: ect_period.started_on) + expect(induction_period.appropriate_body).to eq(reuse_reference_appropriate_body) + + training_period = scenario_provider_led_training_period_for_school!(school:, previous_year:) + expect(training_period.schedule.identifier).to eq(reuse_choices_schedule_identifier) + + case type + when :partnership + expect(training_period.school_partnership).to be_present + + expect( + target_year_active_lead_provider_exists?( + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider + ) + ).to be(true) + + expect( + target_year_partnership_exists?( + school:, + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider, + delivery_partner: reuse_reference_delivery_partner_not_reusable + ) + ).to be(false) + + when :eoi + expect(training_period.expression_of_interest).to be_present + + expect( + target_year_active_lead_provider_exists?( + contract_period_year: target_contract_period_year, + lead_provider: reuse_reference_lead_provider_not_available + ) + ).to be(false) + else + raise "Unexpected type: #{type.inspect}" + end + end + end + end +end diff --git a/spec/support/seeds/reuse_choices_seed_helpers.rb b/spec/support/seeds/reuse_choices_seed_helpers.rb new file mode 100644 index 0000000000..d970355917 --- /dev/null +++ b/spec/support/seeds/reuse_choices_seed_helpers.rb @@ -0,0 +1,79 @@ +module Seeds + module ReuseChoicesSeedHelpers + def run_reuse_choices_seed!(contract_period_year:) + Seeds::ReuseChoices.new(contract_period_year:).call + end + + def reuse_choices_base_urn + Seeds::ReuseChoices::BASE_URN + end + + def reuse_choices_schedule_identifier + Seeds::ReuseChoices::SCHEDULE_IDENTIFIER + end + + def reuse_choices_urns + base = reuse_choices_base_urn + (base..(base + 16)).to_a + end + + def reuse_school(offset:) + School.find_by!(urn: reuse_choices_base_urn + offset) + end + + def reuse_reference_lead_provider + LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_REUSABLE_NAME) + end + + def reuse_reference_lead_provider_not_available + LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + end + + def reuse_reference_delivery_partner + DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_REUSABLE_NAME) + end + + def reuse_reference_delivery_partner_not_reusable + DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_NOT_REUSABLE_NAME) + end + + def reuse_reference_appropriate_body + AppropriateBody.find_by!(name: Seeds::ReuseChoices::APPROPRIATE_BODY_NAME) + end + + def scenario_ect_period_for_school!(school:, previous_year:) + school.ect_at_school_periods.find_by!( + started_on: Date.new(previous_year, 9, 1), + finished_on: Date.new(previous_year + 1, 7, 31) + ) + end + + def scenario_provider_led_training_period_for_school!(school:, previous_year:) + ect_at_school_period = scenario_ect_period_for_school!(school:, previous_year:) + + TrainingPeriod.find_by!( + ect_at_school_period:, + training_programme: "provider_led", + started_on: ect_at_school_period.started_on + ) + end + + def target_year_partnership_exists?(school:, contract_period_year:, lead_provider:, delivery_partner:) + SchoolPartnership + .joins(lead_provider_delivery_partnership: [{ active_lead_provider: :contract_period }, :delivery_partner]) + .where(school:) + .where(contract_periods: { year: contract_period_year }) + .where(active_lead_providers: { lead_provider_id: lead_provider.id }) + .where(delivery_partners: { id: delivery_partner.id }) + .exists? + end + + def target_year_active_lead_provider_exists?(contract_period_year:, lead_provider:) + ActiveLeadProvider + .joins(:contract_period) + .where(lead_provider:) + .where(contract_periods: { year: contract_period_year }) + .exists? + end + end +end From 8ea0a42c53e9c0c394bbc8aadce5af9f083bc34b Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 09:41:30 +0000 Subject: [PATCH 02/11] Tidy reuse_choices.rb --- db/seeds/support/seeds/reuse_choices.rb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index d5091093e3..7a2c159409 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -38,18 +38,25 @@ def call attr_reader :contract_period_year def ensure_contract_periods! + existing = ContractPeriod.where(year: years).index_by(&:year) + years.each do |year| - ContractPeriod.find_or_create_by!(year:) do |cp| - cp.started_on = Date.new(year, 6, 1) - cp.finished_on = Date.new(year + 1, 5, 31) - cp.enabled = true - end + next if existing.key?(year) + + ContractPeriod.create!( + year:, + started_on: Date.new(year, 6, 1), + finished_on: Date.new(year + 1, 5, 31), + enabled: true + ) end end def ensure_schedules! + contract_periods_by_year = ContractPeriod.where(year: years).index_by(&:year) + years.each do |year| - contract_period = ContractPeriod.find_by!(year:) + contract_period = contract_periods_by_year.fetch(year) Schedule.find_or_create_by!( contract_period:, From a2c67e3a622d0efe244863d12f903af853b655c6 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 09:53:36 +0000 Subject: [PATCH 03/11] Update AB block --- db/seeds/support/seeds/reuse_choices.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index 7a2c159409..25e7adfeaa 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -72,10 +72,7 @@ def ensure_reference_data! DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_REUSABLE_NAME) DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) - AppropriateBody.find_or_create_by!( - name: APPROPRIATE_BODY_NAME, - body_type: "teaching_school_hub" - ) + AppropriateBody.find_or_create_by!(name: APPROPRIATE_BODY_NAME) end def ensure_target_year_availability_for_reusable_lead_provider! From 3fc17e3d4048c349d214f6241a425f13e0bc6b04 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 10:49:35 +0000 Subject: [PATCH 04/11] Update AB in seeds --- db/seeds/support/seeds/reuse_choices.rb | 21 ++++---- .../seeds/reuse_choices_seed_helpers.rb | 51 +++++++++++++------ 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index 25e7adfeaa..fe153e432b 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -15,8 +15,8 @@ class ReuseChoices DELIVERY_PARTNER_NOT_REUSABLE_NAME = "Reuse – Delivery Partner Two" - APPROPRIATE_BODY_NAME = - "Reuse – Appropriate Body" + PREFERRED_APPROPRIATE_BODY_NAME = + "Golden Leaf Teaching School Hub" def initialize(contract_period_year:) @contract_period_year = contract_period_year @@ -71,8 +71,6 @@ def ensure_reference_data! DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_REUSABLE_NAME) DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) - - AppropriateBody.find_or_create_by!(name: APPROPRIATE_BODY_NAME) end def ensure_target_year_availability_for_reusable_lead_provider! @@ -108,7 +106,10 @@ def not_reusable_delivery_partner end def matrix_appropriate_body - @matrix_appropriate_body ||= AppropriateBody.find_by!(name: APPROPRIATE_BODY_NAME) + @matrix_appropriate_body ||= + AppropriateBody.find_by(name: PREFERRED_APPROPRIATE_BODY_NAME) || + AppropriateBody.first || + raise("No AppropriateBody exists. Run appropriate_bodies seeds first.") end # Scenario group 1 – blank slate school @@ -247,6 +248,7 @@ def type_label(type) def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_provider:, delivery_partner_for_partnership:) previous_contract_period = ContractPeriod.find_by!(year: previous_year) previous_schedule = Schedule.find_by!(contract_period: previous_contract_period, identifier: SCHEDULE_IDENTIFIER) + ab = matrix_appropriate_body teacher = FactoryBot.create(:teacher) @@ -258,7 +260,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro teacher:, started_on: Date.new(previous_year, 9, 1), finished_on: Date.new(previous_year + 1, 7, 31), - school_reported_appropriate_body: matrix_appropriate_body + school_reported_appropriate_body: ab ) InductionPeriod.find_or_create_by!( @@ -266,7 +268,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro started_on: ect_period.started_on ) do |ip| ip.finished_on = ect_period.finished_on - ip.appropriate_body = matrix_appropriate_body + ip.appropriate_body = ab ip.induction_programme = "fip" ip.training_programme = "provider_led" ip.number_of_terms = 3 @@ -281,7 +283,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro school.update!( last_chosen_training_programme: "provider_led", last_chosen_lead_provider: active_lead_provider.lead_provider, - last_chosen_appropriate_body: matrix_appropriate_body + last_chosen_appropriate_body: ab ) case mode @@ -326,6 +328,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro def ensure_scenario_school!(offset:, gias_name:, set_provider_led_last_chosen:, last_chosen_lead_provider:) urn = BASE_URN + offset + ab = matrix_appropriate_body ensure_gias_school!(urn:, name: gias_name) @@ -337,7 +340,7 @@ def ensure_scenario_school!(offset:, gias_name:, set_provider_led_last_chosen:, if set_provider_led_last_chosen school.last_chosen_training_programme = "provider_led" if school.has_attribute?(:last_chosen_training_programme) school.last_chosen_lead_provider = last_chosen_lead_provider if school.respond_to?(:last_chosen_lead_provider=) - school.last_chosen_appropriate_body = matrix_appropriate_body if school.has_attribute?(:last_chosen_appropriate_body_id) + school.last_chosen_appropriate_body = ab if school.has_attribute?(:last_chosen_appropriate_body_id) else school.last_chosen_training_programme = nil if school.has_attribute?(:last_chosen_training_programme) school.last_chosen_lead_provider_id = nil if school.has_attribute?(:last_chosen_lead_provider_id) diff --git a/spec/support/seeds/reuse_choices_seed_helpers.rb b/spec/support/seeds/reuse_choices_seed_helpers.rb index d970355917..c9c3887980 100644 --- a/spec/support/seeds/reuse_choices_seed_helpers.rb +++ b/spec/support/seeds/reuse_choices_seed_helpers.rb @@ -1,44 +1,44 @@ module Seeds module ReuseChoicesSeedHelpers + BASE_URN = Seeds::ReuseChoices::BASE_URN + def run_reuse_choices_seed!(contract_period_year:) + ensure_test_appropriate_body! Seeds::ReuseChoices.new(contract_period_year:).call end - def reuse_choices_base_urn - Seeds::ReuseChoices::BASE_URN - end - - def reuse_choices_schedule_identifier - Seeds::ReuseChoices::SCHEDULE_IDENTIFIER - end - def reuse_choices_urns - base = reuse_choices_base_urn - (base..(base + 16)).to_a + (BASE_URN..(BASE_URN + 16)).to_a end def reuse_school(offset:) - School.find_by!(urn: reuse_choices_base_urn + offset) + School.find_by!(urn: BASE_URN + offset) end def reuse_reference_lead_provider - LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_REUSABLE_NAME) + find_by_name!(LeadProvider, Seeds::ReuseChoices::LEAD_PROVIDER_REUSABLE_NAME) end def reuse_reference_lead_provider_not_available - LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + find_by_name!(LeadProvider, Seeds::ReuseChoices::LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) end def reuse_reference_delivery_partner - DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_REUSABLE_NAME) + find_by_name!(DeliveryPartner, Seeds::ReuseChoices::DELIVERY_PARTNER_REUSABLE_NAME) end def reuse_reference_delivery_partner_not_reusable - DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_NOT_REUSABLE_NAME) + find_by_name!(DeliveryPartner, Seeds::ReuseChoices::DELIVERY_PARTNER_NOT_REUSABLE_NAME) end def reuse_reference_appropriate_body - AppropriateBody.find_by!(name: Seeds::ReuseChoices::APPROPRIATE_BODY_NAME) + AppropriateBody.find_by(name: Seeds::ReuseChoices::PREFERRED_APPROPRIATE_BODY_NAME) || + AppropriateBody.first || + raise("Expected an AppropriateBody to exist for seed scenarios") + end + + def reuse_choices_schedule_identifier + Seeds::ReuseChoices::SCHEDULE_IDENTIFIER end def scenario_ect_period_for_school!(school:, previous_year:) @@ -75,5 +75,24 @@ def target_year_active_lead_provider_exists?(contract_period_year:, lead_provide .where(contract_periods: { year: contract_period_year }) .exists? end + + private + + def find_by_name!(klass, name) + klass.find_by!(name:) + end + + def ensure_test_appropriate_body! + return if AppropriateBody.exists? + + org_assoc = AppropriateBody.reflect_on_association(:dfe_sign_in_organisation) + + if org_assoc + org = org_assoc.klass.create!(name: "Test DfE Sign-in Org") + AppropriateBody.create!(name: "Test Appropriate Body", dfe_sign_in_organisation: org) + else + AppropriateBody.create!(name: "Test Appropriate Body", dfe_sign_in_organisation_id: SecureRandom.uuid) + end + end end end From 2ae0dfac396cc87272e434ad06602b97e8829dd9 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 11:05:31 +0000 Subject: [PATCH 05/11] Update seeds helper --- spec/support/seeds/reuse_choices_seed_helpers.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/spec/support/seeds/reuse_choices_seed_helpers.rb b/spec/support/seeds/reuse_choices_seed_helpers.rb index c9c3887980..af8fab2ba7 100644 --- a/spec/support/seeds/reuse_choices_seed_helpers.rb +++ b/spec/support/seeds/reuse_choices_seed_helpers.rb @@ -85,14 +85,7 @@ def find_by_name!(klass, name) def ensure_test_appropriate_body! return if AppropriateBody.exists? - org_assoc = AppropriateBody.reflect_on_association(:dfe_sign_in_organisation) - - if org_assoc - org = org_assoc.klass.create!(name: "Test DfE Sign-in Org") - AppropriateBody.create!(name: "Test Appropriate Body", dfe_sign_in_organisation: org) - else - AppropriateBody.create!(name: "Test Appropriate Body", dfe_sign_in_organisation_id: SecureRandom.uuid) - end + FactoryBot.create(:appropriate_body) end end end From f07b1cb05ebacc8661ebc185c1b9feabc079a370 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 11:16:11 +0000 Subject: [PATCH 06/11] Target AB CI failures --- db/seeds/support/seeds/reuse_choices.rb | 38 +++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index fe153e432b..edaa8bbb37 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -112,6 +112,17 @@ def matrix_appropriate_body raise("No AppropriateBody exists. Run appropriate_bodies seeds first.") end + def matrix_appropriate_body_period + return unless School.reflect_on_association(:last_chosen_appropriate_body_period) + + @matrix_appropriate_body_period ||= AppropriateBodyPeriod.find_or_create_by!( + appropriate_body: matrix_appropriate_body, + started_on: Date.new(2020, 1, 1) + ) do |p| + p.finished_on = nil if p.respond_to?(:finished_on=) + end + end + # Scenario group 1 – blank slate school def seed_blank_control_school! school = ensure_scenario_school!( @@ -280,11 +291,18 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro contract_period: previous_contract_period ) - school.update!( + attrs = { last_chosen_training_programme: "provider_led", last_chosen_lead_provider: active_lead_provider.lead_provider, - last_chosen_appropriate_body: ab - ) + } + + if school.respond_to?(:last_chosen_appropriate_body_period=) && matrix_appropriate_body_period + attrs[:last_chosen_appropriate_body_period] = matrix_appropriate_body_period + elsif school.respond_to?(:last_chosen_appropriate_body=) + attrs[:last_chosen_appropriate_body] = ab + end + + school.update!(attrs) case mode when :partnership @@ -340,11 +358,21 @@ def ensure_scenario_school!(offset:, gias_name:, set_provider_led_last_chosen:, if set_provider_led_last_chosen school.last_chosen_training_programme = "provider_led" if school.has_attribute?(:last_chosen_training_programme) school.last_chosen_lead_provider = last_chosen_lead_provider if school.respond_to?(:last_chosen_lead_provider=) - school.last_chosen_appropriate_body = ab if school.has_attribute?(:last_chosen_appropriate_body_id) + + if school.respond_to?(:last_chosen_appropriate_body_period=) && matrix_appropriate_body_period + school.last_chosen_appropriate_body_period = matrix_appropriate_body_period + elsif school.respond_to?(:last_chosen_appropriate_body=) + school.last_chosen_appropriate_body = ab + end else school.last_chosen_training_programme = nil if school.has_attribute?(:last_chosen_training_programme) school.last_chosen_lead_provider_id = nil if school.has_attribute?(:last_chosen_lead_provider_id) - school.last_chosen_appropriate_body = nil if school.has_attribute?(:last_chosen_appropriate_body_id) + + if school.respond_to?(:last_chosen_appropriate_body_period=) + school.last_chosen_appropriate_body_period = nil + elsif school.respond_to?(:last_chosen_appropriate_body=) + school.last_chosen_appropriate_body = nil + end end school.save! From 0acb404c17d7be22711fba6b6a2e215534fd6ac9 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 11:50:36 +0000 Subject: [PATCH 07/11] Update AB method --- spec/support/seeds/reuse_choices_seed_helpers.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/support/seeds/reuse_choices_seed_helpers.rb b/spec/support/seeds/reuse_choices_seed_helpers.rb index af8fab2ba7..86754b3f98 100644 --- a/spec/support/seeds/reuse_choices_seed_helpers.rb +++ b/spec/support/seeds/reuse_choices_seed_helpers.rb @@ -85,7 +85,13 @@ def find_by_name!(klass, name) def ensure_test_appropriate_body! return if AppropriateBody.exists? - FactoryBot.create(:appropriate_body) + test_uuid = "83173E6F-BA28-4654-A3DF-8279D573AB09" + + AppropriateBody.create!( + name: Seeds::ReuseChoices::PREFERRED_APPROPRIATE_BODY_NAME, # "Golden Leaf Teaching School Hub" + body_type: "teaching_school_hub", + dfe_sign_in_organisation_id: test_uuid + ) end end end From 275e3ad8562fb3129cd843e4909198634b4f6e06 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Mon, 16 Feb 2026 12:03:36 +0000 Subject: [PATCH 08/11] Update seeds to include AppropriateBodyPeriods --- db/ecf_schema.rb | 4 +- db/schema.rb | 4 +- db/seeds/lead_providers.rb | 9 +- db/seeds/reuse_choices_scenarios.rb | 14 +- db/seeds/support/seeds/reuse_choices.rb | 149 +++++++++--------- spec/seeds/reuse_choices_seed_spec.rb | 11 +- .../seeds/reuse_choices_seed_helpers.rb | 50 ++---- 7 files changed, 108 insertions(+), 133 deletions(-) diff --git a/db/ecf_schema.rb b/db/ecf_schema.rb index 79aa76e8d4..2642478c8a 100644 --- a/db/ecf_schema.rb +++ b/db/ecf_schema.rb @@ -10,12 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_02_28_135429) do +ActiveRecord::Schema[8.0].define(version: 2025_02_28_135429) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "fuzzystrmatch" + enable_extension "pg_catalog.plpgsql" enable_extension "pgcrypto" - enable_extension "plpgsql" enable_extension "uuid-ossp" create_table "additional_school_emails", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| diff --git a/db/schema.rb b/db/schema.rb index 8ca364172d..02764f5ae1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1065,9 +1065,9 @@ add_foreign_key "appropriate_bodies", "dfe_sign_in_organisations" add_foreign_key "appropriate_body_periods", "appropriate_bodies" add_foreign_key "contract_banded_fee_structure_bands", "contract_banded_fee_structures", column: "banded_fee_structure_id", on_delete: :cascade - add_foreign_key "contracts", "contract_banded_fee_structures", column: "banded_fee_structure_id" - add_foreign_key "contracts", "contract_flat_rate_fee_structures", column: "flat_rate_fee_structure_id" add_foreign_key "contracts", "active_lead_providers" + add_foreign_key "contracts", "contract_banded_fee_structures", column: "banded_fee_structure_id" + add_foreign_key "contracts", "contract_flat_rate_fee_structures", column: "flat_rate_fee_structure_id" add_foreign_key "declarations", "delivery_partners", column: "delivery_partner_when_created_id" add_foreign_key "declarations", "statements", column: "clawback_statement_id" add_foreign_key "declarations", "statements", column: "payment_statement_id" diff --git a/db/seeds/lead_providers.rb b/db/seeds/lead_providers.rb index 9df230dc99..5a93765138 100644 --- a/db/seeds/lead_providers.rb +++ b/db/seeds/lead_providers.rb @@ -19,15 +19,12 @@ def describe_lead_provider(lead_provider, years) ] lead_providers_data.each do |data| - lead_provider = LeadProvider.find_or_initialize_by(name: data.fetch(:name)) - lead_provider.vat_registered = data.fetch(:vat_registered) - lead_provider.ecf_id ||= SecureRandom.uuid if lead_provider.has_attribute?(:ecf_id) - lead_provider.save! + lead_provider = LeadProvider.find_or_create_by!(data.slice(:name, :vat_registered)) - data.fetch(:years).each do |year| + data[:years].each do |year| contract_period = ContractPeriod.find_by!(year:) ActiveLeadProvider.find_or_create_by!(lead_provider:, contract_period:) end - describe_lead_provider(lead_provider, data.fetch(:years)) + describe_lead_provider(lead_provider, data[:years]) end diff --git a/db/seeds/reuse_choices_scenarios.rb b/db/seeds/reuse_choices_scenarios.rb index 91895997eb..4255bb3037 100644 --- a/db/seeds/reuse_choices_scenarios.rb +++ b/db/seeds/reuse_choices_scenarios.rb @@ -1,7 +1,11 @@ -require Rails.root.join("db/seeds/support/seeds/reuse_choices") +if Rails.env.staging? || Rails.env.development? || Rails.env.review? + require Rails.root.join("db/seeds/support/seeds/reuse_choices") -return unless Rails.env.staging? || Rails.env.development? || Rails.env.review? + print_seed_info( + "Seeding reuse choices scenario schools (staging only)", + colour: :yellow, + blank_lines_before: 1 + ) -Rails.logger.debug "Seeding reuse choices scenario schools (staging only)" - -Seeds::ReuseChoices.new(contract_period_year: 2025).call + Seeds::ReuseChoices.new(contract_period_year: 2025).call +end diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index edaa8bbb37..2a5d216869 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -1,3 +1,4 @@ +# db/seeds/support/seeds/reuse_choices.rb module Seeds class ReuseChoices BASE_URN = 9_100_100 @@ -26,6 +27,7 @@ def call ensure_contract_periods! ensure_schedules! ensure_reference_data! + ensure_matrix_appropriate_body_period! ensure_target_year_availability_for_reusable_lead_provider! seed_blank_control_school! @@ -37,6 +39,14 @@ def call attr_reader :contract_period_year + def years + (2021..contract_period_year).to_a + end + + def target_contract_period + @target_contract_period ||= ContractPeriod.find_by!(year: contract_period_year) + end + def ensure_contract_periods! existing = ContractPeriod.where(year: years).index_by(&:year) @@ -53,13 +63,15 @@ def ensure_contract_periods! end def ensure_schedules! - contract_periods_by_year = ContractPeriod.where(year: years).index_by(&:year) + existing_by_year = Schedule + .where(contract_period_year: years, identifier: SCHEDULE_IDENTIFIER) + .index_by(&:contract_period_year) years.each do |year| - contract_period = contract_periods_by_year.fetch(year) + next if existing_by_year.key?(year) - Schedule.find_or_create_by!( - contract_period:, + Schedule.create!( + contract_period_year: year, identifier: SCHEDULE_IDENTIFIER ) end @@ -80,21 +92,12 @@ def ensure_target_year_availability_for_reusable_lead_provider! ) end - def years - (2021..contract_period_year).to_a - end - - def target_contract_period - @target_contract_period ||= ContractPeriod.find_by!(year: contract_period_year) - end - def reusable_lead_provider @reusable_lead_provider ||= LeadProvider.find_by!(name: LEAD_PROVIDER_REUSABLE_NAME) end def lead_provider_not_available_in_target_year - @lead_provider_not_available_in_target_year ||= - LeadProvider.find_by!(name: LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + @lead_provider_not_available_in_target_year ||= LeadProvider.find_by!(name: LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) end def reusable_delivery_partner @@ -105,25 +108,38 @@ def not_reusable_delivery_partner @not_reusable_delivery_partner ||= DeliveryPartner.find_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) end - def matrix_appropriate_body - @matrix_appropriate_body ||= - AppropriateBody.find_by(name: PREFERRED_APPROPRIATE_BODY_NAME) || - AppropriateBody.first || - raise("No AppropriateBody exists. Run appropriate_bodies seeds first.") + def ensure_matrix_appropriate_body_period! + matrix_appropriate_body_period end def matrix_appropriate_body_period - return unless School.reflect_on_association(:last_chosen_appropriate_body_period) + @matrix_appropriate_body_period ||= begin + abp = AppropriateBodyPeriod.find_or_create_by!(name: PREFERRED_APPROPRIATE_BODY_NAME) + + abp.body_type = "teaching_school_hub" if abp.has_attribute?(:body_type) && abp.body_type != "teaching_school_hub" - @matrix_appropriate_body_period ||= AppropriateBodyPeriod.find_or_create_by!( - appropriate_body: matrix_appropriate_body, - started_on: Date.new(2020, 1, 1) - ) do |p| - p.finished_on = nil if p.respond_to?(:finished_on=) + if abp.has_attribute?(:dfe_sign_in_organisation_id) && abp.dfe_sign_in_organisation_id.present? + abp.dfe_sign_in_organisation_id = nil + end + + if abp.has_attribute?(:appropriate_body_id) && abp.appropriate_body_id.present? + abp.appropriate_body_id = nil + end + + abp.save! if abp.changed? + abp end end + def set_last_chosen_appropriate_body!(school, chosen:) + return unless school.has_attribute?(:last_chosen_appropriate_body_id) + + school.last_chosen_appropriate_body_id = chosen ? matrix_appropriate_body_period.id : nil + end + + # # Scenario group 1 – blank slate school + # def seed_blank_control_school! school = ensure_scenario_school!( offset: 0, @@ -140,7 +156,9 @@ def seed_blank_control_school! ) end + # # Scenario group 2 – previous programme reusable in target year + # def seed_reusable_previous_scenarios! scenarios = [ { offset: 1, previous_year: 2024, type: :partnership }, @@ -150,7 +168,7 @@ def seed_reusable_previous_scenarios! { offset: 5, previous_year: 2022, type: :partnership }, { offset: 6, previous_year: 2022, type: :eoi }, { offset: 7, previous_year: 2021, type: :partnership }, - { offset: 8, previous_year: 2021, type: :eoi }, + { offset: 8, previous_year: 2021, type: :eoi } ] scenarios.each { |scenario| seed_reusable_previous_scenario!(**scenario) } @@ -173,29 +191,28 @@ def seed_reusable_previous_scenario!(offset:, previous_year:, type:) delivery_partner_for_partnership: reusable_delivery_partner ) - case type - when :partnership + if type == :partnership ensure_school_partnership!( school:, lead_provider: reusable_lead_provider, delivery_partner: reusable_delivery_partner, year: contract_period_year ) - when :eoi + else ActiveLeadProvider.find_or_create_by!( lead_provider: reusable_lead_provider, contract_period: target_contract_period ) - else - raise ArgumentError, "Unknown type: #{type.inspect}" end end + # # Scenario group 3 – previous programme NOT reusable in target year # # Rules: # - partnership NOT reusable: LP exists in target year BUT pairing does NOT # - EOI NOT reusable: LP does NOT exist in target year (no ALP in target year) + # def seed_not_reusable_previous_scenarios! scenarios = [ { offset: 9, previous_year: 2024, type: :partnership }, @@ -205,7 +222,7 @@ def seed_not_reusable_previous_scenarios! { offset: 13, previous_year: 2022, type: :partnership }, { offset: 14, previous_year: 2022, type: :eoi }, { offset: 15, previous_year: 2021, type: :partnership }, - { offset: 16, previous_year: 2021, type: :eoi }, + { offset: 16, previous_year: 2021, type: :eoi } ] scenarios.each { |scenario| seed_not_reusable_previous_scenario!(**scenario) } @@ -214,7 +231,7 @@ def seed_not_reusable_previous_scenarios! def seed_not_reusable_previous_scenario!(offset:, previous_year:, type:) label = "Reuse scenario – #{previous_year} #{type_label(type)} (not reusable)" last_chosen_lead_provider = - (type == :partnership) ? reusable_lead_provider : lead_provider_not_available_in_target_year + type == :partnership ? reusable_lead_provider : lead_provider_not_available_in_target_year school = ensure_scenario_school!( offset:, @@ -231,19 +248,16 @@ def seed_not_reusable_previous_scenario!(offset:, previous_year:, type:) delivery_partner_for_partnership: not_reusable_delivery_partner ) - case type - when :partnership + if type == :partnership ActiveLeadProvider.find_or_create_by!( lead_provider: reusable_lead_provider, contract_period: target_contract_period ) - when :eoi - ActiveLeadProvider.where( + else + ActiveLeadProvider.find_by( lead_provider: lead_provider_not_available_in_target_year, contract_period: target_contract_period - ).delete_all - else - raise ArgumentError, "Unknown type: #{type.inspect}" + )&.destroy! end end @@ -255,11 +269,13 @@ def type_label(type) end end + # # ONE ECT + ONE TrainingPeriod per school (+ InductionPeriod) + # def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_provider:, delivery_partner_for_partnership:) previous_contract_period = ContractPeriod.find_by!(year: previous_year) previous_schedule = Schedule.find_by!(contract_period: previous_contract_period, identifier: SCHEDULE_IDENTIFIER) - ab = matrix_appropriate_body + abp = matrix_appropriate_body_period teacher = FactoryBot.create(:teacher) @@ -271,7 +287,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro teacher:, started_on: Date.new(previous_year, 9, 1), finished_on: Date.new(previous_year + 1, 7, 31), - school_reported_appropriate_body: ab + school_reported_appropriate_body: abp ) InductionPeriod.find_or_create_by!( @@ -279,7 +295,7 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro started_on: ect_period.started_on ) do |ip| ip.finished_on = ect_period.finished_on - ip.appropriate_body = ab + ip.appropriate_body_period = abp ip.induction_programme = "fip" ip.training_programme = "provider_led" ip.number_of_terms = 3 @@ -291,21 +307,14 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro contract_period: previous_contract_period ) - attrs = { - last_chosen_training_programme: "provider_led", - last_chosen_lead_provider: active_lead_provider.lead_provider, - } - - if school.respond_to?(:last_chosen_appropriate_body_period=) && matrix_appropriate_body_period - attrs[:last_chosen_appropriate_body_period] = matrix_appropriate_body_period - elsif school.respond_to?(:last_chosen_appropriate_body=) - attrs[:last_chosen_appropriate_body] = ab + if school.has_attribute?(:last_chosen_training_programme) + school.last_chosen_training_programme = "provider_led" end + school.last_chosen_lead_provider = active_lead_provider.lead_provider + set_last_chosen_appropriate_body!(school, chosen: true) + school.save! - school.update!(attrs) - - case mode - when :partnership + if mode == :partnership school_partnership = ensure_school_partnership!( school:, @@ -324,9 +333,9 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro tp.school_partnership = school_partnership tp.expression_of_interest = nil tp.finished_on = ect_period.finished_on + tp.finished_on = tp.started_on + 1.day if tp.finished_on.present? && tp.finished_on <= tp.started_on end - - when :eoi + else TrainingPeriod.find_or_create_by!( ect_at_school_period: ect_period, mentor_at_school_period: nil, @@ -337,42 +346,28 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro tp.school_partnership = nil tp.expression_of_interest = active_lead_provider tp.finished_on = ect_period.finished_on + tp.finished_on = tp.started_on + 1.day if tp.finished_on.present? && tp.finished_on <= tp.started_on end - - else - raise ArgumentError, "Unknown mode: #{mode.inspect}" end end def ensure_scenario_school!(offset:, gias_name:, set_provider_led_last_chosen:, last_chosen_lead_provider:) urn = BASE_URN + offset - ab = matrix_appropriate_body - ensure_gias_school!(urn:, name: gias_name) school = School.find_or_initialize_by(urn:) - school.induction_tutor_name ||= "Reuse Tutor" school.induction_tutor_email ||= "reuse@example.com" if set_provider_led_last_chosen school.last_chosen_training_programme = "provider_led" if school.has_attribute?(:last_chosen_training_programme) - school.last_chosen_lead_provider = last_chosen_lead_provider if school.respond_to?(:last_chosen_lead_provider=) - - if school.respond_to?(:last_chosen_appropriate_body_period=) && matrix_appropriate_body_period - school.last_chosen_appropriate_body_period = matrix_appropriate_body_period - elsif school.respond_to?(:last_chosen_appropriate_body=) - school.last_chosen_appropriate_body = ab - end + school.last_chosen_lead_provider = last_chosen_lead_provider + set_last_chosen_appropriate_body!(school, chosen: true) else school.last_chosen_training_programme = nil if school.has_attribute?(:last_chosen_training_programme) school.last_chosen_lead_provider_id = nil if school.has_attribute?(:last_chosen_lead_provider_id) - - if school.respond_to?(:last_chosen_appropriate_body_period=) - school.last_chosen_appropriate_body_period = nil - elsif school.respond_to?(:last_chosen_appropriate_body=) - school.last_chosen_appropriate_body = nil - end + school.last_chosen_lead_provider = nil + set_last_chosen_appropriate_body!(school, chosen: false) end school.save! diff --git a/spec/seeds/reuse_choices_seed_spec.rb b/spec/seeds/reuse_choices_seed_spec.rb index 954a8027c8..c4a7b4d766 100644 --- a/spec/seeds/reuse_choices_seed_spec.rb +++ b/spec/seeds/reuse_choices_seed_spec.rb @@ -41,7 +41,6 @@ expect(school.last_chosen_training_programme).to be_nil expect(school.last_chosen_lead_provider).to be_nil - expect(school.last_chosen_appropriate_body).to be_nil end it "has at least one partnership option in the target year so the school can proceed" do @@ -67,7 +66,7 @@ { offset: 5, previous_year: 2022, type: :partnership }, { offset: 6, previous_year: 2022, type: :eoi }, { offset: 7, previous_year: 2021, type: :partnership }, - { offset: 8, previous_year: 2021, type: :eoi }, + { offset: 8, previous_year: 2021, type: :eoi } ] scenarios.each do |scenario| @@ -78,13 +77,12 @@ expect(school.last_chosen_training_programme).to eq("provider_led") expect(school.last_chosen_lead_provider).to eq(reuse_reference_lead_provider) - expect(school.last_chosen_appropriate_body).to eq(reuse_reference_appropriate_body) ect_period = scenario_ect_period_for_school!(school:, previous_year:) expect(ect_period.school_reported_appropriate_body).to eq(reuse_reference_appropriate_body) induction_period = ect_period.teacher.induction_periods.find_by!(started_on: ect_period.started_on) - expect(induction_period.appropriate_body).to eq(reuse_reference_appropriate_body) + expect(induction_period.appropriate_body_period).to eq(reuse_reference_appropriate_body) expect(induction_period.number_of_terms).to be_present training_period = scenario_provider_led_training_period_for_school!(school:, previous_year:) @@ -130,7 +128,7 @@ { offset: 13, previous_year: 2022, type: :partnership }, { offset: 14, previous_year: 2022, type: :eoi }, { offset: 15, previous_year: 2021, type: :partnership }, - { offset: 16, previous_year: 2021, type: :eoi }, + { offset: 16, previous_year: 2021, type: :eoi } ] scenarios.each do |scenario| @@ -140,11 +138,10 @@ type = scenario.fetch(:type) expect(school.last_chosen_training_programme).to eq("provider_led") - expect(school.last_chosen_appropriate_body).to eq(reuse_reference_appropriate_body) ect_period = scenario_ect_period_for_school!(school:, previous_year:) induction_period = ect_period.teacher.induction_periods.find_by!(started_on: ect_period.started_on) - expect(induction_period.appropriate_body).to eq(reuse_reference_appropriate_body) + expect(induction_period.appropriate_body_period).to eq(reuse_reference_appropriate_body) training_period = scenario_provider_led_training_period_for_school!(school:, previous_year:) expect(training_period.schedule.identifier).to eq(reuse_choices_schedule_identifier) diff --git a/spec/support/seeds/reuse_choices_seed_helpers.rb b/spec/support/seeds/reuse_choices_seed_helpers.rb index 86754b3f98..3680691179 100644 --- a/spec/support/seeds/reuse_choices_seed_helpers.rb +++ b/spec/support/seeds/reuse_choices_seed_helpers.rb @@ -1,44 +1,44 @@ module Seeds module ReuseChoicesSeedHelpers - BASE_URN = Seeds::ReuseChoices::BASE_URN - def run_reuse_choices_seed!(contract_period_year:) - ensure_test_appropriate_body! Seeds::ReuseChoices.new(contract_period_year:).call end + def reuse_choices_base_urn + Seeds::ReuseChoices::BASE_URN + end + + def reuse_choices_schedule_identifier + Seeds::ReuseChoices::SCHEDULE_IDENTIFIER + end + def reuse_choices_urns - (BASE_URN..(BASE_URN + 16)).to_a + base = reuse_choices_base_urn + (base..(base + 16)).to_a end def reuse_school(offset:) - School.find_by!(urn: BASE_URN + offset) + School.find_by!(urn: reuse_choices_base_urn + offset) end def reuse_reference_lead_provider - find_by_name!(LeadProvider, Seeds::ReuseChoices::LEAD_PROVIDER_REUSABLE_NAME) + LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_REUSABLE_NAME) end def reuse_reference_lead_provider_not_available - find_by_name!(LeadProvider, Seeds::ReuseChoices::LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) + LeadProvider.find_by!(name: Seeds::ReuseChoices::LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) end def reuse_reference_delivery_partner - find_by_name!(DeliveryPartner, Seeds::ReuseChoices::DELIVERY_PARTNER_REUSABLE_NAME) + DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_REUSABLE_NAME) end def reuse_reference_delivery_partner_not_reusable - find_by_name!(DeliveryPartner, Seeds::ReuseChoices::DELIVERY_PARTNER_NOT_REUSABLE_NAME) + DeliveryPartner.find_by!(name: Seeds::ReuseChoices::DELIVERY_PARTNER_NOT_REUSABLE_NAME) end def reuse_reference_appropriate_body - AppropriateBody.find_by(name: Seeds::ReuseChoices::PREFERRED_APPROPRIATE_BODY_NAME) || - AppropriateBody.first || - raise("Expected an AppropriateBody to exist for seed scenarios") - end - - def reuse_choices_schedule_identifier - Seeds::ReuseChoices::SCHEDULE_IDENTIFIER + AppropriateBodyPeriod.find_by!(name: Seeds::ReuseChoices::PREFERRED_APPROPRIATE_BODY_NAME) end def scenario_ect_period_for_school!(school:, previous_year:) @@ -75,23 +75,5 @@ def target_year_active_lead_provider_exists?(contract_period_year:, lead_provide .where(contract_periods: { year: contract_period_year }) .exists? end - - private - - def find_by_name!(klass, name) - klass.find_by!(name:) - end - - def ensure_test_appropriate_body! - return if AppropriateBody.exists? - - test_uuid = "83173E6F-BA28-4654-A3DF-8279D573AB09" - - AppropriateBody.create!( - name: Seeds::ReuseChoices::PREFERRED_APPROPRIATE_BODY_NAME, # "Golden Leaf Teaching School Hub" - body_type: "teaching_school_hub", - dfe_sign_in_organisation_id: test_uuid - ) - end end end From 49d38f5adb92d65a97ec2010080989e0a805cb21 Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Tue, 17 Feb 2026 11:45:46 +0000 Subject: [PATCH 09/11] Update out of sync db & specs --- db/ecf_schema.rb | 4 ++-- db/schema.rb | 2 +- db/seeds/support/seeds/reuse_choices.rb | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/db/ecf_schema.rb b/db/ecf_schema.rb index 2642478c8a..79aa76e8d4 100644 --- a/db/ecf_schema.rb +++ b/db/ecf_schema.rb @@ -10,12 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_02_28_135429) do +ActiveRecord::Schema[7.1].define(version: 2025_02_28_135429) do # These are extensions that must be enabled in order to support this database enable_extension "citext" enable_extension "fuzzystrmatch" - enable_extension "pg_catalog.plpgsql" enable_extension "pgcrypto" + enable_extension "plpgsql" enable_extension "uuid-ossp" create_table "additional_school_emails", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| diff --git a/db/schema.rb b/db/schema.rb index 02764f5ae1..ef209c09ad 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1065,9 +1065,9 @@ add_foreign_key "appropriate_bodies", "dfe_sign_in_organisations" add_foreign_key "appropriate_body_periods", "appropriate_bodies" add_foreign_key "contract_banded_fee_structure_bands", "contract_banded_fee_structures", column: "banded_fee_structure_id", on_delete: :cascade - add_foreign_key "contracts", "active_lead_providers" add_foreign_key "contracts", "contract_banded_fee_structures", column: "banded_fee_structure_id" add_foreign_key "contracts", "contract_flat_rate_fee_structures", column: "flat_rate_fee_structure_id" + add_foreign_key "contracts", "active_lead_providers" add_foreign_key "declarations", "delivery_partners", column: "delivery_partner_when_created_id" add_foreign_key "declarations", "statements", column: "clawback_statement_id" add_foreign_key "declarations", "statements", column: "payment_statement_id" diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index 2a5d216869..21131e2fb7 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -1,4 +1,3 @@ -# db/seeds/support/seeds/reuse_choices.rb module Seeds class ReuseChoices BASE_URN = 9_100_100 From b24705efdb4e4c428152eb1eb9559bf1ac53ffda Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Tue, 17 Feb 2026 16:12:22 +0000 Subject: [PATCH 10/11] Fix ReuseChoices seeds to consistently use Golden Leaf ABP and ensure idempotent AB assignment --- db/seeds/support/seeds/reuse_choices.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index 21131e2fb7..375011cdcf 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -273,7 +273,7 @@ def type_label(type) # def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_provider:, delivery_partner_for_partnership:) previous_contract_period = ContractPeriod.find_by!(year: previous_year) - previous_schedule = Schedule.find_by!(contract_period: previous_contract_period, identifier: SCHEDULE_IDENTIFIER) + previous_schedule = Schedule.find_by!(contract_period_year: previous_year, identifier: SCHEDULE_IDENTIFIER) abp = matrix_appropriate_body_period teacher = FactoryBot.create(:teacher) @@ -289,7 +289,9 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro school_reported_appropriate_body: abp ) - InductionPeriod.find_or_create_by!( + ect_period.update!(school_reported_appropriate_body: abp) if ect_period.school_reported_appropriate_body_id != abp.id + + induction_period = InductionPeriod.find_or_create_by!( teacher: ect_period.teacher, started_on: ect_period.started_on ) do |ip| @@ -300,6 +302,8 @@ def seed_previous_teacher_and_training!(school:, previous_year:, mode:, lead_pro ip.number_of_terms = 3 end + induction_period.update!(appropriate_body_period: abp) if induction_period.appropriate_body_period_id != abp.id + active_lead_provider = ActiveLeadProvider.find_or_create_by!( lead_provider:, From 8091958e353f4845c55d7fa646e8050b25fbc8bc Mon Sep 17 00:00:00 2001 From: Erica Porter Date: Wed, 18 Feb 2026 11:05:42 +0000 Subject: [PATCH 11/11] Tidy reuse_choices --- db/seeds/support/seeds/reuse_choices.rb | 47 ++++++++----------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/db/seeds/support/seeds/reuse_choices.rb b/db/seeds/support/seeds/reuse_choices.rb index 375011cdcf..9d80c2309d 100644 --- a/db/seeds/support/seeds/reuse_choices.rb +++ b/db/seeds/support/seeds/reuse_choices.rb @@ -3,20 +3,11 @@ class ReuseChoices BASE_URN = 9_100_100 SCHEDULE_IDENTIFIER = "ecf-standard-september" - LEAD_PROVIDER_REUSABLE_NAME = - "Reuse – Lead Provider One" - - LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME = - "Reuse – Lead Provider X (not available in target year)" - - DELIVERY_PARTNER_REUSABLE_NAME = - "Reuse – Delivery Partner One" - - DELIVERY_PARTNER_NOT_REUSABLE_NAME = - "Reuse – Delivery Partner Two" - - PREFERRED_APPROPRIATE_BODY_NAME = - "Golden Leaf Teaching School Hub" + LEAD_PROVIDER_REUSABLE_NAME = "Reuse – Lead Provider One" + LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME = "Reuse – Lead Provider X (not available in target year)" + DELIVERY_PARTNER_REUSABLE_NAME = "Reuse – Delivery Partner One" + DELIVERY_PARTNER_NOT_REUSABLE_NAME = "Reuse – Delivery Partner Two" + PREFERRED_APPROPRIATE_BODY_NAME = "Golden Leaf Teaching School Hub" def initialize(contract_period_year:) @contract_period_year = contract_period_year @@ -69,17 +60,13 @@ def ensure_schedules! years.each do |year| next if existing_by_year.key?(year) - Schedule.create!( - contract_period_year: year, - identifier: SCHEDULE_IDENTIFIER - ) + Schedule.create!(contract_period_year: year, identifier: SCHEDULE_IDENTIFIER) end end def ensure_reference_data! LeadProvider.find_or_create_by!(name: LEAD_PROVIDER_REUSABLE_NAME) LeadProvider.find_or_create_by!(name: LEAD_PROVIDER_NOT_AVAILABLE_IN_TARGET_YEAR_NAME) - DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_REUSABLE_NAME) DeliveryPartner.find_or_create_by!(name: DELIVERY_PARTNER_NOT_REUSABLE_NAME) end @@ -111,19 +98,20 @@ def ensure_matrix_appropriate_body_period! matrix_appropriate_body_period end + def clear_attr!(record, attr_name) + record[attr_name] = nil if record.has_attribute?(attr_name) + end + def matrix_appropriate_body_period @matrix_appropriate_body_period ||= begin abp = AppropriateBodyPeriod.find_or_create_by!(name: PREFERRED_APPROPRIATE_BODY_NAME) - abp.body_type = "teaching_school_hub" if abp.has_attribute?(:body_type) && abp.body_type != "teaching_school_hub" - - if abp.has_attribute?(:dfe_sign_in_organisation_id) && abp.dfe_sign_in_organisation_id.present? - abp.dfe_sign_in_organisation_id = nil + if abp.has_attribute?(:body_type) && abp.body_type != "teaching_school_hub" + abp.body_type = "teaching_school_hub" end - if abp.has_attribute?(:appropriate_body_id) && abp.appropriate_body_id.present? - abp.appropriate_body_id = nil - end + clear_attr!(abp, :dfe_sign_in_organisation_id) + clear_attr!(abp, :appropriate_body_id) abp.save! if abp.changed? abp @@ -208,10 +196,6 @@ def seed_reusable_previous_scenario!(offset:, previous_year:, type:) # # Scenario group 3 – previous programme NOT reusable in target year # - # Rules: - # - partnership NOT reusable: LP exists in target year BUT pairing does NOT - # - EOI NOT reusable: LP does NOT exist in target year (no ALP in target year) - # def seed_not_reusable_previous_scenarios! scenarios = [ { offset: 9, previous_year: 2024, type: :partnership }, @@ -229,8 +213,7 @@ def seed_not_reusable_previous_scenarios! def seed_not_reusable_previous_scenario!(offset:, previous_year:, type:) label = "Reuse scenario – #{previous_year} #{type_label(type)} (not reusable)" - last_chosen_lead_provider = - type == :partnership ? reusable_lead_provider : lead_provider_not_available_in_target_year + last_chosen_lead_provider = type == :partnership ? reusable_lead_provider : lead_provider_not_available_in_target_year school = ensure_scenario_school!( offset:,