diff --git a/app/controllers/support/cases/additional_contacts_controller.rb b/app/controllers/support/cases/additional_contacts_controller.rb index f7d543cdd..f55faaf02 100644 --- a/app/controllers/support/cases/additional_contacts_controller.rb +++ b/app/controllers/support/cases/additional_contacts_controller.rb @@ -8,34 +8,35 @@ class Cases::AdditionalContactsController < Cases::ApplicationController def index; end def new - @additional_contact = @current_case&.case_additional_contacts&.build + @case_additional_contact_form = CaseAdditionalContactForm.new(@current_case) 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! + @case_additional_contact_form = CaseAdditionalContactForm.from_validation(validation) + @current_case = Support::Case.find(case_additional_contact_form_params[:support_case_id]) if @current_case.blank? + @emails = @current_case.case_additional_contacts&.pluck(:email) + if validation.success? && !@emails.include?(case_additional_contact_form_params[:email]) + Support::CaseAdditionalContact.create!(case_additional_contact_form_params) 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]) + flash[:error] = { message: I18n.t("support.case_contact_details.flash.already_a_contact"), class: "govuk-error" } if @emails.include?(case_additional_contact_form_params[:email]) render :new end end def edit - @current_case = Support::Case.find(@additional_contact.support_case_id) + @case_additional_contact_form = CaseAdditionalContactForm.from_case(@additional_contact) end def update + @case_additional_contact_form = CaseAdditionalContactForm.from_validation(validation) @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) + if validation.success? && !@emails.include?(case_additional_contact_form_params[:email]) + @additional_contact.update!(case_additional_contact_form_params) + redirect_to support_case_additional_contacts_path(case_id: @current_case.id), notice: I18n.t("support.case_contact_details.flash.update_success") if @additional_contact.update(case_additional_contact_form_params) else - flash.now[:notice] = I18n.t("support.case_contact_details.flash.already_a_contact") if @emails.include?(additional_contact_params[:email]) + flash[:error] = { message: I18n.t("support.case_contact_details.flash.already_a_contact"), class: "govuk-error" } if @emails.include?(case_additional_contact_form_params[:email]) render :edit end end @@ -52,7 +53,7 @@ def set_current_case end def validation - CaseAdditionalContactFormSchema.new.call(**additional_contact_params) + CaseAdditionalContactFormSchema.new.call(**case_additional_contact_form_params) end def set_additional_contact @@ -60,7 +61,8 @@ def set_additional_contact end def set_additional_contacts - @additional_contacts = @current_case.case_additional_contacts + @back_url = support_case_path(@current_case, anchor: "school-details") + @additional_contacts = @current_case.case_additional_contacts.order(:created_at) end def get_emails_of_contacts @@ -68,8 +70,8 @@ def get_emails_of_contacts @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| + def case_additional_contact_form_params + params.require(:case_additional_contacts_form).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 diff --git a/app/controllers/support/cases/contact_details_controller.rb b/app/controllers/support/cases/contact_details_controller.rb index f91ccb401..d446ec2c8 100644 --- a/app/controllers/support/cases/contact_details_controller.rb +++ b/app/controllers/support/cases/contact_details_controller.rb @@ -6,11 +6,15 @@ def edit def update @case_contact_details_form = CaseContactDetailsForm.from_validation(validation) - - if validation.success? && @case_contact_details_form.update_contact_details(current_case, current_agent.id) - redirect_to support_case_path(current_case, anchor: "school-details"), - notice: I18n.t("support.case_contact_details.flash.updated") + @emails = current_case.case_additional_contacts&.pluck(:email) + case_contact_details_form_params[:is_evaluator] = params[:is_evaluator] == "true" ? "true" : "false" + if validation.success? && !@emails.include?(case_contact_details_form_params[:email]) + if @current_case.update!(case_contact_details_form_params) + redirect_to support_case_path(current_case, anchor: "school-details"), + notice: I18n.t("support.case_contact_details.flash.updated") + end else + flash[:error] = { message: "Already a contact", class: "govuk-error" } if @emails.include?(case_contact_details_form_params[:email]) render :edit end end @@ -22,7 +26,7 @@ def validation end def case_contact_details_form_params - params.require(:case_contact_details_form).permit(:first_name, :last_name, :phone, :email, :extension_number) + params.require(:case_contact_details_form).permit(:first_name, :last_name, :phone_number, :email, :extension_number, :is_evaluator, :organisation_id, :organisation_type) end end end diff --git a/app/cores/case_management/update_case_additional_contacts.rb b/app/cores/case_management/update_case_additional_contacts.rb new file mode 100644 index 000000000..57081da1c --- /dev/null +++ b/app/cores/case_management/update_case_additional_contacts.rb @@ -0,0 +1,27 @@ +module CaseManagement + class UpdateCaseAdditionalContacts + include Wisper::Publisher + + def call(support_case_id:, first_name:, last_name:, phone:, email:, extension_number:, role:) + support_case = Support::Case.find(support_case_id) + support_case.update!( + first_name:, + last_name:, + phone_number: phone, + email:, + extension_number:, + role:, + ) + + broadcast(:case_additional_contacts_changed, { + case_id: support_case_id, + first_name:, + last_name:, + phone_number: phone, + email:, + extension_number:, + role:, + }) + end + end +end diff --git a/app/forms/support/case_additional_contact_form.rb b/app/forms/support/case_additional_contact_form.rb new file mode 100644 index 000000000..9b8554f67 --- /dev/null +++ b/app/forms/support/case_additional_contact_form.rb @@ -0,0 +1,29 @@ +module Support + class CaseAdditionalContactForm + extend Dry::Initializer + include Concerns::ValidatableForm + + option :first_name, Types::Params::String | Types::Nil, optional: true + option :last_name, Types::Params::String | Types::Nil, optional: true + option :email, Types::Params::String, optional: true, default: proc { "" } + option :phone_number, Types::Params::String | Types::Nil, optional: true + option :extension_number, Types::Params::String | Types::Nil, optional: true + option :role, Types::Params::String | Types::Array, optional: true + + def self.from_case(additional_contact) + new(first_name: additional_contact.first_name, last_name: additional_contact.last_name, email: additional_contact.email, phone: additional_contact.phone_number, extension_number: additional_contact.extension_number, role: additional_contact.role) + end + + def update_contact_details(kase) + CaseManagement::UpdateCaseAdditionalContacts.new.call( + support_case_id: kase.id, + first_name:, + last_name:, + phone:, + email:, + extension_number:, + role:, + ) + end + end +end diff --git a/app/forms/support/case_additional_contact_form_schema.rb b/app/forms/support/case_additional_contact_form_schema.rb new file mode 100644 index 000000000..9e634307e --- /dev/null +++ b/app/forms/support/case_additional_contact_form_schema.rb @@ -0,0 +1,21 @@ +module Support + class CaseAdditionalContactFormSchema < Dry::Validation::Contract + include Concerns::TranslatableFormSchema + + params do + required(:first_name).value(:string) + required(:last_name).value(:string) + optional(:phone_number).value(:string) + required(:email).value(:string) + optional(:extension_number).value(:string) + end + + rule(:email) do + if value.blank? + key(:email).failure(:missing) + else + key(:email).failure(:invalid_format) unless value.scan(URI::MailTo::EMAIL_REGEXP).any? + end + end + end +end diff --git a/app/forms/support/case_contact_details_form.rb b/app/forms/support/case_contact_details_form.rb index 1aecb6a0f..f362ebbb2 100644 --- a/app/forms/support/case_contact_details_form.rb +++ b/app/forms/support/case_contact_details_form.rb @@ -6,11 +6,17 @@ class CaseContactDetailsForm option :first_name, Types::Params::String | Types::Nil, optional: true option :last_name, Types::Params::String | Types::Nil, optional: true option :email, Types::Params::String, optional: true, default: proc { "" } - option :phone, Types::Params::String | Types::Nil, optional: true + option :phone_number, Types::Params::String | Types::Nil, optional: true option :extension_number, Types::Params::String | Types::Nil, optional: true def self.from_case(kase) - new(first_name: kase.first_name, last_name: kase.last_name, email: kase.email, phone: kase.phone_number, extension_number: kase.extension_number) + new( + first_name: kase.first_name, + last_name: kase.last_name, + email: kase.email, + phone_number: kase.phone_number, + extension_number: kase.extension_number, + ) end def update_contact_details(kase, agent_id) @@ -19,7 +25,7 @@ def update_contact_details(kase, agent_id) agent_id:, first_name:, last_name:, - phone:, + phone_number:, email:, extension_number:, ) diff --git a/app/helpers/support/case_additional_contacts_helper.rb b/app/helpers/support/case_additional_contacts_helper.rb new file mode 100644 index 000000000..5570f3793 --- /dev/null +++ b/app/helpers/support/case_additional_contacts_helper.rb @@ -0,0 +1,7 @@ +module Support + module CaseAdditionalContactsHelper + def role_options + CheckboxOption.from(I18nOption.from("support.case_additional_contact.role.options.%%key%%", Support::CaseAdditionalContact.role_values), exclusive_fields: %w[none]) + end + end +end diff --git a/app/models/support/case.rb b/app/models/support/case.rb index 785d8a4ff..3146768dd 100644 --- a/app/models/support/case.rb +++ b/app/models/support/case.rb @@ -57,6 +57,8 @@ class Case < ApplicationRecord has_one :framework_request, class_name: "FrameworkRequest", foreign_key: :support_case_id has_one :case_request, class_name: "CaseRequest", foreign_key: :support_case_id + has_many :case_additional_contacts, class_name: "Support::CaseAdditionalContact", foreign_key: :support_case_id + accepts_nested_attributes_for :hub_transition, allow_destroy: true, reject_if: :all_blank # Support level diff --git a/app/models/support/case_additional_contact.rb b/app/models/support/case_additional_contact.rb new file mode 100644 index 000000000..9aab783ac --- /dev/null +++ b/app/models/support/case_additional_contact.rb @@ -0,0 +1,12 @@ +module Support + class CaseAdditionalContact < ApplicationRecord + belongs_to :case, class_name: "Support::Case", foreign_key: "support_case_id" + belongs_to :organisation, class_name: "Support::Organisation", optional: true + + validates :first_name, :last_name, :email, presence: true + + def self.role_values + %w[lead evaluator] + end + end +end diff --git a/app/models/support/organisation.rb b/app/models/support/organisation.rb index 9605a9ba6..47c675861 100644 --- a/app/models/support/organisation.rb +++ b/app/models/support/organisation.rb @@ -22,6 +22,8 @@ class Organisation < ApplicationRecord belongs_to :local_authority, class_name: "LocalAuthority" + has_many :case_additional_contacts, class_name: "Support::CaseAdditionalContact" + has_many :cases, class_name: "Support::Case", as: :organisation validates :urn, uniqueness: true diff --git a/app/views/layouts/_messages.html.erb b/app/views/layouts/_messages.html.erb index e700a12d3..48af1d7f1 100644 --- a/app/views/layouts/_messages.html.erb +++ b/app/views/layouts/_messages.html.erb @@ -1,22 +1,20 @@ <% flash.each do |name, msg| %> <% if flash[:error].present? && flash[:error][:class].present? %> - <%if flash[:error][:class]!= "remove-message"%> -
-
-

- There is a problem -

- -
-
- <%end%> - <%else%> +
+
+

+ There is a problem +

+ +
+
+ <%else%> <% if msg.is_a?(String) %> <% end %> - <%end%> + <%end%> <% end %> diff --git a/app/views/support/cases/additional_contacts/_form.html.erb b/app/views/support/cases/additional_contacts/_form.html.erb new file mode 100644 index 000000000..323f79d4b --- /dev/null +++ b/app/views/support/cases/additional_contacts/_form.html.erb @@ -0,0 +1,50 @@ + +

<%= I18n.t("support.case_contact_details.header") %>

+<%new_contact = action_name == 'new' || action_name == 'create'%> +

<%= I18n.t("support.case_contact_details.description") %>

+<%= form_with(model: @case_additional_contact_form, scope: :case_additional_contacts_form, url: new_contact ? support_case_additional_contacts_path(@current_case) : support_case_additional_contact_path(@current_case, support_case_additional_contact), method: new_contact ? :post : :put, remote: true) do |form| %> + <%= form.govuk_error_summary %> + + <%= form.govuk_text_field :first_name, autofocus: true, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.first_name") } %> + <%= form.govuk_text_field :last_name, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.last_name") } %> + <%= form.govuk_text_field :email, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.email") } %> + <%= form.govuk_text_field :phone_number, width: 'one-quarter', label: { text: I18n.t("support.case_contact_details.label.phone") } %> + <%= form.govuk_text_field :extension_number, width: 'one-quarter', label: { text: I18n.t("support.case_contact_details.label.extension_number") } %> + + <% + +=begin%> + #below code is commented because it can be used later. It is a field for organisation selection. + <%= render "components/autocomplete", + container_id: "case-contacts-organisation-field", + label_text: I18n.t("support.case_additional_contact.organisation.header"), + label_class: "govuk_text_field", + element_id: "additional_contacts-autocomplete", + element_name: "organisation_name", + template_suggestion: "{{autocomplete_template}}", + value_field: :name, + default_value: form.object.organisation&.name, + hidden_fields: { + 'support_case_additional_contact[organisation_id]' => [:id, form.object.organisation&.id], + # 'case_request[organisation_type]' => [:source, form.object.organisation.class&.name], + }, + query_url: support_establishments_path(format: :json, q: "{{QUERY}}") %> +<% +=end%> + + +
+ + <%= form.govuk_collection_check_boxes :role, role_options, :id, :title, legend: { text: "Roles" } %> + +
+ <%= form.hidden_field :support_case_id, value: @current_case.id %> + +
+ <%= form.submit I18n.t("support.case_contact_details.submit"), class: "govuk-button" %> + <%if !new_contact%> + <%= link_to 'Delete', support_case_additional_contact_path(@current_case, support_case_additional_contact), method: :delete, data: { confirm: 'Are you sure you want to delete this contact?' }, class: 'govuk-button govuk-button--secondary' %> + <%end%> + <%= link_to 'Cancel changes', support_case_additional_contacts_path(@current_case), class: 'govuk-button govuk-button--secondary' %> +
+<% end %> diff --git a/app/views/support/cases/additional_contacts/edit.html.erb b/app/views/support/cases/additional_contacts/edit.html.erb new file mode 100644 index 000000000..ee43dc29d --- /dev/null +++ b/app/views/support/cases/additional_contacts/edit.html.erb @@ -0,0 +1 @@ +<%= render 'form', support_case_additional_contact: @additional_contact %> \ No newline at end of file diff --git a/app/views/support/cases/additional_contacts/index.html.erb b/app/views/support/cases/additional_contacts/index.html.erb new file mode 100644 index 000000000..6d60c505e --- /dev/null +++ b/app/views/support/cases/additional_contacts/index.html.erb @@ -0,0 +1,32 @@ + + +

<%= I18n.t("support.case_contact_details.listing_heading") %>

+

<%= I18n.t("support.case_contact_details.listing_description") %>

+ + + + + + + + + + + + + + <% @additional_contacts&.each do |contact| %> +
+
+ + + + + + + + <% end %> + +
<%= I18n.t("support.case.label.contact_name") %><%= I18n.t("support.case.label.contact_email") %><%= I18n.t("support.case.label.contact_role") %>
<%= contact.first_name %> <%= contact.last_name %><%= contact.email %><%= contact.role.join(", ").titleize if contact.role %><%= link_to 'change', edit_support_case_additional_contact_path(@current_case, contact) %>
+ <%= link_to 'Add', new_support_case_additional_contact_path(@current_case), class: 'govuk-button' %> + \ No newline at end of file diff --git a/app/views/support/cases/additional_contacts/new.html.erb b/app/views/support/cases/additional_contacts/new.html.erb new file mode 100644 index 000000000..ee43dc29d --- /dev/null +++ b/app/views/support/cases/additional_contacts/new.html.erb @@ -0,0 +1 @@ +<%= render 'form', support_case_additional_contact: @additional_contact %> \ No newline at end of file diff --git a/app/views/support/cases/contact_details/edit.html.erb b/app/views/support/cases/contact_details/edit.html.erb index 56b1a6e2b..173cf8888 100644 --- a/app/views/support/cases/contact_details/edit.html.erb +++ b/app/views/support/cases/contact_details/edit.html.erb @@ -5,9 +5,41 @@ <%= form.govuk_text_field :first_name, autofocus: true, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.first_name") } %> <%= form.govuk_text_field :last_name, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.last_name") } %> - <%= form.govuk_text_field :phone, width: 'one-quarter', label: { text: I18n.t("support.case_contact_details.label.phone") } %> + <%= form.govuk_text_field :phone_number, width: 'one-quarter', label: { text: I18n.t("support.case_contact_details.label.phone") } %> <%= form.govuk_text_field :extension_number, width: 'one-quarter', label: { text: I18n.t("support.case_contact_details.label.extension_number") } %> <%= form.govuk_text_field :email, width: 'one-half', label: { text: I18n.t("support.case_contact_details.label.email") } %> + <% + +=begin%> + #below code is commented because it can be used later. It is a field for organisation selection. + <%= render "components/autocomplete", + container_id: "case-contacts-organisation-field", + label_text: I18n.t("support.case_additional_contact.organisation.header"), + label_class: "govuk_text_field", + element_id: "additional_contacts-autocomplete", + element_name: "organisation_name", + template_suggestion: "{{autocomplete_template}}", + value_field: :name, + default_value: @current_case&.organisation&.name, + hidden_fields: { + 'case_contact_details_form[organisation_id]' => :id, + 'case_contact_details_form[organisation_type]' => :source, + }, + query_url: support_establishments_path(format: :json, q: "{{QUERY}}") %> +<% +=end%> + Roles +
+ <%= form.govuk_check_box :lead_role, :true, checked: true, disabled: true, label: { text: "Lead" } %> +
+ +
+ <%= form.govuk_check_box :is_evaluator, :true, :false, multiple: false, checked: @current_case.is_evaluator, label: { text: "Evaluator" } %> +
+ + <%= form.submit I18n.t("support.case_contact_details.submit"), class: "govuk-button" %> + <%= link_to 'Cancel changes', support_case_path(@current_case), class: 'govuk-button govuk-button--secondary' %> <% end %> + diff --git a/app/views/support/cases/school_details/show.html.erb b/app/views/support/cases/school_details/show.html.erb index d6440de68..2551260f7 100644 --- a/app/views/support/cases/school_details/show.html.erb +++ b/app/views/support/cases/school_details/show.html.erb @@ -60,6 +60,20 @@ +
+
+ <%= I18n.t("support.case.label.case_additional_contact") %> +
+
+ <%= @current_case.case_additional_contacts.count %> +
+
+ <% unless @current_case.closed? %> + <%= link_to "Change", support_case_additional_contacts_path(@current_case), class: "govuk-link", target: "_top" %> + <% end %> +
+
+
<%= I18n.t("support.case.label.organisation_name") %> @@ -74,7 +88,6 @@ <% end %>
-
<%= I18n.t("support.case.label.organisation_type") %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 7524ff3a8..6581ce718 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -977,6 +977,8 @@ en: flag: Flag last_updated: Last updated level: Level + case_additional_contact: Additional contacts + contact_role: Contact role local_authority: short: LEA long: Local Education Authority @@ -1312,8 +1314,16 @@ en: warning: This will remove all existing beneficiary schools on the case. case_contact_details: flash: - updated: Contact details updated successfully + updated: Contact details successfully updated + success: Additional contact successfully created + update_success: Additional contact successfully updated. + already_a_contact: This email address is already linked to another contact on this case + validation_failed_message: Please enter contact email address + destroyed: Additional contact successfully removed header: Update contact details + listing_heading: Additional contacts + listing_description: Additional contacts for this case. These individuals will be included by default on all emails to the school and any automated emails. + description: Only add school contacts to the case. DO NOT add supplier contact details. label: email: Email address extension_number: Extension number @@ -1958,6 +1968,15 @@ en: header: attachment: Attachment description: Description + case_additional_contact: + role: + options: + lead: Lead + evaluator: Evaluator + header: Select all roles applicable to this individual + organisation: + header: Organisation (optional) + support_request: button: send: Send request diff --git a/config/locales/validation/support/en.yml b/config/locales/validation/support/en.yml index cfe9d0e7d..90ab86bb0 100644 --- a/config/locales/validation/support/en.yml +++ b/config/locales/validation/support/en.yml @@ -109,8 +109,8 @@ en: missing: Please enter contact last name for the case email: - missing: Please enter contact email for the case - invalid_format: Please enter a valid contact email for the case + missing: Please enter contact email address + invalid_format: Please enter a valid contact email address # Selecting an organisation organisation_id: diff --git a/config/routes.rb b/config/routes.rb index 9a4cab4e8..184acf1bb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -233,6 +233,7 @@ resource :on_hold, only: %i[create] resource :summary, only: %i[edit update] resources :contracts, only: %i[edit update] + resources :additional_contacts resource :email, only: %i[create] do scope module: :emails do resources :content, only: %i[show], param: :template diff --git a/db/migrate/20240712131114_create_support_case_additional_contacts.rb b/db/migrate/20240712131114_create_support_case_additional_contacts.rb new file mode 100644 index 000000000..fcd00f385 --- /dev/null +++ b/db/migrate/20240712131114_create_support_case_additional_contacts.rb @@ -0,0 +1,14 @@ +class CreateSupportCaseAdditionalContacts < ActiveRecord::Migration[7.1] + def change + create_table :support_case_additional_contacts, id: :uuid do |t| + t.references :support_case, foreign_key: { to_table: :support_cases }, type: :uuid, null: false + t.string :first_name + t.string :last_name + t.string :role, array: true, default: [] + t.string :phone_number + t.string :extension_number + t.string :email + t.timestamps + end + end +end diff --git a/db/migrate/20240722144936_add_organisation_id_to_case_additional_contacts.rb b/db/migrate/20240722144936_add_organisation_id_to_case_additional_contacts.rb new file mode 100644 index 000000000..17c31847a --- /dev/null +++ b/db/migrate/20240722144936_add_organisation_id_to_case_additional_contacts.rb @@ -0,0 +1,5 @@ +class AddOrganisationIdToCaseAdditionalContacts < ActiveRecord::Migration[7.1] + def change + add_column :support_case_additional_contacts, :organisation_id, :uuid + end +end diff --git a/db/migrate/20240818210639_add_is_evaluator_to_case.rb b/db/migrate/20240818210639_add_is_evaluator_to_case.rb new file mode 100644 index 000000000..22ebefa90 --- /dev/null +++ b/db/migrate/20240818210639_add_is_evaluator_to_case.rb @@ -0,0 +1,5 @@ +class AddIsEvaluatorToCase < ActiveRecord::Migration[7.1] + def change + add_column :support_cases, :is_evaluator, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 9daee06a7..8c37d15ae 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_08_02_141442) do +ActiveRecord::Schema[7.1].define(version: 2024_08_18_210639) do create_sequence "evaluation_refs" create_sequence "framework_refs" @@ -529,6 +529,20 @@ t.index ["support_tower_id"], name: "index_support_agents_on_support_tower_id" end + create_table "support_case_additional_contacts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "support_case_id", null: false + t.string "first_name" + t.string "last_name" + t.string "role", default: [], array: true + t.string "phone_number" + t.string "extension_number" + t.string "email" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "organisation_id" + t.index ["support_case_id"], name: "index_support_case_additional_contacts_on_support_case_id" + end + create_table "support_case_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "support_case_id" t.uuid "support_email_attachment_id" @@ -601,6 +615,7 @@ t.integer "discovery_method" t.string "discovery_method_other_text" t.string "project" + t.boolean "is_evaluator", default: false t.string "other_school_urns", default: [], array: true t.index ["category_id"], name: "index_support_cases_on_category_id" t.index ["existing_contract_id"], name: "index_support_cases_on_existing_contract_id" @@ -1021,6 +1036,7 @@ add_foreign_key "request_for_help_categories", "support_categories" add_foreign_key "short_text_answers", "steps", on_delete: :cascade add_foreign_key "support_agents", "support_towers" + add_foreign_key "support_case_additional_contacts", "support_cases" add_foreign_key "support_case_attachments", "support_cases" add_foreign_key "support_case_attachments", "support_email_attachments" add_foreign_key "support_case_organisations", "support_cases" diff --git a/spec/factories/support/case_additional_contact.rb b/spec/factories/support/case_additional_contact.rb new file mode 100644 index 000000000..0e6616db3 --- /dev/null +++ b/spec/factories/support/case_additional_contact.rb @@ -0,0 +1,10 @@ +FactoryBot.define do + factory :support_case_additional_contact, class: "Support::CaseAdditionalContact" do + email { "school@email.co.uk" } + first_name { "School" } + last_name { "Contact" } + role { "lead" } + + association :case, factory: :support_case + end +end diff --git a/spec/features/support/case_additional_contacts_spec.rb b/spec/features/support/case_additional_contacts_spec.rb new file mode 100644 index 000000000..73a370f42 --- /dev/null +++ b/spec/features/support/case_additional_contacts_spec.rb @@ -0,0 +1,55 @@ +require "rails_helper" + +RSpec.describe "Additional Contacts", type: :feature, js: true do + include_context "with an agent" + + let(:support_case) { create(:support_case) } + + before do + visit support_case_path(support_case) + end + + describe "Creating an additional contact" do + context "with valid attributes" do + before do + visit new_support_case_additional_contact_path(case_id: support_case.id) + + fill_in "First name", with: "John" + fill_in "Last name", with: "Doe" + fill_in "Email address", with: "john.doe@example.com" + fill_in "Phone number", with: "1234567890" + fill_in "Extension number", with: "123" + click_button "Save changes" # Adjust if the button text is different + end + + specify "creates a new contact and redirects to the additional contacts index" do + expect(page).to have_current_path(support_case_additional_contacts_path(case_id: support_case.id)) + expect(page).to have_content("Additional contact successfully created") + expect(page).to have_content("John Doe") + end + end + end + + describe "Updating an additional contact" do + let(:additional_contact) { create(:support_case_additional_contact, support_case_id: support_case.id) } + + context "with valid attributes" do + before do + visit edit_support_case_additional_contact_path(case_id: support_case.id, id: additional_contact.id) + + fill_in "First name", with: "Jane" + fill_in "Last name", with: "Smith" + fill_in "Email address", with: "jane.smith@example.com" + fill_in "Phone number", with: "0987654321" + fill_in "Extension number", with: "456" + click_button "Save changes" # Adjust if the button text is different + end + + specify "updates the contact and redirects to the additional contacts index" do + expect(page).to have_current_path(support_case_additional_contacts_path(case_id: support_case.id)) + expect(page).to have_content("Additional contact successfully updated") + expect(page).to have_content("Jane Smith") + end + end + end +end diff --git a/spec/features/support/case_organisation_details_spec.rb b/spec/features/support/case_organisation_details_spec.rb index 5108b0428..6ba0880de 100644 --- a/spec/features/support/case_organisation_details_spec.rb +++ b/spec/features/support/case_organisation_details_spec.rb @@ -40,8 +40,8 @@ it "displays the group name and type on the case page in CM" do within("#school-details") do - expect(all("dd.govuk-summary-list__value")[4]).to have_text "Group #1" - expect(all("dd.govuk-summary-list__value")[5]).to have_text "Multi-academy Trust" + expect(all("dd.govuk-summary-list__value")[5]).to have_text "Group #1" + expect(all("dd.govuk-summary-list__value")[6]).to have_text "Multi-academy Trust" end end end diff --git a/spec/features/support/case_school_details_spec.rb b/spec/features/support/case_school_details_spec.rb index 45cf4253e..e0bc9d0e6 100644 --- a/spec/features/support/case_school_details_spec.rb +++ b/spec/features/support/case_school_details_spec.rb @@ -33,9 +33,13 @@ expect(all("dd.govuk-summary-list__value")[3]).to have_text "john.smith@email.com" expect(all("dd.govuk-summary-list__actions")[3]).to have_link "Change" - expect(all("dt.govuk-summary-list__key")[4]).to have_text "Organisation name" - expect(all("dd.govuk-summary-list__value")[4]).to have_text "School #1" + expect(all("dt.govuk-summary-list__key")[4]).to have_text "Additional contacts" + expect(all("dd.govuk-summary-list__value")[4]).to have_text "0" expect(all("dd.govuk-summary-list__actions")[4]).to have_link "Change" + + expect(all("dt.govuk-summary-list__key")[5]).to have_text "Organisation name" + expect(all("dd.govuk-summary-list__value")[5]).to have_text "School #1" + expect(all("dd.govuk-summary-list__actions")[5]).to have_link "Change" end end end @@ -61,9 +65,13 @@ expect(all("dd.govuk-summary-list__value")[3]).to have_text "bill.jones@email.com" expect(all("dd.govuk-summary-list__actions")[3]).not_to have_link "Change" - expect(all("dt.govuk-summary-list__key")[4]).to have_text "Organisation name" - expect(all("dd.govuk-summary-list__value")[4]).to have_text "School #1" + expect(all("dt.govuk-summary-list__key")[4]).to have_text "Additional contacts" + expect(all("dd.govuk-summary-list__value")[4]).to have_text "0" expect(all("dd.govuk-summary-list__actions")[4]).not_to have_link "Change" + + expect(all("dt.govuk-summary-list__key")[5]).to have_text "Organisation name" + expect(all("dd.govuk-summary-list__value")[5]).to have_text "School #1" + expect(all("dd.govuk-summary-list__actions")[5]).not_to have_link "Change" end end end diff --git a/spec/models/support/case_spec.rb b/spec/models/support/case_spec.rb index 6eb1a7d1d..4b8d4f5f9 100644 --- a/spec/models/support/case_spec.rb +++ b/spec/models/support/case_spec.rb @@ -59,7 +59,7 @@ describe "#to_csv" do it "includes headers" do expect(described_class.to_csv).to eql( - "id,ref,category_id,request_text,support_level,status,state,created_at,updated_at,agent_id,first_name,last_name,email,phone_number,source,organisation_id,existing_contract_id,new_contract_id,procurement_id,savings_status,savings_estimate_method,savings_actual_method,savings_estimate,savings_actual,action_required,organisation_type,value,closure_reason,extension_number,other_category,other_query,procurement_amount,confidence_level,special_requirements,query_id,exit_survey_sent,detected_category_id,creation_source,user_selected_category,created_by_id,procurement_stage_id,initial_request_text,with_school,next_key_date,next_key_date_description,discovery_method,discovery_method_other_text,project,other_school_urns\n", + "id,ref,category_id,request_text,support_level,status,state,created_at,updated_at,agent_id,first_name,last_name,email,phone_number,source,organisation_id,existing_contract_id,new_contract_id,procurement_id,savings_status,savings_estimate_method,savings_actual_method,savings_estimate,savings_actual,action_required,organisation_type,value,closure_reason,extension_number,other_category,other_query,procurement_amount,confidence_level,special_requirements,query_id,exit_survey_sent,detected_category_id,creation_source,user_selected_category,created_by_id,procurement_stage_id,initial_request_text,with_school,next_key_date,next_key_date_description,discovery_method,discovery_method_other_text,project,is_evaluator,other_school_urns\n", ) end end