From 74526e9fafb45f692b9fe9975e58ae29f89b0fc0 Mon Sep 17 00:00:00 2001 From: Manny Dinssa <44172848+Dinssa@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:35:30 +0100 Subject: [PATCH] Update scheme deactivation confirmation with affected locations --- app/controllers/schemes_controller.rb | 47 ++++++++++++++++--- app/helpers/locations_helper.rb | 10 +++- app/helpers/schemes_helper.rb | 11 ++++- app/models/location.rb | 41 ++++++++++++---- app/models/scheme.rb | 8 ++++ app/views/locations/index.html.erb | 13 +++-- app/views/schemes/deactivate_confirm.html.erb | 47 ++++++++++++++----- .../deactivate_confirm.html.erb_spec.rb | 46 ++++++++++++++++++ 8 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 spec/views/schemes/deactivate_confirm.html.erb_spec.rb diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index c0a36b920..9df4bebe7 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -51,17 +51,34 @@ class SchemesController < ApplicationController end def deactivate_confirm - @affected_logs = @scheme.lettings_logs.visible.after_date(params[:deactivation_date]) - if @affected_logs.count.zero? + @deactivation_date = Time.zone.parse(params[:deactivation_date]) + @affected_logs = @scheme.lettings_logs.visible.after_date(@deactivation_date) + @deactivation_date_type = params[:deactivation_date_type] + + scheme_locations = @scheme.locations.confirmed + + locations_active_on_deactivation_date, remaining_locations = scheme_locations.partition do |location| + location.status_at(@deactivation_date) == :active + end + + locations_deactivating_after_deactivation_date, remaining_locations = remaining_locations.partition do |location| + location.status_at(@deactivation_date) == :deactivating_soon || location.status_at(@deactivation_date) == :reactivating_soon + end + + locations_startdate_after_deactivation_date, = remaining_locations.partition do |location| + location.status_at(@deactivation_date) == :activating_soon + end + + @affected_locations = locations_active_on_deactivation_date + locations_deactivating_after_deactivation_date + locations_startdate_after_deactivation_date + + if @affected_logs.count.zero? && @affected_locations.count.zero? deactivate - else - @deactivation_date = params[:deactivation_date] - @deactivation_date_type = params[:deactivation_date_type] end end def deactivate - if @scheme.open_deactivation&.update!(deactivation_date: params[:deactivation_date]) || @scheme.scheme_deactivation_periods.create!(deactivation_date: params[:deactivation_date]) + deactivation_date = params[:deactivation_date] + if @scheme.open_deactivation&.update!(deactivation_date:) || @scheme.scheme_deactivation_periods.create!(deactivation_date:) logs = reset_location_and_scheme_for_logs! flash[:notice] = deactivate_success_notice @@ -370,4 +387,22 @@ private def session_filters filter_manager.session_filters end + + def deactivate_locations(deactivation_date) + # Add a deactivation period to @locations_without_deactivation_period + @locations_without_deactivation_period.each do |location| + LocationDeactivationPeriod.create!(location:, deactivation_date:) + end + + # Change the deactivation period for @locations_with_future_deactivation_period + @locations_with_future_deactivation_period.each do |location| + location_deactivation_period = location.location_deactivation_periods.find_by("deactivation_date > ?", Time.zone.now) + location_deactivation_period.update!(deactivation_date:) if location_deactivation_period + end + + # Clear the start date for @locations_with_future_start_date + @locations_with_future_start_date.each do |location| + location.update!(startdate: nil) + end + end end diff --git a/app/helpers/locations_helper.rb b/app/helpers/locations_helper.rb index f963c7040..7d2b6dee1 100644 --- a/app/helpers/locations_helper.rb +++ b/app/helpers/locations_helper.rb @@ -70,7 +70,7 @@ module LocationsHelper def toggle_location_link(location) return govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(location.scheme, location), warning: true if location.active? || location.deactivates_in_a_long_time? - return govuk_button_link_to "Reactivate this location", scheme_location_new_reactivation_path(location.scheme, location) if location.deactivated? + return govuk_button_link_to "Reactivate this location", scheme_location_new_reactivation_path(location.scheme, location) if location.deactivated? && !location.deactivated_by_scheme? end def delete_location_link(location) @@ -107,6 +107,14 @@ private periods << ActivePeriod.new(deactivation.reactivation_date, nil) end + if location.deactivated_by_scheme? || location.deactivating_soon_by_scheme? + scheme_periods = location.scheme.scheme_deactivation_periods.sort_by(&:deactivation_date) + scheme_periods.each do |scheme_period| + periods.last.to = scheme_period.deactivation_date + periods << ActivePeriod.new(scheme_period.reactivation_date, nil) + end + end + remove_overlapping_and_empty_periods(periods) end diff --git a/app/helpers/schemes_helper.rb b/app/helpers/schemes_helper.rb index f96f9e4c8..0e318d283 100644 --- a/app/helpers/schemes_helper.rb +++ b/app/helpers/schemes_helper.rb @@ -12,7 +12,7 @@ module SchemesHelper def toggle_scheme_link(scheme) return govuk_button_link_to "Deactivate this scheme", scheme_new_deactivation_path(scheme), warning: true if scheme.active? || scheme.deactivates_in_a_long_time? - return govuk_button_link_to "Reactivate this scheme", scheme_new_reactivation_path(scheme) if scheme.deactivated? + return govuk_button_link_to "Reactivate this scheme", scheme_new_reactivation_path(scheme) if scheme.deactivated? || scheme.deactivating_soon? end def delete_scheme_link(scheme) @@ -76,6 +76,15 @@ module SchemesHelper end end + def scheme_status_hint(scheme) + case scheme.status + when :deactivating_soon + "This scheme deactivates on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date." + when :deactivated + "This scheme deactivated on #{scheme.last_deactivation_date.to_formatted_s(:govuk_date)}. Any locations you add will be deactivated on the same date. Reactivate the scheme to add locations active after this date." + end + end + private ActivePeriod = Struct.new(:from, :to) diff --git a/app/models/location.rb b/app/models/location.rb index 8efa4ee28..917c4338c 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -40,6 +40,7 @@ class Location < ApplicationRecord filtered_records = filtered_records .left_outer_joins(:location_deactivation_periods) .joins(scheme: [:owning_organisation]) + .left_outer_joins(scheme: :scheme_deactivation_periods) .order("location_deactivation_periods.created_at DESC") .merge(scopes.reduce(&:or)) end @@ -55,12 +56,17 @@ class Location < ApplicationRecord scope :deactivated, lambda { deactivated_by_organisation .or(deactivated_directly) + .or(deactivated_by_scheme) } scope :deactivated_by_organisation, lambda { merge(Organisation.filter_by_inactive) } + scope :deactivated_by_scheme, lambda { + merge(Scheme.deactivated) + } + scope :deactivated_directly, lambda { |date = Time.zone.now| merge(LocationDeactivationPeriod.deactivations_without_reactivation) .where("location_deactivation_periods.deactivation_date <= ?", date) @@ -68,8 +74,13 @@ class Location < ApplicationRecord scope :deactivating_soon, lambda { |date = Time.zone.now| merge(LocationDeactivationPeriod.deactivations_without_reactivation) - .where("location_deactivation_periods.deactivation_date > ?", date) - .where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) + .where("location_deactivation_periods.deactivation_date > ?", date) + .where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) + .or(deactivating_soon_by_scheme) + } + + scope :deactivating_soon_by_scheme, lambda { + merge(Scheme.deactivating_soon) } scope :reactivating_soon, lambda { |date = Time.zone.now| @@ -84,17 +95,19 @@ class Location < ApplicationRecord scope :active_status, lambda { where.not(id: joins(:location_deactivation_periods).reactivating_soon.pluck(:id)) - .where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) - .where.not(id: joins(:location_deactivation_periods).deactivated_directly.pluck(:id)) - .where.not(id: incomplete.pluck(:id)) - .where.not(id: joins(:location_deactivation_periods).deactivating_soon.pluck(:id)) - .where.not(id: activating_soon.pluck(:id)) + .where.not(id: joins(:location_deactivation_periods).deactivated_directly.pluck(:id)) + .where.not(id: joins(scheme: %i[owning_organisation scheme_deactivation_periods]).deactivated_by_scheme.pluck(:id)) + .where.not(id: joins(scheme: [:scheme_deactivation_periods]).deactivating_soon_by_scheme.pluck(:id)) + .where.not(id: joins(:location_deactivation_periods).deactivating_soon.pluck(:id)) + .where.not(id: incomplete.pluck(:id)) + .where.not(id: activating_soon.pluck(:id)) } scope :active, lambda { |date = Time.zone.now| where.not(id: joins(:location_deactivation_periods).reactivating_soon(date).pluck(:id)) - .where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) .where.not(id: joins(:location_deactivation_periods).deactivated_directly(date).pluck(:id)) + .where.not(id: joins(scheme: %i[owning_organisation scheme_deactivation_periods]).deactivated_by_scheme.pluck(:id)) + .where.not(id: joins(scheme: [:scheme_deactivation_periods]).deactivating_soon_by_scheme.pluck(:id)) .where.not(id: incomplete.pluck(:id)) .where.not(id: activating_soon(date).pluck(:id)) } @@ -163,9 +176,9 @@ class Location < ApplicationRecord return :deleted if discarded_at.present? return :incomplete unless confirmed return :deactivated if scheme.owning_organisation.status_at(date) == :deactivated || - open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date + open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date || scheme.status_at(date) == :deactivated + return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date || scheme.status_at(date) == :deactivating_soon return :activating_soon if startdate.present? && date < startdate - return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date return :reactivating_soon if last_deactivation_before(date)&.reactivation_date.present? && date < last_deactivation_before(date).reactivation_date :active @@ -187,6 +200,14 @@ class Location < ApplicationRecord status_at(6.months.from_now) == :deactivating_soon end + def deactivated_by_scheme? + status == :deactivated && scheme.status == :deactivated + end + + def deactivating_soon_by_scheme? + status == :deactivating_soon && scheme.status == :deactivating_soon + end + def validate_postcode if !postcode&.match(POSTCODE_REGEXP) error_message = I18n.t("validations.postcode") diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 07ec14731..9d26b72c0 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -275,6 +275,10 @@ class Scheme < ApplicationRecord scheme_deactivation_periods.where("deactivation_date <= ?", date).order("created_at").last end + def last_deactivation_date + scheme_deactivation_periods.order(deactivation_date: :desc).first&.deactivation_date + end + def status @status ||= status_at(Time.zone.now) end @@ -313,6 +317,10 @@ class Scheme < ApplicationRecord status == :deactivated end + def deactivating_soon? + status == :deactivating_soon + end + def deactivates_in_a_long_time? status_at(6.months.from_now) == :deactivating_soon end diff --git a/app/views/locations/index.html.erb b/app/views/locations/index.html.erb index 78a362332..64d9bf286 100644 --- a/app/views/locations/index.html.erb +++ b/app/views/locations/index.html.erb @@ -56,10 +56,17 @@ <% end %> <% end %> + <% if status_hint_message = scheme_status_hint(@scheme) %> +