Skip to content
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

Validating A levels when publishing for teacher degree apprenticeship courses #4339

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions app/components/a_level_row_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
<% if course.a_levels_requirements_answered? %>
<% if has_errors? %>
<%= govuk_inset_text(classes: "app-inset-text--narrow-border app-inset-text--error") do %>
<% a_level_errors.each do |a_level_error| %>
<p class="govuk-heading-s app-inset-text__title">
<%= t("course.#{wizard_step(a_level_error)}.heading") %>
</p>
<p class="govuk-body">
<%= govuk_link_to(
@errors[a_level_error],
enrichment_error_url(course:, provider_code:, field: a_level_error.to_s, message: @errors[a_level_error])
) %>
</p>
<% end %>
<% end %>
<% elsif minimum_a_level_completed? %>
<% if @course.a_level_requirements.present? %>
<% Array(@course.a_level_subject_requirements).map do |a_level_subject_requirement| %>
<p class="govuk-body">
Expand Down Expand Up @@ -26,17 +40,17 @@
<% else %>
<%= a_level_not_required_content %>
<% end %>

<% else %>
<%= govuk_inset_text(classes: inset_text_css_classes) do %>
<p class="govuk-heading-s app-inset-text__title"><%= t("publish.providers.courses.description_content.a_levels_heading") %></p>
<%= govuk_inset_text(classes: "app-inset-text--narrow-border app-inset-text--important") do %>
<p class="govuk-heading-s app-inset-text__title">
<%= t("publish.providers.courses.description_content.a_levels_heading") %>
</p>
<p class="govuk-body">
<%= govuk_link_to t("publish.providers.courses.description_content.enter_a_levels"),
publish_provider_recruitment_cycle_course_a_levels_are_any_a_levels_required_for_this_course_path(
course.provider.provider_code,
course.provider.recruitment_cycle_year,
course.course_code,
display_errors: has_errors? ? true : nil
course.course_code
) %>
</p>
<% end %>
Expand Down
36 changes: 31 additions & 5 deletions app/components/a_level_row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
class ALevelRowComponent < ViewComponent::Base
attr_reader :course, :errors

delegate :provider, to: :course
delegate :provider_code, to: :provider
include ViewHelper

A_LEVEL_ERRORS = %i[
a_level_requirements
a_level_subject_requirements
accept_pending_a_level
accept_a_level_equivalency
].freeze

def initialize(course:, errors: nil)
super
@course = course
@errors = errors&.values&.flatten
@errors = errors
end

def a_level_not_required_content
Expand Down Expand Up @@ -34,11 +45,26 @@ def a_level_equivalency_summary_content
I18n.t("course.a_level_equivalencies.row.#{@course.accept_a_level_equivalency?}") unless @course.accept_a_level_equivalency.nil?
end

def inset_text_css_classes
'app-inset-text--narrow-border app-inset-text--important'
def has_errors?
@errors.present? && a_level_errors.any?
end

def has_errors?
false
def a_level_errors
Array(@errors.keys & A_LEVEL_ERRORS)
end

def wizard_step(a_level_error)
{
a_level_requirements: :are_any_a_levels_required_for_this_course,
a_level_subject_requirements: :what_a_level_is_required,
accept_pending_a_level: :consider_pending_a_level,
accept_a_level_equivalency: :a_level_equivalencies
}.with_indifferent_access[a_level_error]
end

def minimum_a_level_completed?
!course.a_level_requirements.nil? &&
(course.a_level_requirements.blank? ||
(course.a_level_requirements.present? && course.a_level_subject_requirements.present?))
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def new
course: @course,
step_params:
)

@wizard.valid_step? if params[:display_errors].present?
end

def create
Expand Down
5 changes: 2 additions & 3 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ def enrichment_error_link(model, field, error)
end

# TODO: refactor enrichment_summary method to not use an instance variable
def enrichment_summary(summary_list, model, key, value, fields, action_path: nil, action_visually_hidden_text: nil)
def enrichment_summary(summary_list, model, key, value, fields, action_path: nil, action_visually_hidden_text: nil, render_errors: true)
action = render_action(action_path, action_visually_hidden_text || key.downcase)

if fields.any? { |field| @errors&.key? field.to_sym }
errors = fields.map do |field|
@errors[field.to_sym]&.map { |error| enrichment_error_link(model, field, error) }
end.flatten

value = raw(*errors)
value = raw(*errors) if render_errors.present?
Copy link
Contributor Author

@tomas-stefano tomas-stefano Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoiding the automatic behaviour because on the row, the error message is slightly different on A level since the A levels is the only multi step form in the course description tab. Unfortunately I have to do this to follow the same pattern but avoiding undesirable results.

action = nil
end

Expand Down
26 changes: 25 additions & 1 deletion app/helpers/view_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,31 @@ def enrichment_error_url(provider_code:, course:, field:, message: nil)
sites: "#{base}/schools?display_errors=true",
study_sites: (course.provider&.study_sites&.none? ? "#{provider_base}/study-sites" : "#{base}/study-sites").to_s,
accrediting_provider: accredited_provider_publish_provider_recruitment_cycle_course_path(course.provider_code, course.recruitment_cycle_year, course.course_code),
applications_open_from: "#{base}/applications-open"
applications_open_from: "#{base}/applications-open",
a_level_requirements: publish_provider_recruitment_cycle_course_a_levels_are_any_a_levels_required_for_this_course_path(
course.provider_code,
course.provider.recruitment_cycle_year,
course.course_code,
display_errors: true
),
a_level_subject_requirements: publish_provider_recruitment_cycle_course_a_levels_what_a_level_is_required_path(
course.provider_code,
course.provider.recruitment_cycle_year,
course.course_code,
display_errors: true
),
accept_pending_a_level: publish_provider_recruitment_cycle_course_a_levels_consider_pending_a_level_path(
course.provider_code,
course.provider.recruitment_cycle_year,
course.course_code,
display_errors: true
),
accept_a_level_equivalency: publish_provider_recruitment_cycle_course_a_levels_a_level_equivalencies_path(
course.provider_code,
course.provider.recruitment_cycle_year,
course.course_code,
display_errors: true
)
}.with_indifferent_access[field]
end
end
Expand Down
1 change: 1 addition & 0 deletions app/models/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ def self.entry_requirement_options_without_nil_choice
validate :validate_custom_age_range, on: %i[create new], if: -> { age_range_in_years.present? }
validate :accredited_provider_exists_in_current_cycle, on: :publish, unless: -> { self_accredited? }
validates_with UniqueCourseValidator, on: :new
validates_with ALevelCourseValidator, on: :publish, if: :teacher_degree_apprenticeship?

validates :name, :profpost_flag, :program_type, :qualification, :start_date, :study_mode, presence: true
validates :age_range_in_years, presence: true, on: %i[new create publish], unless: :further_education_course?
Expand Down
15 changes: 15 additions & 0 deletions app/validators/a_level_course_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

class ALevelCourseValidator < ActiveModel::Validator
def validate(record)
return record.errors.add(:a_level_requirements, :blank) if record.a_level_requirements.nil?

return if record.a_level_requirements.blank? # No A level required

return record.errors.add(:a_level_subject_requirements, :blank) if record.a_level_subject_requirements.blank?

return record.errors.add(:accept_pending_a_level, :blank) if record.accept_pending_a_level.nil?

record.errors.add(:accept_a_level_equivalency, :blank) if record.accept_a_level_equivalency.nil?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validations are sequential (meaning one at a time), so I opt-in to add a custom validator.

end
end
11 changes: 8 additions & 3 deletions app/views/publish/courses/_description_content.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,14 @@
:course,
t("publish.providers.courses.description_content.a_levels_label"),
(render ALevelRowComponent.new(course:, errors: @errors)),
%w[a_levels_requirements],
action_path: publish_provider_recruitment_cycle_course_a_levels_are_any_a_levels_required_for_this_course_path(@provider.provider_code, @provider.recruitment_cycle_year, course.course_code),
action_visually_hidden_text: "A levels"
%w[a_level_requirements a_level_subject_requirements accept_pending_a_level accept_a_level_equivalency],
action_path: publish_provider_recruitment_cycle_course_a_levels_are_any_a_levels_required_for_this_course_path(
@provider.provider_code,
@provider.recruitment_cycle_year,
course.course_code
),
action_visually_hidden_text: "A levels",
render_errors: false
) %>
<% end %>

Expand Down
8 changes: 8 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,14 @@ en:
does_not_exist_in_cycle: "The accredited provider %{accredited_provider_code} does not exist in this cycle"
is_send:
inclusion: Select if this course has a special educational needs and disability (SEND) specialism
a_level_requirements:
blank: Enter A level requirements
a_level_subject_requirements:
blank: Enter A level requirements
accept_pending_a_level:
blank: Enter information on pending A levels
accept_a_level_equivalency:
blank: Enter A level equivalency test requirements
base:
duplicate: "This course already exists. You should add further schools for this course to the existing profile in Publish"
visa_sponsorship_not_publishable: "Select if visas can be sponsored"
Expand Down
Loading
Loading