diff --git a/app/services/publish_teacher_training/subject/import.rb b/app/services/publish_teacher_training/subject/import.rb index 6a35484f4..98191019d 100644 --- a/app/services/publish_teacher_training/subject/import.rb +++ b/app/services/publish_teacher_training/subject/import.rb @@ -3,8 +3,9 @@ module Subject class Import include ServicePattern - PRIMARY_IDS = %w[PrimarySubject].freeze - SECONDARY_IDS = %w[SecondarySubject ModernLanguagesSubject].freeze + PRIMARY_ID = "PrimarySubject".freeze + SECONDARY_ID = "SecondarySubject".freeze + MODERN_LANGUAGES_ID = "ModernLanguagesSubject".freeze def call fetch_subject @@ -15,9 +16,12 @@ def call def fetch_subject api_response = PublishTeacherTraining::Subject::Api.call data = api_response.fetch("data") - # Find Primary Subjects IDs - primary_subject_ids = fetch_subject_ids(subject_area_ids: PRIMARY_IDS, data:) - secondary_subject_ids = fetch_subject_ids(subject_area_ids: SECONDARY_IDS, data:) + # Find Primary Subject IDs + primary_subject_ids = fetch_subject_ids(subject_area_id: PRIMARY_ID, data:) + # Find Secondary Subject IDs + secondary_subject_ids = fetch_subject_ids(subject_area_id: SECONDARY_ID, data:) + # Find Modern Language Subject IDs + modern_language_subject_ids = fetch_subject_ids(subject_area_id: MODERN_LANGUAGES_ID, data:) subjects_data = api_response.fetch("included") # Sync Primary Subjects @@ -33,36 +37,52 @@ def fetch_subject subject_ids: secondary_subject_ids, subjects_data:, ) + + # Sync Modern Language Subjects + sync_subjects( + subject_area: :secondary, + subject_ids: modern_language_subject_ids, + subjects_data:, + parent_subject: ::Subject.find_by(name: "Modern Languages"), + ) end - def sync_subjects(subject_area:, subject_ids:, subjects_data:) + def sync_subjects(subject_area:, subject_ids:, subjects_data:, parent_subject: nil) + return if subject_ids.blank? + subject_area_subjects_data = subjects_data.select do |subject| subject_ids.include?(subject["id"]) end subject_area_subjects_data.each do |subject_data| subject_attributes = subject_data.fetch("attributes") begin - ::Subject.find_or_create_by!( + subject = ::Subject.find_or_create_by!( subject_area:, name: subject_attributes.fetch("name"), code: subject_attributes.fetch("code"), ) + # Parent subject assigned separately, in case the subject already + # exists without the parent subject associated. + next if parent_subject.blank? + + subject.update!(parent_subject:) rescue ActiveRecord::RecordInvalid => e Sentry.capture_exception(e) end end end - def fetch_subject_ids(subject_area_ids:, data:) + def fetch_subject_ids(subject_area_id:, data:) subject_ids = [] - subject_areas = data.select do |subject_area_data| - subject_area_ids.include?(subject_area_data.fetch("id")) + subject_area = data.find do |subject_area_data| + subject_area_data["id"] == subject_area_id end - subject_areas.each do |subject_area| - subject_area.dig("relationships", "subjects", "data").each do |subject_data| - subject_ids << subject_data["id"] - end + + return if subject_area.blank? + + subject_area.dig("relationships", "subjects", "data").each do |subject_data| + subject_ids << subject_data["id"] end subject_ids diff --git a/db/data/20240522123948_update_modern_language_child_subjects.rb b/db/data/20240522123948_update_modern_language_child_subjects.rb new file mode 100644 index 000000000..db28ad279 --- /dev/null +++ b/db/data/20240522123948_update_modern_language_child_subjects.rb @@ -0,0 +1,55 @@ +class UpdateModernLanguageChildSubjects < ActiveRecord::Migration[7.1] + def up + api_response = PublishTeacherTraining::Subject::Api.call + child_subject_ids = modern_language_child_subject_ids(api_response.fetch("data")) + + subjects_data = api_response.fetch("included") + + assign_parent_subject(parent_subject: modern_languages, child_subject_ids:, subjects_data:) + end + + def down + return if modern_languages.blank? + + Subject.where(parent_subject: modern_languages).update_all(parent_subject_id: nil) + end + + private + + def modern_languages + @modern_languages ||= Subject.find_by(name: "Modern Languages") + end + + def modern_language_child_subject_ids(data) + subject_ids = [] + + modern_language_subject_area = data.find do |subject_area| + subject_area["id"] == "ModernLanguagesSubject" + end + + modern_language_subject_area.dig("relationships", "subjects", "data").each do |subject_data| + subject_ids << subject_data["id"] + end + + subject_ids + end + + def assign_parent_subject(parent_subject:, child_subject_ids:, subjects_data:) + return if parent_subject.blank? + + child_subjects_data = subjects_data.select do |subject| + child_subject_ids.include?(subject["id"]) + end + + child_subjects_data.each do |child_subject_data| + subject_attributes = child_subject_data["attributes"] + child_subject = Subject.find_by( + name: subject_attributes["name"], + code: subject_attributes["code"], + ) + next if child_subject.blank? + + child_subject.update!(parent_subject:) + end + end +end diff --git a/db/data_schema.rb b/db/data_schema.rb new file mode 100644 index 000000000..b42f15f8d --- /dev/null +++ b/db/data_schema.rb @@ -0,0 +1 @@ +DataMigrate::Data.define(version: 20240522123948) diff --git a/spec/services/publish_teacher_training/subject/import_spec.rb b/spec/services/publish_teacher_training/subject/import_spec.rb index f282fd403..52411239f 100644 --- a/spec/services/publish_teacher_training/subject/import_spec.rb +++ b/spec/services/publish_teacher_training/subject/import_spec.rb @@ -16,15 +16,20 @@ described_class.call }.to change(Subject.primary, :count).by(2).and change( Subject.secondary, :count - ).by(3) + ).by(4) expect(Subject.primary.pluck(:name)).to match_array([ "Primary", "Primary with English" ]) expect(Subject.secondary.pluck(:name)).to match_array([ - "Art and design", "Science", "French" + "Art and design", "Science", "French", "Modern Languages" ]) + + modern_languages = Subject.find_by(name: "Modern Languages") + expect(modern_languages.child_subjects.pluck(:name)).to match_array( + %w[French], + ) end context "when a subject already exists" do @@ -33,7 +38,7 @@ expect { described_class.call - }.to change(Subject, :count).by(4) + }.to change(Subject, :count).by(5) end end end @@ -147,6 +152,10 @@ def response_body "type" => "subjects", "id" => "4", }, + { + "type" => "subjects", + "id" => "7", + }, ], }, }, @@ -209,6 +218,14 @@ def response_body "code" => "F0", }, }, + { + "id" => "7", + "type" => "subjects", + "attributes" => { + "name" => "Modern Languages", + "code" => nil, + }, + }, { "id" => "5", "attributes" => {