From 544de0a8006537e3406a73fa3611ce40455d470e Mon Sep 17 00:00:00 2001 From: Shafay Javed Date: Wed, 7 Aug 2024 08:19:59 +0100 Subject: [PATCH] feat(crm): Adding non participating schools in a group --- .../cases/additional_contacts_controller.rb | 77 +++++++++++++++++++ .../other_schools_controller.rb | 67 ++++++++++++++++ .../support/establishments_controller.rb | 8 ++ app/forms/support/other_school_form.rb | 20 +++++ app/forms/support/other_school_form_schema.rb | 21 +++++ app/models/support/case.rb | 5 ++ app/views/layouts/_messages.html.erb | 43 ++++++++--- .../confirmation_message.html.erb | 35 +++++++++ .../non_beneficiery_schools.html.erb | 38 +++++++++ .../other_schools/other_school.html.erb | 20 +++++ .../participating_schools/show.html.erb | 2 + .../cases/school_details/show.html.erb | 14 ++++ config/locales/en.yml | 40 +++++++++- config/locales/validation/support/en.yml | 6 ++ config/routes.rb | 8 ++ ...0802141442_add_other_school_urn_to_case.rb | 5 ++ db/schema.rb | 3 +- ...t_can_update_participating_schools_spec.rb | 2 +- spec/models/support/case_spec.rb | 2 +- 19 files changed, 397 insertions(+), 19 deletions(-) create mode 100644 app/controllers/support/cases/additional_contacts_controller.rb create mode 100644 app/controllers/support/cases/school_details/other_schools_controller.rb create mode 100644 app/forms/support/other_school_form.rb create mode 100644 app/forms/support/other_school_form_schema.rb create mode 100644 app/views/support/cases/school_details/other_schools/confirmation_message.html.erb create mode 100644 app/views/support/cases/school_details/other_schools/non_beneficiery_schools.html.erb create mode 100644 app/views/support/cases/school_details/other_schools/other_school.html.erb create mode 100644 db/migrate/20240802141442_add_other_school_urn_to_case.rb diff --git a/app/controllers/support/cases/additional_contacts_controller.rb b/app/controllers/support/cases/additional_contacts_controller.rb new file mode 100644 index 000000000..f7d543cdd --- /dev/null +++ b/app/controllers/support/cases/additional_contacts_controller.rb @@ -0,0 +1,77 @@ +module Support + class Cases::AdditionalContactsController < Cases::ApplicationController + before_action :set_current_case, only: %i[create update edit new] + before_action :set_additional_contact, only: %i[edit update destroy] + before_action :set_additional_contacts, only: %i[index] + before_action :get_emails_of_contacts, only: %i[create update] + + def index; end + + def new + @additional_contact = @current_case&.case_additional_contacts&.build + end + + def create + @current_case = Support::Case.find(additional_contact_params[:support_case_id]) if @current_case.blank? + @additional_contact = Support::CaseAdditionalContact.build(additional_contact_params) + + if validation.success? && !@emails.include?(additional_contact_params[:email]) + @additional_contact.save! + redirect_to support_case_additional_contacts_path(case_id: @current_case.id), notice: I18n.t("support.case_contact_details.flash.success") + else + flash.now[:notice] = I18n.t("support.case_contact_details.flash.already_a_contact") if @emails.include?(additional_contact_params[:email]) + render :new + end + end + + def edit + @current_case = Support::Case.find(@additional_contact.support_case_id) + end + + def update + @emails.delete(@additional_contact.email) + if validation.success? && !@emails.include?(additional_contact_params[:email]) + @additional_contact.update!(additional_contact_params) + redirect_to support_case_additional_contacts_path(case_id: @current_case.id), notice: I18n.t("support.case.label.non_participating_schools.success.message") if @additional_contact.update(additional_contact_params) + + else + flash.now[:notice] = I18n.t("support.case_contact_details.flash.already_a_contact") if @emails.include?(additional_contact_params[:email]) + render :edit + end + end + + def destroy + @additional_contact.destroy! + redirect_to support_case_additional_contacts_path(case_id: @current_case.id), notice: I18n.t("support.case_contact_details.flash.destroyed") + end + + private + + def set_current_case + @current_case = Support::Case.find(params[:case_id]) + end + + def validation + CaseAdditionalContactFormSchema.new.call(**additional_contact_params) + end + + def set_additional_contact + @additional_contact = Support::CaseAdditionalContact.find(params[:id]) + end + + def set_additional_contacts + @additional_contacts = @current_case.case_additional_contacts + end + + def get_emails_of_contacts + @emails = @current_case.case_additional_contacts.pluck(:email) + @emails << @current_case.email + end + + def additional_contact_params + params.require(:support_case_additional_contact).permit(:first_name, :last_name, :email, :phone_number, :extension_number, :support_case_id, :organisation_id, role: []).tap do |p| + p[:role].reject!(&:blank?) + end + end + end +end diff --git a/app/controllers/support/cases/school_details/other_schools_controller.rb b/app/controllers/support/cases/school_details/other_schools_controller.rb new file mode 100644 index 000000000..cfc7bd984 --- /dev/null +++ b/app/controllers/support/cases/school_details/other_schools_controller.rb @@ -0,0 +1,67 @@ +module Support + module Cases + module SchoolDetails + class OtherSchoolsController < Cases::ApplicationController + before_action :set_instances, only: %i[confirmation_message remove_school non_beneficiery_schools] + + def non_beneficiery_schools + @back_url = support_case_path(@current_case, anchor: "school-details") + @other_schools = @current_case.other_schools.map { |s| Support::OrganisationPresenter.new(s) } + end + + def other_school + @other_school_form = OtherSchoolForm.new if @other_school_form.blank? + end + + def add_other_school + @organisation = Support::Organisation.find_by(id: other_school_form_params[:school_id]) + @other_school_form = OtherSchoolForm.from_validation(validation) + if validation.success? + if (@current_case.other_school_urns.include? @organisation.urn) || (@current_case.organisation.organisations.pluck(:urn).include? @organisation.urn) + message = if @current_case.other_school_urns.include? @organisation.urn + I18n.t("support.case.label.school_details.non_participating_schools.error.already_a_member_message", name: @organisation.name) + else + I18n.t("support.case.label.school_details.non_participating_schools.error.part_of_group_message", name: @organisation.name) + end + flash[:error] = { message:, class: "govuk-error" } + render :other_school + else + urns = @current_case.other_school_urns << @organisation.urn + @current_case.update!(other_school_urns: urns) + redirect_to non_beneficiery_schools_support_case_school_details_other_schools_path(@current_case) + flash[:notice] = I18n.t("support.case.label.school_details.non_participating_schools.success.message") + end + else + flash[:error] = { class: "remove-message" } + render :other_school + end + end + + def confirmation_message + @back_url = non_beneficiery_schools_support_case_school_details_other_schools_path(@current_case) + end + + def remove_school + school_urns = @current_case.other_school_urns - [@organisation.urn] + @current_case.update!(other_school_urns: school_urns) + redirect_to non_beneficiery_schools_support_case_school_details_other_schools_path(@current_case) + end + + private + + def validation + OtherSchoolFormSchema.new.call(**other_school_form_params) + end + + def set_instances + @organisation = Support::Organisation.find_by(id: params[:school_id]) + @current_case = Support::Case.find_by(id: params[:case_id]) + end + + def other_school_form_params + params.require(:case_organisation_form).permit(:school_id, :organisation_name) + end + end + end + end +end diff --git a/app/controllers/support/establishments_controller.rb b/app/controllers/support/establishments_controller.rb index 1ee8a058a..f009a3456 100644 --- a/app/controllers/support/establishments_controller.rb +++ b/app/controllers/support/establishments_controller.rb @@ -8,6 +8,14 @@ def index end end + def list_for_non_participating_establishment + respond_to do |format| + format.json do + render json: EstablishmentSearch.omnisearch(params[:q]).where("establishment_type not in (?)", ["Federation", "Trust", "Single-academy Trust", "Multi-academy Trust", "Umbrella trust"]).as_json(methods: %i[autocomplete_template]) + end + end + end + protected def authorize_agent_scope = :access_establishment_search? diff --git a/app/forms/support/other_school_form.rb b/app/forms/support/other_school_form.rb new file mode 100644 index 000000000..b0fa4abff --- /dev/null +++ b/app/forms/support/other_school_form.rb @@ -0,0 +1,20 @@ +# :nocov: +module Support + class OtherSchoolForm + extend Dry::Initializer + include Concerns::ValidatableForm + + option :school_id, Types::Params::String, optional: true + option :organisation_name, Types::Params::String, optional: true + + def assign_organisation_to_case(kase, agent_id) + CaseManagement::AssignOrganisationToCase.new.call( + support_case_id: kase.id, + agent_id:, + organisation_id:, + organisation_type:, + ) + end + end +end +# :nocov: diff --git a/app/forms/support/other_school_form_schema.rb b/app/forms/support/other_school_form_schema.rb new file mode 100644 index 000000000..3d0f7c7b6 --- /dev/null +++ b/app/forms/support/other_school_form_schema.rb @@ -0,0 +1,21 @@ +# :nocov: +module Support + class OtherSchoolFormSchema < Dry::Validation::Contract + include Concerns::TranslatableFormSchema + + params do + required(:school_id).value(:string) + required(:organisation_name).value(:string) + end + + rule(:school_id) do + key(:school_id).failure(:missing) if value.blank? + end + + rule(:organisation_name) do + # intentional use of organisation_id - the user should only see 1 error around organisation + key(:school_id).failure(:missing) if value.blank? + end + end +end +# :nocov: diff --git a/app/models/support/case.rb b/app/models/support/case.rb index d5dd8c9d9..785d8a4ff 100644 --- a/app/models/support/case.rb +++ b/app/models/support/case.rb @@ -160,6 +160,11 @@ def schools organisation.is_a?(Support::Organisation) ? [organisation] : participating_schools end + # If this case is associated with a MAT, there may be several participating_schools that may not be the part of MAT + def other_schools + other_school_urns.map { |urn| Support::Organisation.find_by(urn:) } + end + # The Local Education Authorities of the schools currently associated with the case, sorted alphabetically and with duplicates removed. # The 'if sch.respond_to?(:local_authority)' catches the edge case where a MAT is the organisation but none of its schools are selected. def leas diff --git a/app/views/layouts/_messages.html.erb b/app/views/layouts/_messages.html.erb index 1abeb640b..e700a12d3 100644 --- a/app/views/layouts/_messages.html.erb +++ b/app/views/layouts/_messages.html.erb @@ -1,16 +1,35 @@ <% flash.each do |name, msg| %> - <% if msg.is_a?(String) %> -