-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix duplicate subject validation on secondary course selection #4224
Changes from all commits
de6c09d
658157c
32f6517
bbfdc1b
4ae9be6
dd4d645
02f51d0
e38badd
83f93a9
9b7535c
878dfda
ebfd3af
c4851a8
f658610
a7c4481
d2f4012
054b920
85a4534
92876cc
a266681
3764980
44b9427
5f7ae53
b2b3a95
84bb08f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ def continue | |
def edit | ||
authorize(provider) | ||
|
||
return if selected_non_language_subjects_ids.include? modern_languages_subject_id.to_s | ||
return if selected_non_language_subjects_ids.include? modern_languages_subject_id | ||
|
||
redirect_to( | ||
details_publish_provider_recruitment_cycle_course_path( | ||
|
@@ -67,7 +67,7 @@ def current_step | |
private | ||
|
||
def updated_subject_list | ||
@updated_subject_list ||= selected_language_subjects_ids.concat(selected_non_language_subjects_ids) | ||
@updated_subject_list ||= selected_non_language_subjects_ids.concat(selected_language_subjects_ids) | ||
end | ||
|
||
def course_subjects_form | ||
|
@@ -87,9 +87,7 @@ def selected_subjects(param_key) | |
|
||
ids = params.dig(:course, param_key)&.map(&:to_i) || [] | ||
|
||
@course.edit_course_options[edit_course_options_key].filter_map do |subject| | ||
subject.id.to_s if ids.include?(subject.id) | ||
end | ||
ids.intersection(@course.edit_course_options[edit_course_options_key].map(&:id)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This piece of code would rearrange the subject_ids array in the order that they appear in the result of Now the subject ids stay in the same order they were before this is called |
||
end | ||
|
||
def selected_language_subjects_ids | ||
|
@@ -101,7 +99,7 @@ def selected_non_language_subjects_ids | |
end | ||
|
||
def has_modern_languages_subject? | ||
@course.subjects.any? { |subject| subject.id == modern_languages_subject_id } | ||
@course.course_subjects.any? { |subject| subject.subject.id == modern_languages_subject_id } | ||
end | ||
|
||
def build_course_params | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,56 +18,71 @@ def continue | |
|
||
def update | ||
authorize(provider) | ||
if params[:course][:master_subject_id] == SecondarySubject.physics.id.to_s | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
redirect_to( | ||
engineers_teach_physics_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code, | ||
course: { master_subject_id: SecondarySubject.physics.id.to_s, subjects_ids: selected_subject_ids } | ||
if validate_subject_ids | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a short circuit to avoid calling |
||
if params[:course][:master_subject_id] == SecondarySubject.physics.id.to_s | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
redirect_to( | ||
engineers_teach_physics_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code, | ||
course: { master_subject_id: SecondarySubject.physics.id.to_s, subjects_ids: selected_subject_ids } | ||
) | ||
) | ||
) | ||
|
||
elsif selected_subject_ids.include?(modern_languages_subject_id.to_s) | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
redirect_to( | ||
modern_languages_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code, | ||
course: { subjects_ids: selected_subject_ids } | ||
|
||
elsif selected_subject_ids.include?(modern_languages_subject_id.to_s) | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
redirect_to( | ||
modern_languages_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code, | ||
course: { subjects_ids: selected_subject_ids } | ||
) | ||
) | ||
) | ||
|
||
elsif course_subjects_form.save! | ||
course_updated_message(section_key) | ||
# TODO: move this to the form? | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
course.update(name: course.generate_name) | ||
course.update(campaign_name: nil) unless course.master_subject_id == SecondarySubject.physics.id | ||
|
||
redirect_to( | ||
details_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code | ||
|
||
elsif course.errors.none? && course_subjects_form.save! | ||
Comment on lines
-43
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This actually isn't necessary anymore since the |
||
course_updated_message(section_key) | ||
# TODO: move this to the form? | ||
course.update(master_subject_id: params[:course][:master_subject_id]) | ||
course.update(name: course.generate_name) | ||
course.update(campaign_name: nil) unless course.master_subject_id == SecondarySubject.physics.id | ||
|
||
redirect_to( | ||
details_publish_provider_recruitment_cycle_course_path( | ||
@course.provider_code, | ||
@course.recruitment_cycle_year, | ||
@course.course_code | ||
) | ||
) | ||
) | ||
end | ||
else | ||
@errors = @course.errors.messages | ||
course.master_subject_id = selected_master | ||
course.subordinate_subject_id = selected_subordinate | ||
Comment on lines
+61
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is used to repopulate the form fields in the event of an invalid form |
||
render :edit | ||
end | ||
end | ||
|
||
private | ||
|
||
def validate_subject_ids | ||
if selected_master.blank? | ||
course.errors.add(:subjects, :course_creation) | ||
return false | ||
elsif selected_master == selected_subordinate | ||
course.errors.add(:subjects, :duplicate) | ||
return false | ||
end | ||
true | ||
end | ||
|
||
def campaign_name_check | ||
params[:course][:campaign_name] = '' unless @course.master_subject_id == SecondarySubject.physics.id | ||
end | ||
|
||
def course_subjects_form | ||
@course_subjects_form ||= CourseSubjectsForm.new(@course, params: selected_subject_ids) | ||
@course_subjects_form ||= CourseSubjectsForm.new(@course, params: [selected_master, selected_subordinate]) | ||
Comment on lines
-70
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These subject_ids are passed directly into the The first two subject_ids in this array should always be This makes it easier to handle the secondary subjects, and their precedence. |
||
end | ||
|
||
def modern_languages_subject_id | ||
|
@@ -87,18 +102,17 @@ def error_keys | |
end | ||
|
||
def selected_master | ||
@selected_master ||= params[:course][:master_subject_id] if params[:course][:master_subject_id].present? | ||
params[:course][:master_subject_id].presence | ||
end | ||
|
||
def selected_subordinate | ||
@selected_subordinate ||= params[:course][:subordinate_subject_id] if params[:course][:subordinate_subject_id].present? | ||
params[:course][:subordinate_subject_id].presence | ||
end | ||
|
||
def build_course_params | ||
previous_subject_selections = params[:course][:subjects_ids] | ||
|
||
params[:course][:subjects_ids] = selected_subject_ids | ||
params[:course].delete(:subordinate_subject_id) | ||
|
||
build_new_course # to get languages edit_options | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ class CourseSubjectsForm < BaseCourseForm | |
alias subject_ids params | ||
|
||
def initialize(model, params: {}) | ||
@previous_subject_names = model.subjects.map(&:subject_name) | ||
@previous_subject_names = model.course_subjects.map { |cs| cs.subject.subject_name } | ||
@previous_course_name = model.name | ||
super | ||
end | ||
|
@@ -15,7 +15,7 @@ def initialize(model, params: {}) | |
attr_reader :previous_subject_names, :previous_course_name | ||
|
||
def valid? | ||
super && assign_subjects_service.valid? | ||
super && assign_subjects_service.errors.none? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The course is returned from Calling |
||
end | ||
|
||
def compute_fields | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,19 @@ class Course < ApplicationRecord | |
has_associated_audits | ||
audited | ||
|
||
attribute :subordinate_subject_id, :integer | ||
after_initialize do | ||
if is_primary? | ||
self.master_subject_id ||= course_subjects.first&.subject_id | ||
else | ||
sub = course_subjects.select(&:position) | ||
|
||
self.master_subject_id ||= sub.first&.subject&.id | ||
|
||
self.subordinate_subject_id ||= sub&.second&.subject&.id | ||
end | ||
Comment on lines
+23
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not account for Further Education, but there is no form inputs for further Education level courses. The |
||
end | ||
|
||
validates :course_code, | ||
uniqueness: { scope: :provider_id }, | ||
presence: true, | ||
|
@@ -566,7 +579,7 @@ def publish_enrichment(current_user) | |
end | ||
|
||
def is_modern_language_course? | ||
subjects.any? { |s| s == SecondarySubject.modern_languages } | ||
course_subjects.any? { |cs| cs.subject == SecondarySubject.modern_languages } | ||
end | ||
|
||
def sites=(desired_sites) | ||
|
@@ -795,15 +808,19 @@ def remove_carat_from_error_messages | |
end | ||
|
||
def modern_language_subjects | ||
subjects.where(type: 'ModernLanguagesSubject') | ||
if persisted? && course_subjects.all?(&:persisted?) | ||
subjects.where(type: 'ModernLanguagesSubject') | ||
else | ||
course_subjects.select { |cs| cs.subject.type == 'ModernLanguagesSubject' }.map(&:subject) | ||
end | ||
end | ||
|
||
def master_subject_nil? | ||
master_subject_id.nil? | ||
end | ||
|
||
def has_any_modern_language_subject_type? | ||
subjects.any? { |subject| subject.type == 'ModernLanguagesSubject' } | ||
course_subjects.any? { |cs| cs.subject.type == 'ModernLanguagesSubject' } | ||
end | ||
|
||
def current_published_enrichment | ||
|
@@ -990,24 +1007,24 @@ def has_the_modern_languages_secondary_subject_type? | |
raise 'SecondarySubject not found' if SecondarySubject.nil? | ||
raise 'SecondarySubject.modern_languages not found' if SecondarySubject.modern_languages.nil? | ||
|
||
subjects.any? { |subject| subject&.id == SecondarySubject.modern_languages.id } | ||
course_subjects.any? { |cs| cs.subject&.id == SecondarySubject.modern_languages.id } | ||
end | ||
|
||
def validate_has_languages | ||
errors.add(:modern_languages_subjects, :select_a_language) unless has_any_modern_language_subject_type? | ||
end | ||
|
||
def validate_subject_count | ||
if subjects.empty? | ||
if course_subjects.empty? | ||
errors.add(:subjects, :course_creation) | ||
return | ||
end | ||
|
||
case level | ||
when 'primary', 'further_education' | ||
errors.add(:subjects, 'has too many subjects') if subjects.count > 1 | ||
errors.add(:subjects, 'has too many subjects') if course_subjects.count > 1 | ||
when 'secondary' | ||
errors.add(:subjects, 'has too many subjects') if subjects.count > 2 && !has_any_modern_language_subject_type? | ||
errors.add(:subjects, 'has too many subjects') if course_subjects.count > 2 && !has_any_modern_language_subject_type? | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,6 @@ def execute(funding_type, course) | |
when 'fee' | ||
course.program_type = calculate_fee_program(course) | ||
end | ||
# NOTE: This looks like unwarranted side effects | ||
course.save | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a hangover from a previous version of the application. This service gets called during the building of a new course. When This is not what we want when incrementally building up errors in the new course flow. |
||
|
||
private | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This contributes to the new ordering of subject ids where the master and subordinate subject ids are at the front and not unshited back when languages are added