From 11bb9c887cdd6725785354b86eeb498e28790f50 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Tue, 22 Nov 2022 09:29:31 +0000 Subject: [PATCH] Cldc 1670 reactivate locations (#1007) * route deactivated scheme to reactivation page * Render correct reactivate question content * refactor into a helper * display successful reactivation banner for default date * Save reactivation date * Add reactivation errors * lint and fix url in tests * make toggle translations generic * Add reactivation status * Reuse date validation messages * Show deactivate this location when location is reactivating soon * Display correct confirmation banner * Add validation for reactivation date before deactivation date * Improve availability label * Use current collection start date if created at is later than that * Update paths * Fix controller and don't display the previous day if location availability start afterwards * refactor availability label * Filter out active periods * lint * Refactor active_period method into the model * Allow deactivations and reactivations from available from date instead of start of the collection date * Prevent deactivations during deactivated periods * lint * typo * Remove active periods that last 1 day (because they get deactivated on the same day) * Move the active_periods into helper * extract remove_overlapping_and_empty_periods into a separate method * Remove nested deactivation periods * Make deactivate/reactvate location form use location_deactivation_period model * refactor toggle date methods * extract shared condition * update validations * refactor validations * Update schemes deactivation form to use dectivation model * Refactor * lint * remove redundant location_id and update scheme controller * update active_periods --- app/controllers/locations_controller.rb | 68 ++++-- app/controllers/schemes_controller.rb | 38 +-- app/helpers/locations_helper.rb | 42 +++- app/helpers/toggle_active_location_helper.rb | 17 ++ app/models/location.rb | 41 +--- app/models/location_deactivation_period.rb | 46 ++++ app/models/scheme.rb | 28 --- app/models/scheme_deactivation_period.rb | 21 ++ .../locations/deactivate_confirm.html.erb | 4 +- app/views/locations/show.html.erb | 6 +- app/views/locations/toggle_active.html.erb | 20 +- app/views/schemes/deactivate_confirm.html.erb | 2 +- app/views/schemes/toggle_active.html.erb | 2 +- config/locales/en.yml | 14 +- config/routes.rb | 2 + .../factories/location_deactivation_period.rb | 1 + spec/features/schemes_spec.rb | 42 ++++ spec/helpers/locations_helper_spec.rb | 183 ++++++++++++++- spec/helpers/schemes_helper_spec.rb | 5 +- spec/models/location_spec.rb | 41 ++-- spec/models/scheme_spec.rb | 34 ++- spec/requests/locations_controller_spec.rb | 220 ++++++++++++++++-- spec/requests/schemes_controller_spec.rb | 22 +- 23 files changed, 699 insertions(+), 200 deletions(-) create mode 100644 app/helpers/toggle_active_location_helper.rb diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index b9132305f..766501260 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -21,14 +21,16 @@ class LocationsController < ApplicationController def show; end def new_deactivation - if params[:location].blank? + @location_deactivation_period = LocationDeactivationPeriod.new + + if params[:location_deactivation_period].blank? render "toggle_active", locals: { action: "deactivate" } else - @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) + @location_deactivation_period.deactivation_date = toggle_date("deactivation_date") + @location_deactivation_period.deactivation_date_type = params[:location_deactivation_period][:deactivation_date_type] + @location_deactivation_period.location = @location + if @location_deactivation_period.valid? + redirect_to scheme_location_deactivate_confirm_path(@location, deactivation_date: @location_deactivation_period.deactivation_date, deactivation_date_type: @location_deactivation_period.deactivation_date_type) else render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity end @@ -41,18 +43,31 @@ class LocationsController < ApplicationController end def deactivate - @location.run_deactivation_validations! - - if @location.location_deactivation_periods.create!(deactivation_date:) && update_affected_logs + if @location.location_deactivation_periods.create!(deactivation_date: params[:deactivation_date]) && reset_location_and_scheme_for_logs! flash[:notice] = deactivate_success_notice end redirect_to scheme_location_path(@scheme, @location) end - def reactivate + def new_reactivation + @location_deactivation_period = LocationDeactivationPeriod.deactivations_without_reactivation.first render "toggle_active", locals: { action: "reactivate" } end + def reactivate + @location_deactivation_period = LocationDeactivationPeriod.deactivations_without_reactivation.first + + @location_deactivation_period.reactivation_date = toggle_date("reactivation_date") + @location_deactivation_period.reactivation_date_type = params[:location_deactivation_period][:reactivation_date_type] + + if @location_deactivation_period.update(reactivation_date: toggle_date("reactivation_date")) + flash[:notice] = reactivate_success_notice + redirect_to scheme_location_path(@scheme, @location) + else + render "toggle_active", locals: { action: "reactivate" }, status: :unprocessable_entity + end + end + def create if date_params_missing?(location_params) || valid_date_params?(location_params) @location = Location.new(location_params) @@ -167,7 +182,7 @@ private 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, :deactivation_date).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).merge(scheme_id: @scheme.id) required_params[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode] required_params end @@ -185,26 +200,35 @@ private when :deactivated "#{@location.name} has been deactivated" when :deactivating_soon - "#{@location.name} will deactivate on #{deactivation_date.to_time.to_formatted_s(:govuk_date)}" + "#{@location.name} will deactivate on #{params[:deactivation_date].to_time.to_formatted_s(:govuk_date)}" + end + end + + def reactivate_success_notice + case @location.status + when :active + "#{@location.name} has been reactivated" + when :reactivating_soon + "#{@location.name} will reactivate on #{toggle_date('reactivation_date').to_time.to_formatted_s(:govuk_date)}" end end - def update_affected_logs - @location.lettings_logs.filter_by_before_startdate(deactivation_date.to_time).update!(location: nil, scheme: nil) + def reset_location_and_scheme_for_logs! + @location.lettings_logs.filter_by_before_startdate(params[:deactivation_date].to_time).update!(location: nil, scheme: nil) end - def deactivation_date - if params[:location].blank? + def toggle_date(key) + if params[:location_deactivation_period].blank? return - elsif params[:location][:deactivation_date_type] == "default" + elsif params[:location_deactivation_period]["#{key}_type".to_sym] == "default" return FormHandler.instance.current_collection_start_date - elsif params[:location][:deactivation_date].present? - return params[:location][:deactivation_date] + elsif params[:location_deactivation_period][key.to_sym].present? + return params[:location_deactivation_period][key.to_sym] end - day = params[:location]["deactivation_date(3i)"] - month = params[:location]["deactivation_date(2i)"] - year = params[:location]["deactivation_date(1i)"] + day = params[:location_deactivation_period]["#{key}(3i)"] + month = params[:location_deactivation_period]["#{key}(2i)"] + year = params[:location_deactivation_period]["#{key}(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) diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index 208394942..1a06d9d41 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -22,14 +22,16 @@ class SchemesController < ApplicationController end def new_deactivation - if params[:scheme].blank? + @scheme_deactivation_period = SchemeDeactivationPeriod.new + + if params[:scheme_deactivation_period].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) + @scheme_deactivation_period.deactivation_date = deactivation_date + @scheme_deactivation_period.deactivation_date_type = params[:scheme_deactivation_period][:deactivation_date_type] + @scheme_deactivation_period.scheme = @scheme + if @scheme_deactivation_period.validate + redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme_deactivation_period.deactivation_date, deactivation_date_type: @scheme_deactivation_period.deactivation_date_type) else render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity end @@ -42,9 +44,7 @@ class SchemesController < ApplicationController end def deactivate - @scheme.run_deactivation_validations! - - if @scheme.scheme_deactivation_periods.create!(deactivation_date:) && update_affected_logs + if @scheme.scheme_deactivation_periods.create!(deactivation_date: params[:deactivation_date]) && reset_location_and_scheme_for_logs! flash[:notice] = deactivate_success_notice end redirect_to scheme_details_path(@scheme) @@ -299,28 +299,28 @@ private when :deactivated "#{@scheme.service_name} has been deactivated" when :deactivating_soon - "#{@scheme.service_name} will deactivate on #{deactivation_date.to_time.to_formatted_s(:govuk_date)}" + "#{@scheme.service_name} will deactivate on #{params[:deactivation_date].to_time.to_formatted_s(:govuk_date)}" end end def deactivation_date - if params[:scheme].blank? + if params[:scheme_deactivation_period].blank? return - elsif params[:scheme][:deactivation_date_type] == "default" + elsif params[:scheme_deactivation_period][:deactivation_date_type] == "default" return FormHandler.instance.current_collection_start_date - elsif params[:scheme][:deactivation_date].present? - return params[:scheme][:deactivation_date] + elsif params[:scheme_deactivation_period][:deactivation_date].present? + return params[:scheme_deactivation_period][:deactivation_date] end - day = params[:scheme]["deactivation_date(3i)"] - month = params[:scheme]["deactivation_date(2i)"] - year = params[:scheme]["deactivation_date(1i)"] + day = params[:scheme_deactivation_period]["deactivation_date(3i)"] + month = params[:scheme_deactivation_period]["deactivation_date(2i)"] + year = params[:scheme_deactivation_period]["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 - def update_affected_logs - @scheme.lettings_logs.filter_by_before_startdate(deactivation_date.to_time).update!(location: nil, scheme: nil) + def reset_location_and_scheme_for_logs! + @scheme.lettings_logs.filter_by_before_startdate(params[:deactivation_date].to_time).update!(location: nil, scheme: nil) end end diff --git a/app/helpers/locations_helper.rb b/app/helpers/locations_helper.rb index 791775a59..ca04826ba 100644 --- a/app/helpers/locations_helper.rb +++ b/app/helpers/locations_helper.rb @@ -42,12 +42,44 @@ module LocationsHelper base_attributes end + ActivePeriod = Struct.new(:from, :to) + def active_periods(location) + periods = [ActivePeriod.new(location.available_from, nil)] + + sorted_deactivation_periods = remove_nested_periods(location.location_deactivation_periods.sort_by(&:deactivation_date)) + sorted_deactivation_periods.each do |deactivation| + periods.last.to = deactivation.deactivation_date + periods << ActivePeriod.new(deactivation.reactivation_date, nil) + end + + remove_overlapping_and_empty_periods(periods) + end + def location_availability(location) - availability = "Active from #{location.available_from.to_formatted_s(:govuk_date)}" - location.location_deactivation_periods.each do |deactivation| - availability << " to #{(deactivation.deactivation_date - 1.day).to_formatted_s(:govuk_date)}\nDeactivated on #{deactivation.deactivation_date.to_formatted_s(:govuk_date)}" - availability << "\nActive from #{deactivation.reactivation_date.to_formatted_s(:govuk_date)}" if deactivation.reactivation_date.present? + availability = "" + active_periods(location).each do |period| + if period.from.present? + availability << "\nActive from #{period.from.to_formatted_s(:govuk_date)}" + availability << " to #{(period.to - 1.day).to_formatted_s(:govuk_date)}\nDeactivated on #{period.to.to_formatted_s(:govuk_date)}" if period.to.present? + end end - availability + availability.strip + end + +private + + def remove_overlapping_and_empty_periods(periods) + periods.select { |period| period.from.present? && (period.to.nil? || period.from < period.to) } + end + + def remove_nested_periods(periods) + periods.select { |inner_period| periods.none? { |outer_period| is_nested?(inner_period, outer_period) } } + end + + def is_nested?(inner, outer) + return false if inner == outer + return false if [inner.deactivation_date, inner.reactivation_date, outer.deactivation_date, outer.reactivation_date].any?(&:blank?) + + [inner.deactivation_date, inner.reactivation_date].all? { |date| date.between?(outer.deactivation_date, outer.reactivation_date) } end end diff --git a/app/helpers/toggle_active_location_helper.rb b/app/helpers/toggle_active_location_helper.rb new file mode 100644 index 000000000..1fdda6416 --- /dev/null +++ b/app/helpers/toggle_active_location_helper.rb @@ -0,0 +1,17 @@ +module ToggleActiveLocationHelper + def toggle_location_form_path(action, location) + if action == "deactivate" + scheme_location_new_deactivation_path(location.scheme, location) + else + scheme_location_reactivate_path(location.scheme, location) + end + end + + def date_type_question(action) + action == "deactivate" ? :deactivation_date_type : :reactivation_date_type + end + + def date_question(action) + action == "deactivate" ? :deactivation_date : :reactivation_date + end +end diff --git a/app/models/location.rb b/app/models/location.rb index 25fc05fd9..c05a2351b 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -1,6 +1,5 @@ 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" @@ -12,7 +11,7 @@ class Location < ApplicationRecord auto_strip_attributes :name - attr_accessor :add_another_location, :deactivation_date_type, :deactivation_date, :run_deactivation_validations + attr_accessor :add_another_location scope :search_by_postcode, ->(postcode) { where("REPLACE(postcode, ' ', '') ILIKE ?", "%#{postcode.delete(' ')}%") } scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") } @@ -371,44 +370,26 @@ class Location < ApplicationRecord end def available_from - startdate || created_at + startdate || [created_at, FormHandler.instance.current_collection_start_date].min end def status - recent_deactivation = location_deactivation_periods.deactivations_without_reactivation.first - return :active if recent_deactivation.blank? - return :deactivating_soon if Time.zone.now < recent_deactivation.deactivation_date + open_deactivation = location_deactivation_periods.deactivations_without_reactivation.first + recent_deactivation = location_deactivation_periods.order("created_at").last - :deactivated + return :deactivated if open_deactivation&.deactivation_date.present? && Time.zone.now >= open_deactivation.deactivation_date + return :deactivating_soon if open_deactivation&.deactivation_date.present? && Time.zone.now < open_deactivation.deactivation_date + return :reactivating_soon if recent_deactivation&.reactivation_date.present? && Time.zone.now < recent_deactivation.reactivation_date + + :active 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, Time.zone.local(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 + def reactivating_soon? + status == :reactivating_soon end private diff --git a/app/models/location_deactivation_period.rb b/app/models/location_deactivation_period.rb index b8579f0bf..dcf347d24 100644 --- a/app/models/location_deactivation_period.rb +++ b/app/models/location_deactivation_period.rb @@ -1,3 +1,49 @@ +class LocationDeactivationPeriodValidator < ActiveModel::Validator + def validate(record) + location = record.location + recent_deactivation = location.location_deactivation_periods.deactivations_without_reactivation.first + if recent_deactivation.present? + validate_reactivation(record, recent_deactivation, location) + else + validate_deactivation(record, location) + end + end + + def validate_reactivation(record, recent_deactivation, location) + if record.reactivation_date.blank? + if record.reactivation_date_type.blank? + record.errors.add(:reactivation_date_type, message: I18n.t("validations.location.toggle_date.not_selected")) + elsif record.reactivation_date_type == "other" + record.errors.add(:reactivation_date, message: I18n.t("validations.location.toggle_date.invalid")) + end + elsif !record.reactivation_date.between?(location.available_from, Time.zone.local(2200, 1, 1)) + record.errors.add(:reactivation_date, message: I18n.t("validations.location.toggle_date.out_of_range", date: location.available_from.to_formatted_s(:govuk_date))) + elsif record.reactivation_date < recent_deactivation.deactivation_date + record.errors.add(:reactivation_date, message: I18n.t("validations.location.reactivation.before_deactivation", date: recent_deactivation.deactivation_date.to_formatted_s(:govuk_date))) + end + end + + def validate_deactivation(record, location) + if record.deactivation_date.blank? + if record.deactivation_date_type.blank? + record.errors.add(:deactivation_date_type, message: I18n.t("validations.location.toggle_date.not_selected")) + elsif record.deactivation_date_type == "other" + record.errors.add(:deactivation_date, message: I18n.t("validations.location.toggle_date.invalid")) + end + elsif location.location_deactivation_periods.any? { |period| period.reactivation_date.present? && record.deactivation_date.between?(period.deactivation_date, period.reactivation_date - 1.day) } + record.errors.add(:deactivation_date, message: I18n.t("validations.location.deactivation.during_deactivated_period")) + else + unless record.deactivation_date.between?(location.available_from, Time.zone.local(2200, 1, 1)) + record.errors.add(:deactivation_date, message: I18n.t("validations.location.toggle_date.out_of_range", date: location.available_from.to_formatted_s(:govuk_date))) + end + end + end +end + class LocationDeactivationPeriod < ApplicationRecord + validates_with LocationDeactivationPeriodValidator + belongs_to :location + attr_accessor :deactivation_date_type, :reactivation_date_type + scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) } end diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 3dfe1ff55..8197a147c 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -19,12 +19,9 @@ class Scheme < ApplicationRecord } validate :validate_confirmed - validate :deactivation_date_errors auto_strip_attributes :service_name - attr_accessor :deactivation_date_type, :deactivation_date, :run_deactivation_validations - SENSITIVE = { No: 0, Yes: 1, @@ -227,29 +224,4 @@ class Scheme < ApplicationRecord 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, Time.zone.local(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/models/scheme_deactivation_period.rb b/app/models/scheme_deactivation_period.rb index 5caba5c7a..f83a68e62 100644 --- a/app/models/scheme_deactivation_period.rb +++ b/app/models/scheme_deactivation_period.rb @@ -1,3 +1,24 @@ +class SchemeDeactivationPeriodValidator < ActiveModel::Validator + def validate(record) + if record.deactivation_date.blank? + if record.deactivation_date_type.blank? + record.errors.add(:deactivation_date_type, message: I18n.t("validations.scheme.deactivation_date.not_selected")) + elsif record.deactivation_date_type == "other" + record.errors.add(:deactivation_date, message: I18n.t("validations.scheme.deactivation_date.invalid")) + end + else + collection_start_date = FormHandler.instance.current_collection_start_date + unless record.deactivation_date.between?(collection_start_date, Time.zone.local(2200, 1, 1)) + record.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 + class SchemeDeactivationPeriod < ApplicationRecord + validates_with SchemeDeactivationPeriodValidator + belongs_to :scheme + attr_accessor :deactivation_date_type, :reactivation_date_type + scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) } end diff --git a/app/views/locations/deactivate_confirm.html.erb b/app/views/locations/deactivate_confirm.html.erb index e3f1ae175..47b7bbf60 100644 --- a/app/views/locations/deactivate_confirm.html.erb +++ b/app/views/locations/deactivate_confirm.html.erb @@ -1,4 +1,4 @@ -<%= form_with model: @location, url: scheme_location_deactivate_path(@location), method: "patch", local: true do |f| %> +<%= form_with model: @location_deactivation_period, url: scheme_location_deactivate_path(@location), method: "patch", local: true do |f| %> <% content_for :before_content do %> <%= govuk_back_link(href: :back) %> <% end %> @@ -6,7 +6,7 @@ <%= @location.postcode %> This change will affect <%= @location.lettings_logs.count %> logs - <%= govuk_warning_text text: I18n.t("warnings.location.deactivation.review_logs") %> + <%= govuk_warning_text text: I18n.t("warnings.location.deactivate.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 %> diff --git a/app/views/locations/show.html.erb b/app/views/locations/show.html.erb index 52607d582..5ed049d08 100644 --- a/app/views/locations/show.html.erb +++ b/app/views/locations/show.html.erb @@ -24,9 +24,9 @@ <% if FeatureToggle.location_toggle_enabled? %> - <% 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 %> + <% if @location.active? || @location.reactivating_soon? %> + <%= govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(@scheme, @location), warning: true %> <% else %> - <%= govuk_button_link_to "Reactivate this location", scheme_location_reactivate_path(scheme_id: @scheme.id, location_id: @location.id) %> + <%= govuk_button_link_to "Reactivate this location", scheme_location_new_reactivation_path(@scheme, @location) %> <% end %> <% end %> diff --git a/app/views/locations/toggle_active.html.erb b/app/views/locations/toggle_active.html.erb index 6d2f4a9ba..909b335e0 100644 --- a/app/views/locations/toggle_active.html.erb +++ b/app/views/locations/toggle_active.html.erb @@ -1,4 +1,4 @@ -<% title = "#{action.humanize} #{@location.postcode}" %> +<% title = "#{action.humanize} #{@location.name}" %> <% content_for :title, title %> <% content_for :before_content do %> @@ -8,25 +8,25 @@ ) %> <% end %> -<%= 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| %> +<%= form_with model: @location_deactivation_period, url: toggle_location_form_path(action, @location), 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.location.deactivation.apply_from") }, - caption: { text: "Deactivate #{@location.postcode}" }, - hint: { text: I18n.t("hints.location.deactivation", date: collection_start_date.to_formatted_s(:govuk_date)) } do %> - <%= govuk_warning_text text: I18n.t("warnings.location.deactivation.existing_logs") %> - <%= f.govuk_radio_button :deactivation_date_type, + <%= f.govuk_radio_buttons_fieldset date_type_question(action), + legend: { text: I18n.t("questions.location.toggle_active.apply_from") }, + caption: { text: title }, + hint: { text: I18n.t("hints.location.toggle_active", date: collection_start_date.to_formatted_s(:govuk_date)) } do %> + <%= govuk_warning_text text: I18n.t("warnings.location.#{action}.existing_logs") %> + <%= f.govuk_radio_button date_type_question(action), "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, + <%= f.govuk_radio_button date_type_question(action), "other", label: { text: "For tenancies starting after a certain date" }, **basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "location") do %> - <%= f.govuk_date_field :deactivation_date, + <%= f.govuk_date_field date_question(action), legend: { text: "Date", size: "m" }, hint: { text: "For example, 27 3 2022" }, width: 20 %> diff --git a/app/views/schemes/deactivate_confirm.html.erb b/app/views/schemes/deactivate_confirm.html.erb index 45f7d4341..0cfd454c8 100644 --- a/app/views/schemes/deactivate_confirm.html.erb +++ b/app/views/schemes/deactivate_confirm.html.erb @@ -1,6 +1,6 @@ <% title = "Deactivate #{@scheme.service_name}" %> <% content_for :title, title %> -<%= form_with model: @scheme, url: scheme_deactivate_path(@scheme), method: "patch", local: true do |f| %> +<%= form_with model: @scheme_deactivation_period, url: scheme_deactivate_path(@scheme), method: "patch", local: true do |f| %> <% content_for :before_content do %> <%= govuk_back_link(href: :back) %> <% end %> diff --git a/app/views/schemes/toggle_active.html.erb b/app/views/schemes/toggle_active.html.erb index 11dd2f276..fbb3ebc5f 100644 --- a/app/views/schemes/toggle_active.html.erb +++ b/app/views/schemes/toggle_active.html.erb @@ -6,7 +6,7 @@ href: scheme_details_path(@scheme), ) %> <% end %> -<%= form_with model: @scheme, url: scheme_new_deactivation_path(@scheme), method: "patch", local: true do |f| %> +<%= form_with model: @scheme_deactivation_period, url: scheme_new_deactivation_path(@scheme), method: "patch", local: true do |f| %>
<% collection_start_date = FormHandler.instance.current_collection_start_date %> diff --git a/config/locales/en.yml b/config/locales/en.yml index a1c18330a..f839ccf7e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -319,10 +319,14 @@ en: out_of_range: "The date must be on or after the %{date}" location: - deactivation_date: + toggle_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}" + reactivation: + before_deactivation: "This location was deactivated on %{date}\nThe reactivation date must be on or after deactivation date" + deactivation: + during_deactivated_period: "The location is already deactivated during this date, please enter a different date" soft_validations: net_income: @@ -374,7 +378,7 @@ en: startdate: "When did the first property in this location become available under this scheme? (optional)" add_another_location: "Do you want to add another location?" mobility_type: "What are the mobility standards for the majority of units in this location?" - deactivation: + toggle_active: apply_from: "When should this change apply?" scheme: deactivation: @@ -391,15 +395,17 @@ en: postcode: "For example, SW1P 4DF." 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." + toggle_active: "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: + deactivate: 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." + reactivate: + existing_logs: "You’ll be able to add logs with this location if their tenancy start date is on or after the date you enter." 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." diff --git a/config/routes.rb b/config/routes.rb index f90f70534..98d7151b1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -61,8 +61,10 @@ Rails.application.routes.draw do get "new-deactivation", to: "locations#new_deactivation" get "deactivate-confirm", to: "locations#deactivate_confirm" get "reactivate", to: "locations#reactivate" + get "new-reactivation", to: "locations#new_reactivation" patch "new-deactivation", to: "locations#new_deactivation" patch "deactivate", to: "locations#deactivate" + patch "reactivate", to: "locations#reactivate" end end diff --git a/spec/factories/location_deactivation_period.rb b/spec/factories/location_deactivation_period.rb index 6a3ab70c3..7d2355ca2 100644 --- a/spec/factories/location_deactivation_period.rb +++ b/spec/factories/location_deactivation_period.rb @@ -1,5 +1,6 @@ FactoryBot.define do factory :location_deactivation_period do + deactivation_date { Time.zone.local(2022, 4, 1) } reactivation_date { nil } end end diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index 67660b8ad..797b718af 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -693,8 +693,10 @@ RSpec.describe "Schemes scheme Features" do context "when I click to see individual scheme" do let(:scheme) { schemes.first } let!(:location) { FactoryBot.create(:location, startdate: Time.zone.local(2022, 4, 4), scheme:) } + let!(:deactivated_location) { FactoryBot.create(:location, startdate: Time.zone.local(2022, 4, 4), scheme:) } before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location: deactivated_location) click_link(scheme.service_name) end @@ -752,6 +754,46 @@ RSpec.describe "Schemes scheme Features" do expect(page).to have_current_path("/schemes/#{scheme.id}/locations") end + context "when location is incative" do + context "and I click to view the location" do + before do + click_link(deactivated_location.postcode) + end + + it "displays details about the selected location" do + expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{deactivated_location.id}") + expect(page).to have_content(deactivated_location.postcode) + expect(page).to have_content(deactivated_location.location_admin_district) + expect(page).to have_content(deactivated_location.name) + expect(page).to have_content(deactivated_location.units) + expect(page).to have_content(deactivated_location.type_of_unit) + expect(page).to have_content(deactivated_location.mobility_type) + expect(page).to have_content(deactivated_location.location_code) + expect(page).to have_content("Active from 4 April 2022 to 3 June 2022 Deactivated on 4 June 2022") + expect(page).to have_content("Deactivated") + end + + it "allows to reactivate a location" do + click_link("Reactivate this location") + expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{deactivated_location.id}/new-reactivation") + expect(page).to have_content("Reactivate #{deactivated_location.name}") + expect(page).to have_content("You’ll be able to add logs with this location if their tenancy start date is on or after the date you enter.") + expect(page).to have_content("If the date is before 1 April 2022, select ‘From the start of the current collection period’ because the previous period has now closed.") + end + + context "when I press the back button" do + before do + click_link "Back" + end + + it "I see location details" do + expect(page).to have_content scheme.locations.first.id + expect(page).to have_current_path("/schemes/#{scheme.id}/locations") + end + end + end + end + context "when I click to change location name" do before do click_link(location.postcode) diff --git a/spec/helpers/locations_helper_spec.rb b/spec/helpers/locations_helper_spec.rb index e0d2abfea..bccacba3c 100644 --- a/spec/helpers/locations_helper_spec.rb +++ b/spec/helpers/locations_helper_spec.rb @@ -47,8 +47,94 @@ RSpec.describe LocationsHelper do end end + describe "Active periods" do + let(:location) { FactoryBot.create(:location, startdate: nil) } + + before do + Timecop.freeze(2022, 10, 10) + end + + after do + Timecop.unfreeze + end + + it "returns one active period without to date" do + expect(active_periods(location).count).to eq(1) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: nil) + end + + it "ignores reactivations that were deactivated on the same day" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location:) + location.reload + + expect(active_periods(location).count).to eq(1) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5)) + end + + it "returns sequential non reactivated active periods" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), location:) + location.reload + + expect(active_periods(location).count).to eq(2) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6)) + end + + it "returns sequential reactivated active periods" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:) + location.reload + expect(active_periods(location).count).to eq(3) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6)) + expect(active_periods(location).third).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil) + end + + it "returns non sequential non reactivated active periods" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: nil, location:) + location.reload + + expect(active_periods(location).count).to eq(2) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil) + end + + it "returns non sequential reactivated active periods" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 7, 6), reactivation_date: Time.zone.local(2022, 8, 5), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 4), location:) + location.reload + expect(active_periods(location).count).to eq(3) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 5, 5)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 6, 4), to: Time.zone.local(2022, 7, 6)) + expect(active_periods(location).third).to have_attributes(from: Time.zone.local(2022, 8, 5), to: nil) + end + + it "returns correct active periods when reactivation happends during a deactivated period" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 11, 11), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 6), reactivation_date: Time.zone.local(2022, 7, 7), location:) + location.reload + + expect(active_periods(location).count).to eq(2) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 4, 6)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 11, 11), to: nil) + end + + it "returns correct active periods when a full deactivation period happens during another deactivation period" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 11), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 6), reactivation_date: Time.zone.local(2022, 7, 7), location:) + location.reload + + expect(active_periods(location).count).to eq(2) + expect(active_periods(location).first).to have_attributes(from: Time.zone.local(2022, 4, 1), to: Time.zone.local(2022, 4, 6)) + expect(active_periods(location).second).to have_attributes(from: Time.zone.local(2022, 7, 7), to: nil) + end + end + describe "display_location_attributes" do - let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 8, 8)) } + let(:location) { FactoryBot.build(:location, created_at: Time.zone.local(2022, 3, 16), startdate: Time.zone.local(2022, 4, 1)) } it "returns correct display attributes" do attributes = [ @@ -59,7 +145,7 @@ RSpec.describe LocationsHelper do { name: "Common type of unit", value: location.type_of_unit }, { name: "Mobility type", value: location.mobility_type }, { name: "Code", value: location.location_code }, - { name: "Availability", value: "Active from 8 August 2022" }, + { name: "Availability", value: "Active from 1 April 2022" }, { name: "Status", value: :active }, ] @@ -67,25 +153,110 @@ RSpec.describe LocationsHelper do end context "when viewing availability" do - context "with are no deactivations" do + context "with no deactivations" do it "displays created_at as availability date if startdate is not present" do location.update!(startdate: nil) availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] expect(availability_attribute).to eq("Active from #{location.created_at.to_formatted_s(:govuk_date)}") end + + it "displays current collection start date as availability date if created_at is later than collection start date" do + location.update!(startdate: nil, created_at: Time.zone.local(2022, 4, 16)) + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022") + end end context "with previous deactivations" do + context "and all reactivated deactivations" do + before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: Time.zone.local(2022, 9, 28), location:) + location.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022\nActive from 28 September 2022") + end + end + + context "and non reactivated deactivation" do + before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, location:) + location.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022") + end + end + end + + context "with out of order deactivations" do + context "and all reactivated deactivations" do + before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: Time.zone.local(2022, 6, 18), location:) + location.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 18 June 2022 to 23 September 2022\nDeactivated on 24 September 2022\nActive from 28 September 2022") + end + end + + context "and one non reactivated deactivation" do + before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, location:) + location.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022") + end + end + end + + context "with multiple out of order deactivations" do + context "and one non reactivated deactivation" do + before do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 24), reactivation_date: Time.zone.local(2022, 10, 28), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, location:) + location.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022 to 23 October 2022\nDeactivated on 24 October 2022\nActive from 28 October 2022") + end + end + end + + context "with intersecting deactivations" do before do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1)) - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 10), reactivation_date: Time.zone.local(2022, 12, 1), location:) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 11, 11), reactivation_date: Time.zone.local(2022, 12, 11), location:) + location.reload end it "displays the timeline of availability" do availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 8 August 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022") + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 October 2022\nDeactivated on 10 October 2022\nActive from 11 December 2022") end end end diff --git a/spec/helpers/schemes_helper_spec.rb b/spec/helpers/schemes_helper_spec.rb index 1924a6cc5..9db3639d9 100644 --- a/spec/helpers/schemes_helper_spec.rb +++ b/spec/helpers/schemes_helper_spec.rb @@ -35,8 +35,9 @@ RSpec.describe SchemesHelper do context "with previous deactivations" do before do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1)) - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, scheme:) + scheme.reload end it "displays the timeline of availability" do diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb index 01185249a..64a4855da 100644 --- a/spec/models/location_spec.rb +++ b/spec/models/location_spec.rb @@ -113,7 +113,7 @@ RSpec.describe Location, type: :model do end describe "status" do - let(:location) { FactoryBot.build(:location) } + let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 4, 1)) } before do Timecop.freeze(2022, 6, 7) @@ -129,27 +129,34 @@ RSpec.describe Location, type: :model do end it "returns deactivating soon if deactivation_date is in the future" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), location:) location.save! expect(location.status).to eq(:deactivating_soon) end it "returns deactivated if deactivation_date is in the past" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), location:) location.save! expect(location.status).to eq(:deactivated) end it "returns deactivated if deactivation_date is today" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), location:) location.save! expect(location.status).to eq(:deactivated) end + + it "returns reactivating soon if the location has a future reactivation date" do + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), reactivation_date: Time.zone.local(2022, 6, 8), location:) + location.save! + expect(location.status).to eq(:reactivating_soon) + end end context "when there have been previous deactivations" do before do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 6, 5)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 4), reactivation_date: Time.zone.local(2022, 6, 5), location:) + location.save! end it "returns active if the location has no relevant deactivation records" do @@ -157,30 +164,36 @@ RSpec.describe Location, type: :model do end it "returns deactivating soon if deactivation_date is in the future" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), location:) location.save! expect(location.status).to eq(:deactivating_soon) end it "returns deactivated if deactivation_date is in the past" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), location:) location.save! expect(location.status).to eq(:deactivated) end it "returns deactivated if deactivation_date is today" do - location.location_deactivation_periods << FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7)) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), location:) location.save! expect(location.status).to eq(:deactivated) end - 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 "returns reactivating soon if the location has a future reactivation date" do + Timecop.freeze(2022, 6, 8) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), reactivation_date: Time.zone.local(2022, 6, 9), location:) + location.save! + expect(location.status).to eq(:reactivating_soon) + end - it "is valid" do - expect(location).to be_valid + it "returns if the location had a deactivation during another deactivation" do + Timecop.freeze(2022, 6, 4) + FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 6, 2), location:) + location.save! + expect(location.status).to eq(:reactivating_soon) + end end end end diff --git a/spec/models/scheme_spec.rb b/spec/models/scheme_spec.rb index d95d867dc..b19e8c992 100644 --- a/spec/models/scheme_spec.rb +++ b/spec/models/scheme_spec.rb @@ -109,27 +109,27 @@ RSpec.describe Scheme, type: :model do end it "returns deactivating soon if deactivation_date is in the future" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivating_soon) end it "returns deactivated if deactivation_date is in the past" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivated) end it "returns deactivated if deactivation_date is today" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivated) end end context "when there have been previous deactivations" do before do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 6, 5)) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 6, 5), scheme:) end it "returns active if the scheme has no relevant deactivation records" do @@ -137,30 +137,22 @@ RSpec.describe Scheme, type: :model do end it "returns deactivating soon if deactivation_date is in the future" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivating_soon) end it "returns deactivated if deactivation_date is in the past" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivated) end it "returns deactivated if deactivation_date is today" do - scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7)) - scheme.save! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:) + scheme.reload expect(scheme.status).to eq(:deactivated) end 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 605c357b7..237149f7d 100644 --- a/spec/requests/locations_controller_spec.rb +++ b/spec/requests/locations_controller_spec.rb @@ -1238,14 +1238,17 @@ RSpec.describe LocationsController, type: :request do 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!(:location) { FactoryBot.create(:location, scheme:) } + let!(:location) { FactoryBot.create(:location, scheme:, startdate: nil, created_at: Time.zone.local(2022, 4, 1)) } let(:deactivation_date) { Time.utc(2022, 10, 10) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location:, scheme:, startdate:, owning_organisation: user.organisation) } let(:startdate) { Time.utc(2022, 10, 11) } + let(:add_deactivations) { nil } before do Timecop.freeze(Time.utc(2022, 10, 10)) sign_in user + add_deactivations + location.save! patch "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation", params: end @@ -1254,7 +1257,7 @@ RSpec.describe LocationsController, type: :request do end context "with default date" do - let(:params) { { location: { deactivation_date_type: "default", deactivation_date: } } } + let(:params) { { location_deactivation_period: { deactivation_date_type: "default", deactivation_date: } } } it "redirects to the confirmation page" do follow_redirect! @@ -1264,7 +1267,7 @@ RSpec.describe LocationsController, type: :request do end context "with other date" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "10", "deactivation_date(1i)": "2022" } } } + let(:params) { { location_deactivation_period: { 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! @@ -1274,7 +1277,7 @@ RSpec.describe LocationsController, type: :request do end context "when confirming deactivation" do - let(:params) { { location: { deactivation_date:, confirm: true, deactivation_date_type: "other" } } } + let(:params) { { deactivation_date:, confirm: true, deactivation_date_type: "other" } } before do Timecop.freeze(Time.utc(2022, 10, 10)) @@ -1319,56 +1322,67 @@ RSpec.describe LocationsController, type: :request do end context "when the date is not selected" do - let(:params) { { location: { "deactivation_date": "" } } } + let(:params) { { location_deactivation_period: { "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.location.deactivation_date.not_selected")) + expect(page).to have_content(I18n.t("validations.location.toggle_date.not_selected")) end end context "when invalid date is entered" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "44", "deactivation_date(1i)": "2022" } } } + let(:params) { { location_deactivation_period: { 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.location.deactivation_date.invalid")) + expect(page).to have_content(I18n.t("validations.location.toggle_date.invalid")) end end context "when the date is entered is before the beginning of current collection window" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "4", "deactivation_date(1i)": "2020" } } } + let(:params) { { location_deactivation_period: { 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.location.deactivation_date.out_of_range", date: "1 April 2022")) + expect(page).to have_content(I18n.t("validations.location.toggle_date.out_of_range", date: "1 April 2022")) end end context "when the day is not entered" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "", "deactivation_date(2i)": "2", "deactivation_date(1i)": "2022" } } } + let(:params) { { location_deactivation_period: { 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.location.deactivation_date.invalid")) + expect(page).to have_content(I18n.t("validations.location.toggle_date.invalid")) end end context "when the month is not entered" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "2", "deactivation_date(2i)": "", "deactivation_date(1i)": "2022" } } } + let(:params) { { location_deactivation_period: { 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.location.deactivation_date.invalid")) + expect(page).to have_content(I18n.t("validations.location.toggle_date.invalid")) end end context "when the year is not entered" do - let(:params) { { location: { deactivation_date_type: "other", "deactivation_date(3i)": "2", "deactivation_date(2i)": "2", "deactivation_date(1i)": "" } } } + let(:params) { { location_deactivation_period: { 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.location.toggle_date.invalid")) + end + end + + context "when deactivation date is during a deactivated period" do + let(:deactivation_date) { Time.zone.local(2022, 10, 10) } + let(:params) { { location_deactivation_period: { deactivation_date_type: "other", "deactivation_date(3i)": "8", "deactivation_date(2i)": "9", "deactivation_date(1i)": "2022" } } } + let(:add_deactivations) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 5, 5), reactivation_date: Time.zone.local(2022, 10, 12), location:) } 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.invalid")) + expect(page).to have_content(I18n.t("validations.location.deactivation.during_deactivated_period")) end end end @@ -1399,7 +1413,7 @@ RSpec.describe LocationsController, type: :request do 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!(:location) { FactoryBot.create(:location, scheme:) } + let!(:location) { FactoryBot.create(:location, scheme:, startdate: nil) } let(:add_deactivations) { location.location_deactivation_periods << location_deactivation_period } before do @@ -1424,20 +1438,184 @@ RSpec.describe LocationsController, type: :request do end context "with deactivated location" do - let(:location_deactivation_period) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 9)) } + let(:location_deactivation_period) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 9), location:) } it "renders reactivate this location" do expect(response).to have_http_status(:ok) - expect(page).to have_link("Reactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/reactivate") + expect(page).to have_link("Reactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/new-reactivation") end end context "with location that's deactivating soon" do - let(:location_deactivation_period) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12)) } + let(:location_deactivation_period) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), location:) } + + it "renders reactivate this location" do + expect(response).to have_http_status(:ok) + expect(page).to have_link("Reactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/new-reactivation") + end + end + + context "with location that's reactivating soon" do + let(:location_deactivation_period) { FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 12), reactivation_date: Time.zone.local(2022, 10, 12), location:) } it "renders reactivate this location" do expect(response).to have_http_status(:ok) - expect(page).to have_link("Reactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/reactivate") + expect(page).to have_link("Deactivate this location", href: "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation") + end + end + end + end + + describe "#reactivate" do + context "when not signed in" do + it "redirects to the sign in page" do + patch "/schemes/1/locations/1/reactivate" + 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/locations/1/reactivate" + 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!(:location) { FactoryBot.create(:location, scheme:, startdate: nil) } + let(:deactivation_date) { Time.zone.local(2022, 4, 1) } + let(:startdate) { Time.utc(2022, 10, 11) } + + before do + Timecop.freeze(Time.utc(2022, 10, 10)) + sign_in user + FactoryBot.create(:location_deactivation_period, deactivation_date:, location:) + location.save! + patch "/schemes/#{scheme.id}/locations/#{location.id}/reactivate", params: + end + + after do + Timecop.unfreeze + end + + context "with default date" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "default" } } } + + it "redirects to the location page and displays a success banner" do + expect(response).to redirect_to("/schemes/#{scheme.id}/locations/#{location.id}") + follow_redirect! + expect(response).to have_http_status(:ok) + expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") + expect(page).to have_content("#{location.name} has been reactivated") + end + + it "updates existing location deactivations with valid reactivation date" do + follow_redirect! + location.reload + expect(location.location_deactivation_periods.count).to eq(1) + expect(location.location_deactivation_periods.first.reactivation_date).to eq(Time.zone.local(2022, 4, 1)) + end + end + + context "with other date" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "10", "reactivation_date(2i)": "10", "reactivation_date(1i)": "2022" } } } + + it "redirects to the location page and displays a success banner" do + expect(response).to redirect_to("/schemes/#{scheme.id}/locations/#{location.id}") + follow_redirect! + expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") + expect(page).to have_content("#{location.name} has been reactivated") + end + + it "updates existing location deactivations with valid reactivation date" do + follow_redirect! + location.reload + expect(location.location_deactivation_periods.count).to eq(1) + expect(location.location_deactivation_periods.first.reactivation_date).to eq(Time.zone.local(2022, 10, 10)) + end + end + + context "with other future date" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "14", "reactivation_date(2i)": "12", "reactivation_date(1i)": "2022" } } } + + it "redirects to the location page and displays a success banner" do + expect(response).to redirect_to("/schemes/#{scheme.id}/locations/#{location.id}") + follow_redirect! + expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") + expect(page).to have_content("#{location.name} will reactivate on 14 December 2022") + end + end + + context "when the date is not selected" do + let(:params) { { location_deactivation_period: { "reactivation_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.location.toggle_date.not_selected")) + end + end + + context "when invalid date is entered" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "10", "reactivation_date(2i)": "44", "reactivation_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.location.toggle_date.invalid")) + end + end + + context "when the date is entered is before the beginning of current collection window" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "10", "reactivation_date(2i)": "4", "reactivation_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.location.toggle_date.out_of_range", date: "1 April 2022")) + end + end + + context "when the day is not entered" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "", "reactivation_date(2i)": "2", "reactivation_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.location.toggle_date.invalid")) + end + end + + context "when the month is not entered" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "2", "reactivation_date(2i)": "", "reactivation_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.location.toggle_date.invalid")) + end + end + + context "when the year is not entered" do + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "2", "reactivation_date(2i)": "2", "reactivation_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.location.toggle_date.invalid")) + end + end + + context "when the reactivation date is before deactivation date" do + let(:deactivation_date) { Time.zone.local(2022, 10, 10) } + let(:params) { { location_deactivation_period: { reactivation_date_type: "other", "reactivation_date(3i)": "8", "reactivation_date(2i)": "9", "reactivation_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.location.reactivation.before_deactivation", date: "10 October 2022")) end end end diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 59d044050..0c3b47f1a 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -270,7 +270,7 @@ RSpec.describe SchemesController, type: :request do end context "with deactivated scheme" do - let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 9)) } + let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 9), scheme:) } it "renders reactivate this scheme" do expect(response).to have_http_status(:ok) @@ -279,7 +279,7 @@ RSpec.describe SchemesController, type: :request do end context "with scheme that's deactivating soon" do - let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12)) } + let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), scheme:) } it "renders reactivate this scheme" do expect(response).to have_http_status(:ok) @@ -1785,7 +1785,7 @@ RSpec.describe SchemesController, type: :request do end context "with default date" do - let(:params) { { scheme: { deactivation_date_type: "default", deactivation_date: } } } + let(:params) { { scheme_deactivation_period: { deactivation_date_type: "default", deactivation_date: } } } it "redirects to the confirmation page" do follow_redirect! @@ -1795,7 +1795,7 @@ RSpec.describe SchemesController, type: :request do 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" } } } + let(:params) { { scheme_deactivation_period: { 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! @@ -1805,7 +1805,7 @@ RSpec.describe SchemesController, type: :request do end context "when confirming deactivation" do - let(:params) { { scheme: { deactivation_date:, confirm: true, deactivation_date_type: "other" } } } + let(:params) { { deactivation_date:, confirm: true, deactivation_date_type: "other" } } before do Timecop.freeze(Time.utc(2022, 10, 10)) @@ -1851,7 +1851,7 @@ RSpec.describe SchemesController, type: :request do end context "when the date is not selected" do - let(:params) { { scheme: { "deactivation_date": "" } } } + let(:params) { { scheme_deactivation_period: { "deactivation_date": "" } } } it "displays the new page with an error message" do expect(response).to have_http_status(:unprocessable_entity) @@ -1860,7 +1860,7 @@ RSpec.describe SchemesController, type: :request do 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" } } } + let(:params) { { scheme_deactivation_period: { 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) @@ -1869,7 +1869,7 @@ RSpec.describe SchemesController, type: :request do 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" } } } + let(:params) { { scheme_deactivation_period: { 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) @@ -1878,7 +1878,7 @@ RSpec.describe SchemesController, type: :request do 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" } } } + let(:params) { { scheme_deactivation_period: { 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) @@ -1887,7 +1887,7 @@ RSpec.describe SchemesController, type: :request do 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" } } } + let(:params) { { scheme_deactivation_period: { 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) @@ -1896,7 +1896,7 @@ RSpec.describe SchemesController, type: :request do 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)": "" } } } + let(:params) { { scheme_deactivation_period: { 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)