From 87793f24bda1a7aa9d14a6355a30041640d2ec38 Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Wed, 16 Nov 2022 16:50:26 +0000 Subject: [PATCH] Cldc 1671 deactivate scheme (#980) * feat: wip update scheme summary page * feat: wip deactivate scheme schemes page * feat: wip toggle active page * feat: wip set deactivation_date to a datetime (to be more specific times later_ * Change conditional question controller to accommodate all models * feat: add specific datetimes for deactivation * feat: correct date and add notice * feat: wip error behaviour * feat: wip errors * feat: wip errors refactoring * feat: wip errors more refactoring * refactor: linting * feat: add second error in correct position and wip date range error * feat: remove unneccessary db field * feat: change type values to strings * refactor: tidy up controller logic * refactor: use same structure as locations deactivation * feat: add general partially missing date input error * feat: add tests ("updates existing scheme with valid deactivation date and renders scheme page" still wip) and add new partially nil date behaviour to locations controller * feat: fix tests, add status tag behaviour and remove unnecessary nils * refactor: linting * refactor: erblinting * refactor: remove redundant line * refactor: respond to PR comments 1 * refactor: respond to PR comments 2 * refactor: respond to PR comments 3 * refactor: respond to PR comments 3 (locations side) * fix: remove @locations in location model * fix: remove @locations in location model * fix: update status names * feat: wip validation update * feat: add validation to model layer * feat: further separate scheme deactivation behaviour * test: update tests to new flow * feat: respond to pr comments and add dynamic success text * feat: duplicate behaviour schemes -> locations (+ tests) * refactor: linting * refactor: typo and remove unnecessary line for this PR * refactor: feature toggle simplification * Refactor locations and schemes controller actions - Rename confirmation partials to `deactivate_confirm.html.erb` so that they match the actions in which they belong to - Make all deactivation date comparision UTC time * feat: update deactivation_date validation and add tests * refactor: linting Co-authored-by: Kat Co-authored-by: James Rose --- app/controllers/locations_controller.rb | 82 ++++----- app/controllers/schemes_controller.rb | 64 ++++++- app/helpers/locations_helper.rb | 2 +- app/helpers/schemes_helper.rb | 26 +++ app/helpers/tag_helper.rb | 4 + app/models/form_handler.rb | 2 +- app/models/location.rb | 35 +++- app/models/organisation.rb | 2 +- app/models/scheme.rb | 68 ++++--- ...m.html.erb => deactivate_confirm.html.erb} | 9 +- app/views/locations/show.html.erb | 6 +- app/views/locations/toggle_active.html.erb | 6 +- app/views/organisations/show.html.erb | 2 +- app/views/schemes/deactivate_confirm.html.erb | 19 ++ app/views/schemes/show.html.erb | 12 +- app/views/schemes/toggle_active.html.erb | 35 ++++ config/initializers/feature_toggle.rb | 14 +- config/locales/en.yml | 22 ++- config/routes.rb | 9 +- ...163351_add_deactivation_date_to_schemes.rb | 5 + db/schema.rb | 7 +- spec/features/schemes_spec.rb | 2 +- spec/helpers/locations_helper_spec.rb | 6 +- spec/helpers/schemes_helper_spec.rb | 27 +++ spec/models/form_handler_spec.rb | 2 +- spec/models/location_spec.rb | 12 ++ spec/models/scheme_spec.rb | 44 +++++ spec/requests/locations_controller_spec.rb | 32 +++- .../requests/organisations_controller_spec.rb | 2 +- spec/requests/schemes_controller_spec.rb | 173 ++++++++++++++++++ 30 files changed, 611 insertions(+), 120 deletions(-) create mode 100644 app/helpers/schemes_helper.rb rename app/views/locations/{toggle_active_confirm.html.erb => deactivate_confirm.html.erb} (58%) create mode 100644 app/views/schemes/deactivate_confirm.html.erb create mode 100644 app/views/schemes/toggle_active.html.erb create mode 100644 db/migrate/20221110163351_add_deactivation_date_to_schemes.rb create mode 100644 spec/helpers/schemes_helper_spec.rb diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index 7955ec944..b25f951ea 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -20,22 +20,35 @@ class LocationsController < ApplicationController def show; end - def deactivate + def new_deactivation if params[:location].blank? render "toggle_active", locals: { action: "deactivate" } - elsif params[:location][:confirm].present? && params[:location][:deactivation_date].present? - confirm_deactivation else - deactivation_date_errors - if @location.errors.present? - @location.deactivation_date_type = params[:location][:deactivation_date_type] - render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity + @location.run_deactivation_validations! + @location.deactivation_date = deactivation_date + @location.deactivation_date_type = params[:location][:deactivation_date_type] + if @location.valid? + redirect_to scheme_location_deactivate_confirm_path(@location, deactivation_date: @location.deactivation_date, deactivation_date_type: @location.deactivation_date_type) else - render "toggle_active_confirm", locals: { action: "deactivate", deactivation_date: } + render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity end end end + def deactivate_confirm + @deactivation_date = params[:deactivation_date] + @deactivation_date_type = params[:deactivation_date_type] + end + + def deactivate + @location.run_deactivation_validations! + + if @location.update!(deactivation_date:) + flash[:notice] = deactivate_success_notice + end + redirect_to scheme_location_path(@scheme, @location) + end + def reactivate render "toggle_active", locals: { action: "reactivate" } end @@ -148,13 +161,13 @@ private end def authenticate_action! - if %w[new edit update create index edit_name edit_local_authority deactivate].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) + if %w[new edit update create index edit_name edit_local_authority new_deactivation deactivate_confirm deactivate].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) render_not_found and return end end def location_params - required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :add_another_location, :startdate, :mobility_type, :location_admin_district, :location_code).merge(scheme_id: @scheme.id) + required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :add_another_location, :startdate, :mobility_type, :location_admin_district, :location_code, :deactivation_date).merge(scheme_id: @scheme.id) required_params[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode] required_params end @@ -167,48 +180,29 @@ private location_params["location_admin_district"] != "Select an option" end - def confirm_deactivation - if @location.update(deactivation_date: params[:location][:deactivation_date]) - flash[:notice] = "#{@location.name || @location.postcode} has been deactivated" - end - redirect_to scheme_location_path(@scheme, @location) - end - - def deactivation_date_errors - if params[:location][:deactivation_date].blank? && params[:location][:deactivation_date_type].blank? - @location.errors.add(:deactivation_date_type, message: I18n.t("validations.location.deactivation_date.not_selected")) - end - - if params[:location][:deactivation_date_type] == "other" - day = params[:location]["deactivation_date(3i)"] - month = params[:location]["deactivation_date(2i)"] - year = params[:location]["deactivation_date(1i)"] - - collection_start_date = FormHandler.instance.current_collection_start_date - - if [day, month, year].any?(&:blank?) - { day:, month:, year: }.each do |period, value| - @location.errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation_date.not_entered", period: period.to_s)) if value.blank? - end - elsif !Date.valid_date?(year.to_i, month.to_i, day.to_i) - @location.errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation_date.invalid")) - elsif !Date.new(year.to_i, month.to_i, day.to_i).between?(collection_start_date, Date.new(2200, 1, 1)) - @location.errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation_date.out_of_range", date: collection_start_date.to_formatted_s(:govuk_date))) - end + def deactivate_success_notice + case @location.status + when :deactivated + "#{@location.name} has been deactivated" + when :deactivating_soon + "#{@location.name} will deactivate on #{@location.deactivation_date.to_formatted_s(:govuk_date)}" end end def deactivation_date - return if params[:location].blank? - - collection_start_date = FormHandler.instance.current_collection_start_date - return collection_start_date if params[:location][:deactivation_date_type] == "default" - return params[:location][:deactivation_date] if params[:location][:deactivation_date_type].blank? + if params[:location].blank? + return + elsif params[:location][:deactivation_date_type] == "default" + return FormHandler.instance.current_collection_start_date + elsif params[:location][:deactivation_date].present? + return params[:location][:deactivation_date] + end day = params[:location]["deactivation_date(3i)"] month = params[:location]["deactivation_date(2i)"] year = params[:location]["deactivation_date(1i)"] + return nil if [day, month, year].any?(&:blank?) - Date.new(year.to_i, month.to_i, day.to_i) + Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i) end end diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index 9a259e3a1..6766ffe85 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -21,6 +21,39 @@ class SchemesController < ApplicationController render_not_found and return unless @scheme end + def new_deactivation + if params[:scheme].blank? + render "toggle_active", locals: { action: "deactivate" } + else + @scheme.run_deactivation_validations = true + @scheme.deactivation_date = deactivation_date + @scheme.deactivation_date_type = params[:scheme][:deactivation_date_type] + if @scheme.valid? + redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme.deactivation_date, deactivation_date_type: @scheme.deactivation_date_type) + else + render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity + end + end + end + + def deactivate_confirm + @deactivation_date = params[:deactivation_date] + @deactivation_date_type = params[:deactivation_date_type] + end + + def deactivate + @scheme.run_deactivation_validations! + + if @scheme.update!(deactivation_date:) + flash[:notice] = deactivate_success_notice + end + redirect_to scheme_details_path(@scheme) + end + + def reactivate + render "toggle_active", locals: { action: "reactivate" } + end + def new @scheme = Scheme.new end @@ -206,7 +239,8 @@ private :support_type, :arrangement_type, :intended_stay, - :confirmed) + :confirmed, + :deactivation_date) if arrangement_type_changed_to_different_org?(required_params) required_params[:managing_organisation_id] = nil @@ -251,7 +285,7 @@ private def authenticate_scope! head :unauthorized and return unless current_user.data_coordinator? || current_user.support? - if %w[show locations primary_client_group confirm_secondary_client_group secondary_client_group support details check_answers edit_name].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) + if %w[show locations primary_client_group confirm_secondary_client_group secondary_client_group support details check_answers edit_name deactivate].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) render_not_found and return end end @@ -259,4 +293,30 @@ private def redirect_if_scheme_confirmed redirect_to @scheme if @scheme.confirmed? end + + def deactivate_success_notice + case @scheme.status + when :deactivated + "#{@scheme.service_name} has been deactivated" + when :deactivating_soon + "#{@scheme.service_name} will deactivate on #{@scheme.deactivation_date.to_formatted_s(:govuk_date)}" + end + end + + def deactivation_date + if params[:scheme].blank? + return + elsif params[:scheme][:deactivation_date_type] == "default" + return FormHandler.instance.current_collection_start_date + elsif params[:scheme][:deactivation_date].present? + return params[:scheme][:deactivation_date] + end + + day = params[:scheme]["deactivation_date(3i)"] + month = params[:scheme]["deactivation_date(2i)"] + year = params[:scheme]["deactivation_date(1i)"] + return nil if [day, month, year].any?(&:blank?) + + Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i) + end end diff --git a/app/helpers/locations_helper.rb b/app/helpers/locations_helper.rb index e21a4724e..2a02ebc94 100644 --- a/app/helpers/locations_helper.rb +++ b/app/helpers/locations_helper.rb @@ -23,7 +23,7 @@ module LocationsHelper resource.map { |key, _| OpenStruct.new(id: key, name: key.to_s.humanize) } end - def display_attributes(location) + def display_location_attributes(location) [ { name: "Postcode", value: location.postcode }, { name: "Local authority", value: location.location_admin_district }, diff --git a/app/helpers/schemes_helper.rb b/app/helpers/schemes_helper.rb new file mode 100644 index 000000000..0a042528b --- /dev/null +++ b/app/helpers/schemes_helper.rb @@ -0,0 +1,26 @@ +module SchemesHelper + def display_scheme_attributes(scheme) + base_attributes = [ + { name: "Scheme code", value: scheme.id_to_display }, + { name: "Name", value: scheme.service_name, edit: true }, + { name: "Confidential information", value: scheme.sensitive, edit: true }, + { name: "Type of scheme", value: scheme.scheme_type }, + { name: "Registered under Care Standards Act 2000", value: scheme.registered_under_care_act }, + { name: "Housing stock owned by", value: scheme.owning_organisation.name, edit: true }, + { name: "Support services provided by", value: scheme.arrangement_type }, + { name: "Organisation providing support", value: scheme.managing_organisation&.name }, + { name: "Primary client group", value: scheme.primary_client_group }, + { name: "Has another client group", value: scheme.has_other_client_group }, + { name: "Secondary client group", value: scheme.secondary_client_group }, + { name: "Level of support given", value: scheme.support_type }, + { name: "Intended length of stay", value: scheme.intended_stay }, + { name: "Availability", value: "Available from #{scheme.available_from.to_formatted_s(:govuk_date)}" }, + { name: "Status", value: scheme.status }, + ] + + if scheme.arrangement_type_same? + base_attributes.delete({ name: "Organisation providing support", value: scheme.managing_organisation&.name }) + end + base_attributes + end +end diff --git a/app/helpers/tag_helper.rb b/app/helpers/tag_helper.rb index 2ea23a86a..6682f97fd 100644 --- a/app/helpers/tag_helper.rb +++ b/app/helpers/tag_helper.rb @@ -7,7 +7,9 @@ module TagHelper in_progress: "In progress", completed: "Completed", active: "Active", + incomplete: "Incomplete", deactivating_soon: "Deactivating soon", + reactivating_soon: "Reactivating soon", deactivated: "Deactivated", }.freeze @@ -17,7 +19,9 @@ module TagHelper in_progress: "blue", completed: "green", active: "green", + incomplete: "red", deactivating_soon: "yellow", + reactivating_soon: "blue", deactivated: "grey", }.freeze diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb index c080e6e9b..61b981436 100644 --- a/app/models/form_handler.rb +++ b/app/models/form_handler.rb @@ -50,7 +50,7 @@ class FormHandler end def current_collection_start_date - Time.utc(current_collection_start_year, 4, 1) + Time.zone.local(current_collection_start_year, 4, 1) end def form_name_from_start_year(year, type) diff --git a/app/models/location.rb b/app/models/location.rb index ab1c3620a..2df620292 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -1,5 +1,6 @@ class Location < ApplicationRecord validate :validate_postcode + validate :deactivation_date_errors validates :units, :type_of_unit, :mobility_type, presence: true belongs_to :scheme has_many :lettings_logs, class_name: "LettingsLog" @@ -10,7 +11,7 @@ class Location < ApplicationRecord auto_strip_attributes :name - attr_accessor :add_another_location, :deactivation_date_type + attr_accessor :add_another_location, :deactivation_date_type, :run_deactivation_validations scope :search_by_postcode, ->(postcode) { where("REPLACE(postcode, ' ', '') ILIKE ?", "%#{postcode.delete(' ')}%") } scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") } @@ -375,7 +376,37 @@ class Location < ApplicationRecord def status return :active if deactivation_date.blank? return :deactivating_soon if Time.zone.now < deactivation_date - return :deactivated if Time.zone.now >= deactivation_date + + :deactivated + end + + def active? + status == :active + end + + def run_deactivation_validations! + @run_deactivation_validations = true + end + + def implicit_run_deactivation_validations + deactivation_date.present? || @run_deactivation_validations + end + + def deactivation_date_errors + return unless implicit_run_deactivation_validations + + if deactivation_date.blank? + if deactivation_date_type.blank? + errors.add(:deactivation_date_type, message: I18n.t("validations.location.deactivation_date.not_selected")) + elsif deactivation_date_type == "other" + errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation_date.invalid")) + end + else + collection_start_date = FormHandler.instance.current_collection_start_date + unless deactivation_date.between?(collection_start_date, Date.new(2200, 1, 1)) + errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation_date.out_of_range", date: collection_start_date.to_formatted_s(:govuk_date))) + end + end end private diff --git a/app/models/organisation.rb b/app/models/organisation.rb index e420ca9d8..cc0df4ef6 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -77,7 +77,7 @@ class Organisation < ApplicationRecord DISPLAY_PROVIDER_TYPE[provider_type.to_sym] end - def display_attributes + def display_organisation_attributes [ { name: "Name", value: name, editable: true }, { name: "Address", value: address_string, editable: true }, diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 83899f494..5de804c58 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -18,9 +18,12 @@ class Scheme < ApplicationRecord } validate :validate_confirmed + validate :deactivation_date_errors auto_strip_attributes :service_name + attr_accessor :deactivation_date_type, :run_deactivation_validations + SENSITIVE = { No: 0, Yes: 1, @@ -153,29 +156,6 @@ class Scheme < ApplicationRecord ] end - def display_attributes - base_attributes = [ - { name: "Scheme code", value: id_to_display }, - { name: "Name", value: service_name, edit: true }, - { name: "Confidential information", value: sensitive, edit: true }, - { name: "Type of scheme", value: scheme_type }, - { name: "Registered under Care Standards Act 2000", value: registered_under_care_act }, - { name: "Housing stock owned by", value: owning_organisation.name, edit: true }, - { name: "Support services provided by", value: arrangement_type }, - { name: "Organisation providing support", value: managing_organisation&.name }, - { name: "Primary client group", value: primary_client_group }, - { name: "Has another client group", value: has_other_client_group }, - { name: "Secondary client group", value: secondary_client_group }, - { name: "Level of support given", value: support_type }, - { name: "Intended length of stay", value: intended_stay }, - ] - - if arrangement_type_same? - base_attributes.delete({ name: "Organisation providing support", value: managing_organisation&.name }) - end - base_attributes - end - def synonyms locations.map(&:postcode).join(",") end @@ -219,7 +199,7 @@ class Scheme < ApplicationRecord end def validate_confirmed - required_attributes = attribute_names - %w[id created_at updated_at old_id old_visible_id confirmed end_date sensitive secondary_client_group total_units has_other_client_group] + required_attributes = attribute_names - %w[id created_at updated_at old_id old_visible_id confirmed end_date sensitive secondary_client_group total_units has_other_client_group deactivation_date deactivation_date_type] if confirmed == true required_attributes.any? do |attribute| @@ -230,4 +210,44 @@ class Scheme < ApplicationRecord end end end + + def available_from + created_at + end + + def status + return :active if deactivation_date.blank? + return :deactivating_soon if Time.zone.now < deactivation_date + + :deactivated + end + + def active? + status == :active + end + + def run_deactivation_validations! + @run_deactivation_validations = true + end + + def implicit_run_deactivation_validations + deactivation_date.present? || @run_deactivation_validations + end + + def deactivation_date_errors + return unless implicit_run_deactivation_validations + + if deactivation_date.blank? + if deactivation_date_type.blank? + errors.add(:deactivation_date_type, message: I18n.t("validations.scheme.deactivation_date.not_selected")) + elsif deactivation_date_type == "other" + errors.add(:deactivation_date, message: I18n.t("validations.scheme.deactivation_date.invalid")) + end + else + collection_start_date = FormHandler.instance.current_collection_start_date + unless deactivation_date.between?(collection_start_date, Date.new(2200, 1, 1)) + errors.add(:deactivation_date, message: I18n.t("validations.scheme.deactivation_date.out_of_range", date: collection_start_date.to_formatted_s(:govuk_date))) + end + end + end end diff --git a/app/views/locations/toggle_active_confirm.html.erb b/app/views/locations/deactivate_confirm.html.erb similarity index 58% rename from app/views/locations/toggle_active_confirm.html.erb rename to app/views/locations/deactivate_confirm.html.erb index 452d66e48..e3f1ae175 100644 --- a/app/views/locations/toggle_active_confirm.html.erb +++ b/app/views/locations/deactivate_confirm.html.erb @@ -4,13 +4,14 @@ <% end %>

<%= @location.postcode %> - <%= "This change will affect #{@location.lettings_logs.count} logs" %> + This change will affect <%= @location.lettings_logs.count %> logs

<%= govuk_warning_text text: I18n.t("warnings.location.deactivation.review_logs") %> <%= f.hidden_field :confirm, value: true %> - <%= f.hidden_field :deactivation_date, value: deactivation_date %> -
+ <%= f.hidden_field :deactivation_date, value: @deactivation_date %> + <%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %> +
<%= f.govuk_submit "Deactivate this location" %> - <%= govuk_button_link_to "Cancel", scheme_location_path(scheme_id: @scheme, id: @location.id), html: { method: :get }, secondary: true %> + <%= govuk_button_link_to "Cancel", scheme_location_path(@scheme, @location), html: { method: :get }, secondary: true %>
<% end %> diff --git a/app/views/locations/show.html.erb b/app/views/locations/show.html.erb index ccc0163c2..52607d582 100644 --- a/app/views/locations/show.html.erb +++ b/app/views/locations/show.html.erb @@ -13,7 +13,7 @@
<%= govuk_summary_list do |summary_list| %> - <% display_attributes(@location).each do |attr| %> + <% display_location_attributes(@location).each do |attr| %> <%= summary_list.row do |row| %> <% row.key { attr[:name] } %> <% row.value { attr[:name].eql?("Status") ? status_tag(attr[:value]) : details_html(attr) } %> @@ -24,8 +24,8 @@
<% if FeatureToggle.location_toggle_enabled? %> - <% if @location.status == :active %> - <%= govuk_button_link_to "Deactivate this location", scheme_location_deactivate_path(scheme_id: @scheme.id, location_id: @location.id), warning: true %> + <% if @location.active? %> + <%= govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(scheme_id: @scheme.id, location_id: @location.id), warning: true %> <% else %> <%= govuk_button_link_to "Reactivate this location", scheme_location_reactivate_path(scheme_id: @scheme.id, location_id: @location.id) %> <% end %> diff --git a/app/views/locations/toggle_active.html.erb b/app/views/locations/toggle_active.html.erb index 96cda6daa..6d2f4a9ba 100644 --- a/app/views/locations/toggle_active.html.erb +++ b/app/views/locations/toggle_active.html.erb @@ -4,11 +4,11 @@ <% content_for :before_content do %> <%= govuk_back_link( text: "Back", - href: scheme_location_path(scheme_id: @location.scheme.id, id: @location.id), + href: scheme_location_path(@location.scheme, @location), ) %> <% end %> -<%= form_with model: @location, url: scheme_location_deactivate_path(scheme_id: @location.scheme.id, location_id: @location.id), method: "patch", local: true do |f| %> +<%= form_with model: @location, url: scheme_location_new_deactivation_path(scheme_id: @location.scheme.id, location_id: @location.id), method: "patch", local: true do |f| %>
<% collection_start_date = FormHandler.instance.current_collection_start_date %> @@ -28,7 +28,7 @@ **basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "location") do %> <%= f.govuk_date_field :deactivation_date, legend: { text: "Date", size: "m" }, - hint: { text: "For example, 27 3 2008" }, + hint: { text: "For example, 27 3 2022" }, width: 20 %> <% end %> <% end %> diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb index 5cd8b64e0..bbe9ae67a 100644 --- a/app/views/organisations/show.html.erb +++ b/app/views/organisations/show.html.erb @@ -14,7 +14,7 @@
<%= govuk_summary_list do |summary_list| %> - <% @organisation.display_attributes.each do |attr| %> + <% @organisation.display_organisation_attributes.each do |attr| %> <% if can_edit_org?(current_user) && attr[:editable] %> <%= summary_list.row do |row| %> <% row.key { attr[:name].to_s.humanize } %> diff --git a/app/views/schemes/deactivate_confirm.html.erb b/app/views/schemes/deactivate_confirm.html.erb new file mode 100644 index 000000000..45f7d4341 --- /dev/null +++ b/app/views/schemes/deactivate_confirm.html.erb @@ -0,0 +1,19 @@ +<% title = "Deactivate #{@scheme.service_name}" %> +<% content_for :title, title %> +<%= form_with model: @scheme, url: scheme_deactivate_path(@scheme), method: "patch", local: true do |f| %> + <% content_for :before_content do %> + <%= govuk_back_link(href: :back) %> + <% end %> +

+ <%= @scheme.service_name %> + This change will affect <%= @scheme.lettings_logs.count %> logs +

+ <%= govuk_warning_text text: I18n.t("warnings.scheme.deactivation.review_logs") %> + <%= f.hidden_field :confirm, value: true %> + <%= f.hidden_field :deactivation_date, value: @deactivation_date %> + <%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %> +
+ <%= f.govuk_submit "Deactivate this scheme" %> + <%= govuk_button_link_to "Cancel", scheme_details_path(@scheme), html: { method: :get }, secondary: true %> +
+<% end %> diff --git a/app/views/schemes/show.html.erb b/app/views/schemes/show.html.erb index 75cb533f7..2c01c06f1 100644 --- a/app/views/schemes/show.html.erb +++ b/app/views/schemes/show.html.erb @@ -15,12 +15,20 @@

Scheme

<%= govuk_summary_list do |summary_list| %> - <% @scheme.display_attributes.each do |attr| %> + <% display_scheme_attributes(@scheme).each do |attr| %> <% next if current_user.data_coordinator? && attr[:name] == ("Housing stock owned by") %> <%= summary_list.row do |row| %> <% row.key { attr[:name].eql?("Registered under Care Standards Act 2000") ? "Registered under Care Standards Act 2000" : attr[:name].to_s.humanize } %> - <% row.value { details_html(attr) } %> + <% row.value { attr[:name].eql?("Status") ? status_tag(attr[:value]) : details_html(attr) } %> <% row.action(text: "Change", href: scheme_edit_name_path(scheme_id: @scheme.id)) if attr[:edit] %> <% end %> <% end %> <% end %> + +<% if FeatureToggle.scheme_toggle_enabled? %> + <% if @scheme.active? %> + <%= govuk_button_link_to "Deactivate this scheme", scheme_new_deactivation_path(@scheme), warning: true %> + <% else %> + <%= govuk_button_link_to "Reactivate this scheme", scheme_reactivate_path(@scheme) %> + <% end %> +<% end %> diff --git a/app/views/schemes/toggle_active.html.erb b/app/views/schemes/toggle_active.html.erb new file mode 100644 index 000000000..11dd2f276 --- /dev/null +++ b/app/views/schemes/toggle_active.html.erb @@ -0,0 +1,35 @@ +<% title = "#{action.humanize} #{@scheme.service_name}" %> +<% content_for :title, title %> +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: scheme_details_path(@scheme), + ) %> +<% end %> +<%= form_with model: @scheme, url: scheme_new_deactivation_path(@scheme), method: "patch", local: true do |f| %> +
+
+ <% collection_start_date = FormHandler.instance.current_collection_start_date %> + <%= f.govuk_error_summary %> + <%= f.govuk_radio_buttons_fieldset :deactivation_date_type, + legend: { text: I18n.t("questions.scheme.deactivation.apply_from") }, + caption: { text: title }, + hint: { text: I18n.t("hints.scheme.deactivation", date: collection_start_date.to_formatted_s(:govuk_date)) } do %> + <%= govuk_warning_text text: I18n.t("warnings.scheme.deactivation.existing_logs") %> + <%= f.govuk_radio_button :deactivation_date_type, + "default", + label: { text: "From the start of the current collection period (#{collection_start_date.to_formatted_s(:govuk_date)})" } %> + <%= f.govuk_radio_button :deactivation_date_type, + "other", + label: { text: "For tenancies starting after a certain date" }, + **basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "scheme") do %> + <%= f.govuk_date_field :deactivation_date, + legend: { text: "Date", size: "m" }, + hint: { text: "For example, 27 3 2022" }, + width: 20 %> + <% end %> + <% end %> + <%= f.govuk_submit "Continue" %> +
+
+<% end %> diff --git a/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb index 1a4b8a862..7cd75ddd3 100644 --- a/config/initializers/feature_toggle.rb +++ b/config/initializers/feature_toggle.rb @@ -4,21 +4,19 @@ class FeatureToggle end def self.sales_log_enabled? - return true unless Rails.env.production? - - false + !Rails.env.production? end def self.managing_owning_enabled? - return true unless Rails.env.production? + !Rails.env.production? + end - false + def self.scheme_toggle_enabled? + !Rails.env.production? end def self.location_toggle_enabled? - return true unless Rails.env.production? - - false + !Rails.env.production? end def self.managing_for_other_user_enabled? diff --git a/config/locales/en.yml b/config/locales/en.yml index 3c4808696..a1c18330a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -312,11 +312,16 @@ en: declaration: missing: "You must show the DLUHC privacy notice to the tenant before you can submit this log." + scheme: + deactivation_date: + not_selected: "Select one of the options" + invalid: "Enter a valid day, month and year" + out_of_range: "The date must be on or after the %{date}" + location: deactivation_date: not_selected: "Select one of the options" - not_entered: "Enter a %{period}" - invalid: "Enter a valid date" + invalid: "Enter a valid day, month and year" out_of_range: "The date must be on or after the %{date}" soft_validations: @@ -371,6 +376,9 @@ en: mobility_type: "What are the mobility standards for the majority of units in this location?" deactivation: apply_from: "When should this change apply?" + scheme: + deactivation: + apply_from: "When should this change apply?" descriptions: location: mobility_type: @@ -384,12 +392,18 @@ en: name: "This is how you refer to this location within your organisation" units: "A unit can be a bedroom in a shared house or flat, or a house with 4 bedrooms. Do not include bedrooms used for wardens, managers, volunteers or sleep-in staff." deactivation: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed." - + scheme: + deactivation: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed." + warnings: location: - deactivation: + deactivation: existing_logs: "It will not be possible to add logs with this location if their tenancy start date is on or after the date you enter. Any existing logs may be affected." review_logs: "Your data providers will need to review these logs and answer a few questions again. We’ll email each log creator with a list of logs that need updating." + scheme: + deactivation: + existing_logs: "It will not be possible to add logs with this scheme if their tenancy start date is on or after the date you enter. Any existing logs may be affected." + review_logs: "Your data providers will need to review these logs and answer a few questions again. We’ll email each log creator with a list of logs that need updating." test: one_argument: "This is based on the tenant’s work situation: %{ecstat1}" diff --git a/config/routes.rb b/config/routes.rb index 8bd78d6e6..f90f70534 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -49,12 +49,19 @@ Rails.application.routes.draw do get "check-answers", to: "schemes#check_answers" get "edit-name", to: "schemes#edit_name" get "support-services-provider", to: "schemes#support_services_provider" + get "new-deactivation", to: "schemes#new_deactivation" + get "deactivate-confirm", to: "schemes#deactivate_confirm" + get "reactivate", to: "schemes#reactivate" + patch "new-deactivation", to: "schemes#new_deactivation" + patch "deactivate", to: "schemes#deactivate" resources :locations do get "edit-name", to: "locations#edit_name" get "edit-local-authority", to: "locations#edit_local_authority" - get "deactivate", to: "locations#deactivate" + get "new-deactivation", to: "locations#new_deactivation" + get "deactivate-confirm", to: "locations#deactivate_confirm" get "reactivate", to: "locations#reactivate" + patch "new-deactivation", to: "locations#new_deactivation" patch "deactivate", to: "locations#deactivate" end end diff --git a/db/migrate/20221110163351_add_deactivation_date_to_schemes.rb b/db/migrate/20221110163351_add_deactivation_date_to_schemes.rb new file mode 100644 index 000000000..6d717268f --- /dev/null +++ b/db/migrate/20221110163351_add_deactivation_date_to_schemes.rb @@ -0,0 +1,5 @@ +class AddDeactivationDateToSchemes < ActiveRecord::Migration[7.0] + def change + add_column :schemes, :deactivation_date, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 0f2ad0025..1ff8f157c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -364,15 +364,15 @@ ActiveRecord::Schema[7.0].define(version: 2022_11_11_102656) do t.integer "la_known" t.integer "income1" t.integer "income1nk" + t.integer "details_known_2" + t.integer "details_known_3" + t.integer "details_known_4" t.integer "age4" t.integer "age4_known" t.integer "age5" t.integer "age5_known" t.integer "age6" t.integer "age6_known" - t.integer "details_known_2" - t.integer "details_known_3" - t.integer "details_known_4" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" @@ -398,6 +398,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_11_11_102656) do t.string "old_visible_id" t.integer "total_units" t.boolean "confirmed" + t.datetime "deactivation_date" t.index ["managing_organisation_id"], name: "index_schemes_on_managing_organisation_id" t.index ["owning_organisation_id"], name: "index_schemes_on_owning_organisation_id" end diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index 48ab31acc..1500a728c 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -779,7 +779,7 @@ RSpec.describe "Schemes scheme Features" do it "allows to deactivate a location" do click_link("Deactivate this location") - expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{location.id}/deactivate") + expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation") end context "when I press the back button" do diff --git a/spec/helpers/locations_helper_spec.rb b/spec/helpers/locations_helper_spec.rb index f2a5a67a5..2adfab35f 100644 --- a/spec/helpers/locations_helper_spec.rb +++ b/spec/helpers/locations_helper_spec.rb @@ -47,7 +47,7 @@ RSpec.describe LocationsHelper do end end - describe "display_attributes" do + describe "display_location_attributes" do let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 8, 8)) } it "returns correct display attributes" do @@ -63,12 +63,12 @@ RSpec.describe LocationsHelper do { name: "Status", value: :active }, ] - expect(display_attributes(location)).to eq(attributes) + expect(display_location_attributes(location)).to eq(attributes) end it "displays created_at as availability date if startdate is not present" do location.update!(startdate: nil) - availability_attribute = display_attributes(location).find { |x| x[:name] == "Availability" }[:value] + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] expect(availability_attribute).to eq("Available from #{location.created_at.to_formatted_s(:govuk_date)}") end diff --git a/spec/helpers/schemes_helper_spec.rb b/spec/helpers/schemes_helper_spec.rb new file mode 100644 index 000000000..46dfbd7c2 --- /dev/null +++ b/spec/helpers/schemes_helper_spec.rb @@ -0,0 +1,27 @@ +require "rails_helper" + +RSpec.describe SchemesHelper do + describe "display_scheme_attributes" do + let!(:scheme) { FactoryBot.create(:scheme, created_at: Time.zone.local(2022, 8, 8)) } + + it "returns correct display attributes" do + attributes = [ + { name: "Scheme code", value: scheme.id_to_display }, + { name: "Name", value: scheme.service_name, edit: true }, + { name: "Confidential information", value: scheme.sensitive, edit: true }, + { name: "Type of scheme", value: scheme.scheme_type }, + { name: "Registered under Care Standards Act 2000", value: scheme.registered_under_care_act }, + { name: "Housing stock owned by", value: scheme.owning_organisation.name, edit: true }, + { name: "Support services provided by", value: scheme.arrangement_type }, + { name: "Primary client group", value: scheme.primary_client_group }, + { name: "Has another client group", value: scheme.has_other_client_group }, + { name: "Secondary client group", value: scheme.secondary_client_group }, + { name: "Level of support given", value: scheme.support_type }, + { name: "Intended length of stay", value: scheme.intended_stay }, + { name: "Availability", value: "Available from 8 August 2022" }, + { name: "Status", value: :active }, + ] + expect(display_scheme_attributes(scheme)).to eq(attributes) + end + end +end diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index e4056c6c1..e0ef853ae 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -120,7 +120,7 @@ RSpec.describe FormHandler do end it "returns the correct current start date" do - expect(form_handler.current_collection_start_date).to eq(Time.utc(2022, 4, 1)) + expect(form_handler.current_collection_start_date).to eq(Time.zone.local(2022, 4, 1)) end end diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb index 8f9f452bc..069bb21d7 100644 --- a/spec/models/location_spec.rb +++ b/spec/models/location_spec.rb @@ -121,26 +121,38 @@ RSpec.describe Location, type: :model do it "returns active if the location is not deactivated" do location.deactivation_date = nil + location.deactivation_date_type = nil location.save! expect(location.status).to eq(:active) end it "returns deactivating soon if deactivation_date is in the future" do location.deactivation_date = Time.zone.local(2022, 8, 8) + location.deactivation_date_type = "other" location.save! expect(location.status).to eq(:deactivating_soon) end it "returns deactivated if deactivation_date is in the past" do location.deactivation_date = Time.zone.local(2022, 4, 8) + location.deactivation_date_type = "other" location.save! expect(location.status).to eq(:deactivated) end it "returns deactivated if deactivation_date is today" do location.deactivation_date = Time.zone.local(2022, 6, 7) + location.deactivation_date_type = "other" location.save! expect(location.status).to eq(:deactivated) end end + + describe "with deactivation_date (but no deactivation_date_type)" do + let(:location) { FactoryBot.create(:location, deactivation_date: Date.new(2022, 4, 1)) } + + it "is valid" do + expect(location).to be_valid + end + end end diff --git a/spec/models/scheme_spec.rb b/spec/models/scheme_spec.rb index 9d17d888c..b9e8fd886 100644 --- a/spec/models/scheme_spec.rb +++ b/spec/models/scheme_spec.rb @@ -91,4 +91,48 @@ RSpec.describe Scheme, type: :model do end end end + + describe "status" do + let(:scheme) { FactoryBot.build(:scheme) } + + before do + Timecop.freeze(2022, 6, 7) + end + + it "returns active if the scheme is not deactivated" do + scheme.deactivation_date = nil + scheme.deactivation_date_type = nil + scheme.save! + expect(scheme.status).to eq(:active) + end + + it "returns deactivating soon if deactivation_date is in the future" do + scheme.deactivation_date = Time.zone.local(2022, 8, 8) + scheme.deactivation_date_type = "other" + scheme.save! + expect(scheme.status).to eq(:deactivating_soon) + end + + it "returns deactivated if deactivation_date is in the past" do + scheme.deactivation_date = Time.zone.local(2022, 4, 8) + scheme.deactivation_date_type = "other" + scheme.save! + expect(scheme.status).to eq(:deactivated) + end + + it "returns deactivated if deactivation_date is today" do + scheme.deactivation_date = Time.zone.local(2022, 6, 7) + scheme.deactivation_date_type = "other" + scheme.save! + expect(scheme.status).to eq(:deactivated) + end + end + + describe "with deactivation_date (but no deactivation_date_type)" do + let(:scheme) { FactoryBot.create(:scheme, deactivation_date: Date.new(2022, 4, 1)) } + + it "is valid" do + expect(scheme).to be_valid + end + end end diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb index a666b6495..2aca9bd93 100644 --- a/spec/requests/locations_controller_spec.rb +++ b/spec/requests/locations_controller_spec.rb @@ -1245,29 +1245,37 @@ RSpec.describe LocationsController, type: :request do before do Timecop.freeze(Time.utc(2022, 10, 10)) sign_in user - patch "/schemes/#{scheme.id}/locations/#{location.id}/deactivate", params: + patch "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation", params: end context "with default date" do - let(:params) { { location: { deactivation_date_type: "default" } } } + let(:params) { { location: { deactivation_date_type: "default", deactivation_date: } } } - it "renders the confirmation page" do + it "redirects to the confirmation page" do + follow_redirect! expect(response).to have_http_status(:ok) expect(page).to have_content("This change will affect #{location.lettings_logs.count} logs") end end context "with other date" do - let(:params) { { location: { deactivation_date: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "10", "deactivation_date(1i)": "2022" } } } + let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "10", "deactivation_date(1i)": "2022" } } } - it "renders the confirmation page" do + it "redirects to the confirmation page" do + follow_redirect! expect(response).to have_http_status(:ok) expect(page).to have_content("This change will affect #{location.lettings_logs.count} logs") end end context "when confirming deactivation" do - let(:params) { { location: { deactivation_date:, confirm: true } } } + let(:params) { { location: { deactivation_date:, confirm: true, deactivation_date_type: "other" } } } + + before do + Timecop.freeze(Time.utc(2022, 10, 10)) + sign_in user + patch "/schemes/#{scheme.id}/locations/#{location.id}/deactivate", params: + end it "updates existing location with valid deactivation date and renders location page" do follow_redirect! @@ -1310,7 +1318,7 @@ RSpec.describe LocationsController, type: :request do it "displays page with an error message" do expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.location.deactivation_date.not_entered", period: "day")) + expect(page).to have_content(I18n.t("validations.location.deactivation_date.invalid")) end end @@ -1319,7 +1327,7 @@ RSpec.describe LocationsController, type: :request do it "displays page with an error message" do expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.location.deactivation_date.not_entered", period: "month")) + expect(page).to have_content(I18n.t("validations.location.deactivation_date.invalid")) end end @@ -1328,7 +1336,7 @@ RSpec.describe LocationsController, type: :request do it "displays page with an error message" do expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.location.deactivation_date.not_entered", period: "year")) + expect(page).to have_content(I18n.t("validations.location.deactivation_date.invalid")) end end end @@ -1365,21 +1373,24 @@ RSpec.describe LocationsController, type: :request do Timecop.freeze(Time.utc(2022, 10, 10)) sign_in user location.deactivation_date = deactivation_date + location.deactivation_date_type = deactivation_date_type location.save! get "/schemes/#{scheme.id}/locations/#{location.id}" end context "with active location" do let(:deactivation_date) { nil } + let(:deactivation_date_type) { nil } it "renders deactivate this location" do expect(response).to have_http_status(:ok) - expect(page).to have_link("Deactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/deactivate") + expect(page).to have_link("Deactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation") end end context "with deactivated location" do let(:deactivation_date) { Time.utc(2022, 10, 9) } + let(:deactivation_date_type) { "other" } it "renders reactivate this location" do expect(response).to have_http_status(:ok) @@ -1389,6 +1400,7 @@ RSpec.describe LocationsController, type: :request do context "with location that's deactivating soon" do let(:deactivation_date) { Time.utc(2022, 10, 12) } + let(:deactivation_date_type) { "other" } it "renders reactivate this location" do expect(response).to have_http_status(:ok) diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index d3d22513a..9b0e934f6 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -59,7 +59,7 @@ RSpec.describe OrganisationsController, type: :request do expect(page).to have_field("search", type: "search") end - it "has hidden accebility field with description" do + it "has hidden accessibility field with description" do expected_field = "

Supported housing schemes

" expect(CGI.unescape_html(response.body)).to include(expected_field) end diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index a5c0b6e4f..5ad18663e 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -242,6 +242,50 @@ RSpec.describe SchemesController, type: :request do expect(response).to have_http_status(:not_found) end end + + context "when looking at scheme details" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + + before do + Timecop.freeze(Time.utc(2022, 10, 10)) + sign_in user + scheme.deactivation_date = deactivation_date + scheme.deactivation_date_type = deactivation_date_type + scheme.save! + get "/schemes/#{scheme.id}" + end + + context "with active scheme" do + let(:deactivation_date) { nil } + let(:deactivation_date_type) { nil } + + it "renders deactivate this scheme" do + expect(response).to have_http_status(:ok) + expect(page).to have_link("Deactivate this scheme", href: "/schemes/#{scheme.id}/new-deactivation") + end + end + + context "with deactivated scheme" do + let(:deactivation_date) { Time.utc(2022, 10, 9) } + let(:deactivation_date_type) { "other" } + + it "renders reactivate this scheme" do + expect(response).to have_http_status(:ok) + expect(page).to have_link("Reactivate this scheme", href: "/schemes/#{scheme.id}/reactivate") + end + end + + context "with scheme that's deactivating soon" do + let(:deactivation_date) { Time.utc(2022, 10, 12) } + let(:deactivation_date_type) { "other" } + + it "renders reactivate this scheme" do + expect(response).to have_http_status(:ok) + expect(page).to have_link("Reactivate this scheme", href: "/schemes/#{scheme.id}/reactivate") + end + end + end end context "when signed in as a support user" do @@ -1698,4 +1742,133 @@ RSpec.describe SchemesController, type: :request do end end end + + describe "#deactivate" do + context "when not signed in" do + it "redirects to the sign in page" do + patch "/schemes/1/new-deactivation" + expect(response).to redirect_to("/account/sign-in") + end + end + + context "when signed in as a data provider" do + let(:user) { FactoryBot.create(:user) } + + before do + sign_in user + patch "/schemes/1/new-deactivation" + end + + it "returns 401 unauthorized" do + request + expect(response).to have_http_status(:unauthorized) + end + end + + context "when signed in as a data coordinator" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let(:startdate) { Time.utc(2021, 1, 2) } + let(:deactivation_date) { Time.utc(2022, 10, 10) } + + before do + Timecop.freeze(Time.utc(2022, 10, 10)) + sign_in user + patch "/schemes/#{scheme.id}/new-deactivation", params: + end + + context "with default date" do + let(:params) { { scheme: { deactivation_date_type: "default", deactivation_date: } } } + + it "redirects to the confirmation page" do + follow_redirect! + expect(response).to have_http_status(:ok) + expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} logs") + end + end + + context "with other date" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "10", "deactivation_date(1i)": "2022" } } } + + it "redirects to the confirmation page" do + follow_redirect! + expect(response).to have_http_status(:ok) + expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} logs") + end + end + + context "when confirming deactivation" do + let(:params) { { scheme: { deactivation_date:, confirm: true, deactivation_date_type: "other" } } } + + before do + Timecop.freeze(Time.utc(2022, 10, 10)) + sign_in user + patch "/schemes/#{scheme.id}/deactivate", params: + end + + it "updates existing scheme with valid deactivation date and renders scheme page" do + follow_redirect! + follow_redirect! + expect(response).to have_http_status(:ok) + expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") + scheme.reload + expect(scheme.deactivation_date).to eq(deactivation_date) + end + end + + context "when the date is not selected" do + let(:params) { { scheme: { "deactivation_date": "" } } } + + it "displays the new page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.not_selected")) + end + end + + context "when invalid date is entered" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "44", "deactivation_date(1i)": "2022" } } } + + it "displays the new page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.invalid")) + end + end + + context "when the date is entered is before the beginning of current collection window" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "4", "deactivation_date(1i)": "2020" } } } + + it "displays the new page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.out_of_range", date: "1 April 2022")) + end + end + + context "when the day is not entered" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "", "deactivation_date(2i)": "2", "deactivation_date(1i)": "2022" } } } + + it "displays page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.invalid")) + end + end + + context "when the month is not entered" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "2", "deactivation_date(2i)": "", "deactivation_date(1i)": "2022" } } } + + it "displays page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.invalid")) + end + end + + context "when the year is not entered" do + let(:params) { { scheme: { deactivation_date_type: "other", "deactivation_date(3i)": "2", "deactivation_date(2i)": "2", "deactivation_date(1i)": "" } } } + + it "displays page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.scheme.deactivation_date.invalid")) + end + end + end + end end