Browse Source

CLDC-3001 Handle locations and logs on deactivate schemes (#2605)

pull/2631/head
Manny Dinssa 4 months ago committed by GitHub
parent
commit
27188ad3a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 19
      app/controllers/schemes_controller.rb
  2. 8
      app/helpers/deactivate_confirm_helper.rb
  3. 31
      app/helpers/locations_helper.rb
  4. 11
      app/helpers/schemes_helper.rb
  5. 70
      app/models/location.rb
  6. 38
      app/models/scheme.rb
  7. 1
      app/models/scheme_deactivation_period.rb
  8. 6
      app/models/validations/shared_validations.rb
  9. 13
      app/views/locations/index.html.erb
  10. 41
      app/views/schemes/deactivate_confirm.html.erb
  11. 13
      app/views/schemes/toggle_active.html.erb
  12. 2
      spec/fixtures/files/locations_csv_export.csv
  13. 2
      spec/fixtures/files/schemes_and_locations_csv_export.csv
  14. 33
      spec/models/location_spec.rb
  15. 31
      spec/requests/schemes_controller_spec.rb
  16. 46
      spec/views/schemes/deactivate_confirm.html.erb_spec.rb

19
app/controllers/schemes_controller.rb

@ -51,17 +51,24 @@ class SchemesController < ApplicationController
end end
def deactivate_confirm def deactivate_confirm
@affected_logs = @scheme.lettings_logs.visible.after_date(params[:deactivation_date]) @deactivation_date = Time.zone.parse(params[:deactivation_date])
if @affected_logs.count.zero? @affected_logs = @scheme.lettings_logs.visible.after_date(@deactivation_date)
@deactivation_date_type = params[:deactivation_date_type]
scheme_locations = @scheme.locations.confirmed
@affected_locations = scheme_locations.select do |location|
%i[active deactivating_soon reactivating_soon activating_soon].include?(location.status_at(@deactivation_date))
end
if @affected_logs.count.zero? && @affected_locations.count.zero?
deactivate deactivate
else
@deactivation_date = params[:deactivation_date]
@deactivation_date_type = params[:deactivation_date_type]
end end
end end
def deactivate 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! logs = reset_location_and_scheme_for_logs!
flash[:notice] = deactivate_success_notice flash[:notice] = deactivate_success_notice

8
app/helpers/deactivate_confirm_helper.rb

@ -0,0 +1,8 @@
module DeactivateConfirmHelper
def affected_title(affected_logs, affected_locations)
title_parts = []
title_parts << pluralize(affected_logs.count, "log") if affected_logs.count.positive?
title_parts << pluralize(affected_locations.count, "location") if affected_locations.count.positive?
"This change will affect #{title_parts.join(' and ')}."
end
end

31
app/helpers/locations_helper.rb

@ -70,7 +70,7 @@ module LocationsHelper
def toggle_location_link(location) 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 "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 end
def delete_location_link(location) def delete_location_link(location)
@ -100,14 +100,37 @@ private
ActivePeriod = Struct.new(:from, :to) ActivePeriod = Struct.new(:from, :to)
def location_active_periods(location) def location_active_periods(location)
periods = [ActivePeriod.new(location.available_from, nil)] periods = [ActivePeriod.new(location.available_from, nil)]
location_deactivation_periods = location_deactivation_periods(location)
scheme_deactivation_periods = scheme_deactivation_periods(location, location_deactivation_periods)
sorted_deactivation_periods = remove_nested_periods(location.location_deactivation_periods.sort_by(&:deactivation_date)) combined_deactivation_periods = location_deactivation_periods + scheme_deactivation_periods
sorted_deactivation_periods = combined_deactivation_periods.sort_by(&:deactivation_date)
update_periods_with_deactivations(periods, sorted_deactivation_periods)
remove_overlapping_and_empty_periods(periods)
end
def location_deactivation_periods(location)
periods = remove_nested_periods(location.location_deactivation_periods.sort_by(&:deactivation_date))
periods.last&.deactivation_date if periods.last&.reactivation_date.nil?
periods
end
def scheme_deactivation_periods(location, location_deactivation_periods)
return [] unless location.scheme.scheme_deactivation_periods.any?
location_deactivation_date = location_deactivation_periods.last&.deactivation_date
periods = remove_nested_periods(location.scheme.scheme_deactivation_periods.sort_by(&:deactivation_date))
periods.select do |period|
period.deactivation_date >= location.available_from && (location_deactivation_date.nil? || period.deactivation_date <= location_deactivation_date)
end
end
def update_periods_with_deactivations(periods, sorted_deactivation_periods)
sorted_deactivation_periods.each do |deactivation| sorted_deactivation_periods.each do |deactivation|
periods.last.to = deactivation.deactivation_date periods.last.to = deactivation.deactivation_date
periods << ActivePeriod.new(deactivation.reactivation_date, nil) periods << ActivePeriod.new(deactivation.reactivation_date, nil)
end end
remove_overlapping_and_empty_periods(periods)
end end
def remove_overlapping_and_empty_periods(periods) def remove_overlapping_and_empty_periods(periods)

11
app/helpers/schemes_helper.rb

@ -12,7 +12,7 @@ module SchemesHelper
def toggle_scheme_link(scheme) 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 "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 end
def delete_scheme_link(scheme) def delete_scheme_link(scheme)
@ -76,6 +76,15 @@ module SchemesHelper
end end
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 private
ActivePeriod = Struct.new(:from, :to) ActivePeriod = Struct.new(:from, :to)

70
app/models/location.rb

@ -40,6 +40,7 @@ class Location < ApplicationRecord
filtered_records = filtered_records filtered_records = filtered_records
.left_outer_joins(:location_deactivation_periods) .left_outer_joins(:location_deactivation_periods)
.joins(scheme: [:owning_organisation]) .joins(scheme: [:owning_organisation])
.left_outer_joins(scheme: :scheme_deactivation_periods)
.order("location_deactivation_periods.created_at DESC") .order("location_deactivation_periods.created_at DESC")
.merge(scopes.reduce(&:or)) .merge(scopes.reduce(&:or))
end end
@ -52,30 +53,47 @@ class Location < ApplicationRecord
.or(where(confirmed: nil)) .or(where(confirmed: nil))
} }
scope :deactivated, lambda { scope :deactivated, lambda { |date = Time.zone.now|
deactivated_by_organisation deactivated_by_organisation
.or(deactivated_directly) .or(deactivated_directly(date))
.or(deactivated_by_scheme(date))
} }
scope :deactivated_by_organisation, lambda { scope :deactivated_by_organisation, lambda {
merge(Organisation.filter_by_inactive) merge(Organisation.filter_by_inactive)
} }
scope :deactivated_by_scheme, lambda { |date = Time.zone.now|
merge(Scheme.deactivated_directly(date))
}
scope :deactivated_directly, lambda { |date = Time.zone.now| scope :deactivated_directly, lambda { |date = Time.zone.now|
merge(LocationDeactivationPeriod.deactivations_without_reactivation) merge(LocationDeactivationPeriod.deactivations_without_reactivation)
.where("location_deactivation_periods.deactivation_date <= ?", date) .where("location_deactivation_periods.deactivation_date <= ?", date)
} }
scope :deactivating_soon, lambda { |date = Time.zone.now| scope :deactivating_soon_directly, lambda { |date = Time.zone.now|
merge(LocationDeactivationPeriod.deactivations_without_reactivation) merge(LocationDeactivationPeriod.deactivations_without_reactivation)
.where("location_deactivation_periods.deactivation_date > ?", date) .where("location_deactivation_periods.deactivation_date > ?", date)
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) }
scope :deactivating_soon, lambda { |date = Time.zone.now|
deactivating_soon_directly
.or(deactivating_soon_by_scheme(date))
}
scope :deactivating_soon_by_scheme, lambda { |date = Time.zone.now|
merge(Scheme.deactivating_soon(date))
} }
scope :reactivating_soon, lambda { |date = Time.zone.now| scope :reactivating_soon, lambda { |date = Time.zone.now|
where.not("location_deactivation_periods.reactivation_date IS NULL") where.not("location_deactivation_periods.reactivation_date IS NULL")
.where("location_deactivation_periods.reactivation_date > ?", date) .where("location_deactivation_periods.reactivation_date > ?", date)
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) .where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id))
}
scope :reactivating_soon_by_scheme, lambda { |date = Time.zone.now|
merge(Scheme.reactivating_soon(date))
} }
scope :activating_soon, lambda { |date = Time.zone.now| scope :activating_soon, lambda { |date = Time.zone.now|
@ -84,19 +102,21 @@ class Location < ApplicationRecord
scope :active_status, lambda { scope :active_status, lambda {
where.not(id: joins(:location_deactivation_periods).reactivating_soon.pluck(:id)) 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(scheme: [:scheme_deactivation_periods]).reactivating_soon_by_scheme.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivated_directly.pluck(:id)) .where.not(id: joins(:location_deactivation_periods).merge(Location.deactivated_directly).pluck(:id))
.where.not(id: incomplete.pluck(:id)) .where.not(id: joins(scheme: [:scheme_deactivation_periods]).merge(Location.deactivated_by_scheme).pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivating_soon.pluck(:id)) .where.not(id: joins(scheme: [:owning_organisation]).merge(Location.deactivated_by_organisation).pluck(:id))
.where.not(id: activating_soon.pluck(:id)) .where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).merge(Location.deactivating_soon_directly).pluck(:id))
.where.not(id: joins(scheme: %i[owning_organisation scheme_deactivation_periods]).merge(Location.deactivating_soon_by_scheme).pluck(:id))
.where.not(id: activating_soon.pluck(:id))
} }
scope :active, lambda { |date = Time.zone.now| scope :active, lambda { |date = Time.zone.now|
where.not(id: joins(:location_deactivation_periods).reactivating_soon(date).pluck(:id)) where.not(id: joins(:location_deactivation_periods).merge(Location.deactivated_directly(date)).pluck(:id))
.where.not(id: joins(scheme: [:owning_organisation]).deactivated_by_organisation.pluck(:id)) .where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:location_deactivation_periods).deactivated_directly(date).pluck(:id))
.where.not(id: incomplete.pluck(:id))
.where.not(id: activating_soon(date).pluck(:id)) .where.not(id: activating_soon(date).pluck(:id))
.where(scheme: Scheme.active(date))
} }
scope :visible, -> { where(discarded_at: nil) } scope :visible, -> { where(discarded_at: nil) }
@ -163,10 +183,10 @@ class Location < ApplicationRecord
return :deleted if discarded_at.present? return :deleted if discarded_at.present?
return :incomplete unless confirmed return :incomplete unless confirmed
return :deactivated if scheme.owning_organisation.status_at(date) == :deactivated || 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 :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 || scheme.status_at(date) == :reactivating_soon
return :reactivating_soon if last_deactivation_before(date)&.reactivation_date.present? && date < last_deactivation_before(date).reactivation_date
:active :active
end end
@ -187,6 +207,18 @@ class Location < ApplicationRecord
status_at(6.months.from_now) == :deactivating_soon status_at(6.months.from_now) == :deactivating_soon
end 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 reactivating_soon_by_scheme?
status == :reactivating_soon && scheme.status == :reactivating_soon
end
def validate_postcode def validate_postcode
if !postcode&.match(POSTCODE_REGEXP) if !postcode&.match(POSTCODE_REGEXP)
error_message = I18n.t("validations.postcode") error_message = I18n.t("validations.postcode")

38
app/models/scheme.rb

@ -61,25 +61,27 @@ class Scheme < ApplicationRecord
merge(Organisation.filter_by_inactive) merge(Organisation.filter_by_inactive)
} }
scope :deactivated_directly, lambda { scope :deactivated_directly, lambda { |date = Time.zone.now|
merge(SchemeDeactivationPeriod.deactivations_without_reactivation) merge(SchemeDeactivationPeriod.deactivations_without_reactivation)
.where("scheme_deactivation_periods.deactivation_date <= ?", Time.zone.now) .where("scheme_deactivation_periods.deactivation_date <= ?", date)
} }
scope :deactivating_soon, lambda { scope :deactivating_soon, lambda { |date = Time.zone.now|
merge(SchemeDeactivationPeriod.deactivations_without_reactivation) merge(SchemeDeactivationPeriod.deactivations_without_reactivation)
.where("scheme_deactivation_periods.deactivation_date > ? AND scheme_deactivation_periods.deactivation_date < ? ", Time.zone.now, 6.months.from_now) .where("scheme_deactivation_periods.deactivation_date > ? AND scheme_deactivation_periods.deactivation_date < ? ", date, 6.months.from_now)
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id)) .where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
} }
scope :reactivating_soon, lambda { scope :reactivating_soon, lambda { |date = Time.zone.now|
where.not("scheme_deactivation_periods.reactivation_date IS NULL") merge(SchemeDeactivationPeriod.deactivations_with_reactivation)
.where("scheme_deactivation_periods.reactivation_date > ?", Time.zone.now) .where.not("scheme_deactivation_periods.reactivation_date IS NULL")
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id)) .where("scheme_deactivation_periods.reactivation_date > ?", date)
.where("scheme_deactivation_periods.deactivation_date <= ?", date)
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
} }
scope :activating_soon, lambda { scope :activating_soon, lambda { |date = Time.zone.now|
where("schemes.startdate > ?", Time.zone.now) where("schemes.startdate > ?", date)
} }
scope :active_status, lambda { scope :active_status, lambda {
@ -91,6 +93,14 @@ class Scheme < ApplicationRecord
.where.not(id: activating_soon.pluck(:id)) .where.not(id: activating_soon.pluck(:id))
} }
scope :active, lambda { |date = Time.zone.now|
where.not(id: joins(:scheme_deactivation_periods).reactivating_soon(date).pluck(:id))
.where.not(id: incomplete.pluck(:id))
.where.not(id: joins(:owning_organisation).deactivated_by_organisation.pluck(:id))
.where.not(id: joins(:owning_organisation).joins(:scheme_deactivation_periods).deactivated_directly(date).pluck(:id))
.where.not(id: activating_soon(date).pluck(:id))
}
scope :visible, -> { where(discarded_at: nil) } scope :visible, -> { where(discarded_at: nil) }
validate :validate_confirmed validate :validate_confirmed
@ -275,6 +285,10 @@ class Scheme < ApplicationRecord
scheme_deactivation_periods.where("deactivation_date <= ?", date).order("created_at").last scheme_deactivation_periods.where("deactivation_date <= ?", date).order("created_at").last
end end
def last_deactivation_date
scheme_deactivation_periods.order(deactivation_date: :desc).first&.deactivation_date
end
def status def status
@status ||= status_at(Time.zone.now) @status ||= status_at(Time.zone.now)
end end
@ -313,6 +327,10 @@ class Scheme < ApplicationRecord
status == :deactivated status == :deactivated
end end
def deactivating_soon?
status == :deactivating_soon
end
def deactivates_in_a_long_time? def deactivates_in_a_long_time?
status_at(6.months.from_now) == :deactivating_soon status_at(6.months.from_now) == :deactivating_soon
end end

1
app/models/scheme_deactivation_period.rb

@ -48,4 +48,5 @@ class SchemeDeactivationPeriod < ApplicationRecord
attr_accessor :deactivation_date_type, :reactivation_date_type attr_accessor :deactivation_date_type, :reactivation_date_type
scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) } scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) }
scope :deactivations_with_reactivation, -> { where.not(reactivation_date: nil) }
end end

6
app/models/validations/shared_validations.rb

@ -102,7 +102,11 @@ module Validations::SharedValidations
return unless %i[reactivating_soon activating_soon deactivated].include?(status) return unless %i[reactivating_soon activating_soon deactivated].include?(status)
closest_reactivation = resource.last_deactivation_before(date) closest_reactivation = resource.last_deactivation_before(date)
open_deactivation = resource.open_deactivation open_deactivation = if resource.is_a?(Location)
resource.open_deactivation || resource.scheme.open_deactivation
else
resource.open_deactivation
end
date = case status date = case status
when :reactivating_soon then closest_reactivation.reactivation_date when :reactivating_soon then closest_reactivation.reactivation_date

13
app/views/locations/index.html.erb

@ -56,10 +56,17 @@
<% end %> <% end %>
<% end %> <% end %>
<% if status_hint_message = scheme_status_hint(@scheme) %>
<div class="govuk-hint">
<%= status_hint_message %>
</div>
<br>
<% end %>
<% if LocationPolicy.new(current_user, @scheme.locations.new).create? %> <% if LocationPolicy.new(current_user, @scheme.locations.new).create? %>
<%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post", secondary: true %> <%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post" %>
<% end %> <% end %>
<br>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "locations" } %>
</div> </div>
</div> </div>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "locations" } %>

41
app/views/schemes/deactivate_confirm.html.erb

@ -2,16 +2,35 @@
<% content_for :before_content do %> <% content_for :before_content do %>
<%= govuk_back_link(href: :back) %> <%= govuk_back_link(href: :back) %>
<% end %> <% end %>
<h1 class="govuk-heading-l"> <div class="govuk-grid-row">
<span class="govuk-caption-l"><%= @scheme.service_name %></span> <div class="govuk-grid-column-two-thirds">
This change will affect <%= @affected_logs.count %> logs
</h1> <h1 class="govuk-heading-l">
<%= govuk_warning_text text: I18n.t("warnings.scheme.deactivate.review_logs") %> <span class="govuk-caption-l"><%= @scheme.service_name %></span>
<%= f.hidden_field :confirm, value: true %> <%= affected_title(@affected_logs, @affected_locations) %>
<%= f.hidden_field :deactivation_date, value: @deactivation_date %> </h1>
<%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %>
<div class="govuk-button-group"> <% if @affected_logs.count > 0 %>
<%= f.govuk_submit "Deactivate this scheme" %> <p>
<%= govuk_button_link_to "Cancel", scheme_details_path(@scheme), html: { method: :get }, secondary: true %> <%= pluralize(@affected_logs.count, "existing log") %> using this scheme <%= @affected_logs.count == 1 ? "has" : "have" %> a tenancy start date after <%= @deactivation_date.to_formatted_s(:govuk_date) %>.
</p>
<%= govuk_warning_text text: I18n.t("warnings.scheme.deactivate.review_logs"), html_attributes: { class: "" } %>
<% end %>
<% if @affected_locations.count > 0 %>
<p>
This scheme has <%= pluralize(@affected_locations.count, "location") %> active on <%= @deactivation_date.to_formatted_s(:govuk_date) %>. <%= @affected_locations.count == 1 ? "This location" : "These locations" %> will deactivate on that date. If the scheme is ever reactivated, <%= @affected_locations.count == 1 ? "this location" : "these locations" %> will reactivate as well.
</p>
<br>
<% end %>
<%= f.hidden_field :confirm, value: true %>
<%= f.hidden_field :deactivation_date, value: @deactivation_date %>
<%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %>
<div class="govuk-button-group">
<%= f.govuk_submit "Deactivate this scheme" %>
<%= govuk_button_link_to "Cancel", scheme_details_path(@scheme), html: { method: :get }, secondary: true %>
</div>
</div>
</div> </div>
<% end %> <% end %>

13
app/views/schemes/toggle_active.html.erb

@ -3,7 +3,7 @@
<% content_for :before_content do %> <% content_for :before_content do %>
<%= govuk_back_link( <%= govuk_back_link(
href: scheme_details_path(@scheme), href: scheme_path(@scheme),
) %> ) %>
<% end %> <% end %>
@ -12,11 +12,12 @@
<div class="govuk-grid-column-two-thirds"> <div class="govuk-grid-column-two-thirds">
<% start_date = FormHandler.instance.earliest_open_for_editing_collection_start_date %> <% start_date = FormHandler.instance.earliest_open_for_editing_collection_start_date %>
<%= f.govuk_error_summary %> <%= f.govuk_error_summary %>
<span class="govuk-caption-m"><%= title %></span>
<h1 class="govuk-heading-m"><%= I18n.t("questions.scheme.toggle_active.apply_from") %></h1>
<%= govuk_warning_text text: I18n.t("warnings.scheme.#{action}.existing_logs") %>
<p class="govuk-hint"><%= I18n.t("hints.scheme.toggle_active", date: start_date.to_formatted_s(:govuk_date)) %></p>
<%= f.govuk_radio_buttons_fieldset date_type_question(action), <%= f.govuk_radio_buttons_fieldset date_type_question(action),
legend: { text: I18n.t("questions.scheme.toggle_active.apply_from") }, legend: { text: I18n.t("questions.scheme.toggle_active.apply_from"), hidden: true } do %>
caption: { text: title },
hint: { text: I18n.t("hints.scheme.toggle_active", date: start_date.to_formatted_s(:govuk_date)) } do %>
<%= govuk_warning_text text: I18n.t("warnings.scheme.#{action}.existing_logs") %>
<%= f.govuk_radio_button date_type_question(action), <%= f.govuk_radio_button date_type_question(action),
"default", "default",
label: { text: "From the start of the open collection period (#{start_date.to_formatted_s(:govuk_date)})" } %> label: { text: "From the start of the open collection period (#{start_date.to_formatted_s(:govuk_date)})" } %>
@ -26,7 +27,7 @@
**basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "scheme") do %> **basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "scheme") do %>
<%= f.govuk_date_field date_question(action), <%= f.govuk_date_field date_question(action),
legend: { text: "Date", size: "m" }, legend: { text: "Date", size: "m" },
hint: { text: "For example, 27 3 2022" }, hint: { text: "For example, 27 3 2025" },
width: 20 %> width: 20 %>
<% end %> <% end %>
<% end %> <% end %>

2
spec/fixtures/files/locations_csv_export.csv vendored

@ -1,2 +1,2 @@
scheme_code,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates scheme_code,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates
,,SW1A 2AA,Downing Street,deactivating_soon,Westminster,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022 to 25 December 2023, Deactivated on 26 December 2023" ,,SW1A 2AA,Downing Street,deactivating_soon,Westminster,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2023 to 25 December 2023, Deactivated on 26 December 2023"

1 scheme_code location_code location_postcode location_name location_status location_local_authority location_units location_type_of_unit location_mobility_type location_active_dates
2 SW1A 2AA Downing Street deactivating_soon Westminster 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022 to 25 December 2023, Deactivated on 26 December 2023 Active from 1 April 2023 to 25 December 2023, Deactivated on 26 December 2023

2
spec/fixtures/files/schemes_and_locations_csv_export.csv vendored

@ -1,2 +1,2 @@
scheme_code,scheme_service_name,scheme_status,scheme_confidential,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_support_services_provided_by,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,scheme_active_dates,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates scheme_code,scheme_service_name,scheme_status,scheme_confidential,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_support_services_provided_by,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,scheme_active_dates,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates
,Test name,active,Yes,Housing for older people,No,MHCLG,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020 to 31 March 2022, Deactivated on 1 April 2022, Active from 1 April 2023",,SW1A 2AA,Downing Street,deactivating_soon,Westminster,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022 to 25 December 2023, Deactivated on 26 December 2023" ,Test name,active,Yes,Housing for older people,No,MHCLG,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020 to 31 March 2022, Deactivated on 1 April 2022, Active from 1 April 2023",,SW1A 2AA,Downing Street,deactivating_soon,Westminster,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2023 to 25 December 2023, Deactivated on 26 December 2023"

1 scheme_code scheme_service_name scheme_status scheme_confidential scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_support_services_provided_by scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at scheme_active_dates location_code location_postcode location_name location_status location_local_authority location_units location_type_of_unit location_mobility_type location_active_dates
2 Test name active Yes Housing for older people No MHCLG The same organisation that owns the housing stock People with alcohol problems Yes Older people with support needs High level Medium stay 2021-04-01T00:00:00+01:00 Active from 1 April 2020 to 31 March 2022, Deactivated on 1 April 2022, Active from 1 April 2023 SW1A 2AA Downing Street deactivating_soon Westminster 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022 to 25 December 2023, Deactivated on 26 December 2023 Active from 1 April 2023 to 25 December 2023, Deactivated on 26 December 2023

33
spec/models/location_spec.rb

@ -930,6 +930,39 @@ RSpec.describe Location, type: :model do
expect(location.status).to eq(:activating_soon) expect(location.status).to eq(:activating_soon)
end end
end end
context "when the scheme the location belongs to is deactivated" do
before do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.yesterday, scheme: location.scheme)
location.save!
end
it "returns deactivated" do
expect(location.status).to eq(:deactivated)
end
end
context "when the scheme the location belongs to is deactivating soon" do
before do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.today + 1.month, scheme: location.scheme)
location.save!
end
it "returns deactivating soon" do
expect(location.status).to eq(:deactivating_soon)
end
end
context "when the scheme the location belongs to is reactivating soon" do
before do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.yesterday, reactivation_date: Time.zone.tomorrow, scheme: location.scheme)
location.save!
end
it "returns reactivating soon" do
expect(location.status).to eq(:reactivating_soon)
end
end
end end
describe "status_at" do describe "status_at" do

31
spec/requests/schemes_controller_spec.rb

@ -612,9 +612,9 @@ RSpec.describe SchemesController, type: :request do
context "with scheme that's deactivating soon" do context "with scheme that's deactivating soon" do
let(:scheme_deactivation_period) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), scheme:) } let(:scheme_deactivation_period) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), scheme:) }
it "does not render toggle scheme link" do it "does render the reactivate this scheme button" do
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(page).not_to have_link("Reactivate this scheme") expect(page).to have_link("Reactivate this scheme")
expect(page).not_to have_link("Deactivate this scheme") expect(page).not_to have_link("Deactivate this scheme")
end end
end end
@ -680,9 +680,9 @@ RSpec.describe SchemesController, type: :request do
context "with scheme that's deactivating soon" do context "with scheme that's deactivating soon" do
let(:scheme_deactivation_period) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), scheme: specific_scheme) } let(:scheme_deactivation_period) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12), scheme: specific_scheme) }
it "does not render toggle scheme link" do it "does render the reactivate this scheme button" do
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(page).not_to have_link("Reactivate this scheme") expect(page).to have_link("Reactivate this scheme")
expect(page).not_to have_link("Deactivate this scheme") expect(page).not_to have_link("Deactivate this scheme")
end end
end end
@ -784,6 +784,7 @@ RSpec.describe SchemesController, type: :request do
context "and associated logs in editable collection period" do context "and associated logs in editable collection period" do
before do before do
create(:location, scheme:)
create(:lettings_log, :sh, scheme:, startdate: Time.zone.local(2022, 9, 9), owning_organisation: user.organisation) create(:lettings_log, :sh, scheme:, startdate: Time.zone.local(2022, 9, 9), owning_organisation: user.organisation)
get "/schemes/#{scheme.id}" get "/schemes/#{scheme.id}"
end end
@ -2533,14 +2534,18 @@ RSpec.describe SchemesController, type: :request do
it "redirects to the confirmation page" do it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} logs") expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} log and 1 location.")
end end
end end
context "and no affected logs" do context "and no affected logs" do
let(:setup_schemes) { scheme.lettings_logs.update(scheme: nil) } let(:setup_schemes) { scheme.lettings_logs.update(scheme: nil) }
it "redirects to the location page and updates the deactivation period" do before do
create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 1), reactivation_date: nil, location:)
end
it "redirects to the scheme page and updates the deactivation period" do
follow_redirect! follow_redirect!
follow_redirect! follow_redirect!
follow_redirect! follow_redirect!
@ -2560,14 +2565,18 @@ RSpec.describe SchemesController, type: :request do
it "redirects to the confirmation page" do it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} logs") expect(page).to have_content("This change will affect #{scheme.lettings_logs.count} log and 1 location.")
end end
end end
context "and no affected logs" do context "and no affected logs" do
let(:setup_schemes) { scheme.lettings_logs.update(scheme: nil) } let(:setup_schemes) { scheme.lettings_logs.update(scheme: nil) }
it "redirects to the location page and updates the deactivation period" do before do
create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 5), reactivation_date: nil, location:)
end
it "redirects to the scheme page and updates the deactivation period" do
follow_redirect! follow_redirect!
follow_redirect! follow_redirect!
follow_redirect! follow_redirect!
@ -2751,6 +2760,10 @@ RSpec.describe SchemesController, type: :request do
let(:params) { { scheme_deactivation_period: { deactivation_date_type: "other", "deactivation_date(3i)": "8", "deactivation_date(2i)": "9", "deactivation_date(1i)": "2023" } } } let(:params) { { scheme_deactivation_period: { deactivation_date_type: "other", "deactivation_date(3i)": "8", "deactivation_date(2i)": "9", "deactivation_date(1i)": "2023" } } }
let(:add_deactivations) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2023, 6, 5), reactivation_date: nil, scheme:) } let(:add_deactivations) { create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2023, 6, 5), reactivation_date: nil, scheme:) }
before do
create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 4, 5), reactivation_date: nil, location:)
end
it "redirects to the scheme page and updates the existing deactivation period" do it "redirects to the scheme page and updates the existing deactivation period" do
follow_redirect! follow_redirect!
follow_redirect! follow_redirect!
@ -2771,7 +2784,7 @@ RSpec.describe SchemesController, type: :request do
it "redirects to the confirmation page" do it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(page).to have_content("This change will affect 1 logs") expect(page).to have_content("This change will affect 1 log and 1 location.")
end end
end end
end end

46
spec/views/schemes/deactivate_confirm.html.erb_spec.rb

@ -0,0 +1,46 @@
require "rails_helper"
RSpec.describe "schemes/deactivate_confirm.html.erb", type: :view do
let(:scheme) { create(:scheme, service_name: "ABCScheme") }
let(:deactivation_date) { Time.zone.today + 1.month }
let(:affected_logs) { create_list(:lettings_log, 2, scheme:, status: 1) }
let(:affected_locations) { create_list(:location, 3, scheme:) }
let(:scheme_deactivation_period) { SchemeDeactivationPeriod.new }
before do
assign(:scheme, scheme)
assign(:deactivation_date, deactivation_date)
assign(:affected_logs, affected_logs)
assign(:affected_locations, affected_locations)
assign(:scheme_deactivation_period, scheme_deactivation_period)
render
end
it "displays the service name in the caption" do
expect(rendered).to have_css("span.govuk-caption-l", text: scheme.service_name)
end
it "displays the correct heading" do
expect(rendered).to have_css("h1.govuk-heading-l", text: "This change will affect 2 logs and 3 locations.")
end
it "displays the affected logs count" do
expect(rendered).to have_text("2 existing logs using this scheme have a tenancy start date after #{deactivation_date.to_formatted_s(:govuk_date)}.")
end
it "displays the warning text" do
expect(rendered).to have_css(".govuk-warning-text", text: I18n.t("warnings.scheme.deactivate.review_logs"))
end
it "displays the affected locations count" do
expect(rendered).to have_text("This scheme has 3 locations active on #{deactivation_date.to_formatted_s(:govuk_date)}.")
end
it "renders the submit button" do
expect(rendered).to have_button("Deactivate this scheme")
end
it "renders the cancel button" do
expect(rendered).to have_link("Cancel", href: scheme_details_path(scheme))
end
end
Loading…
Cancel
Save