Browse Source

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
pull/1018/head
kosiakkatrina 2 years ago committed by GitHub
parent
commit
11bb9c887c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 68
      app/controllers/locations_controller.rb
  2. 38
      app/controllers/schemes_controller.rb
  3. 42
      app/helpers/locations_helper.rb
  4. 17
      app/helpers/toggle_active_location_helper.rb
  5. 41
      app/models/location.rb
  6. 46
      app/models/location_deactivation_period.rb
  7. 28
      app/models/scheme.rb
  8. 21
      app/models/scheme_deactivation_period.rb
  9. 4
      app/views/locations/deactivate_confirm.html.erb
  10. 6
      app/views/locations/show.html.erb
  11. 20
      app/views/locations/toggle_active.html.erb
  12. 2
      app/views/schemes/deactivate_confirm.html.erb
  13. 2
      app/views/schemes/toggle_active.html.erb
  14. 14
      config/locales/en.yml
  15. 2
      config/routes.rb
  16. 1
      spec/factories/location_deactivation_period.rb
  17. 42
      spec/features/schemes_spec.rb
  18. 183
      spec/helpers/locations_helper_spec.rb
  19. 5
      spec/helpers/schemes_helper_spec.rb
  20. 41
      spec/models/location_spec.rb
  21. 34
      spec/models/scheme_spec.rb
  22. 220
      spec/requests/locations_controller_spec.rb
  23. 22
      spec/requests/schemes_controller_spec.rb

68
app/controllers/locations_controller.rb

@ -21,14 +21,16 @@ class LocationsController < ApplicationController
def show; end def show; end
def new_deactivation def new_deactivation
if params[:location].blank? @location_deactivation_period = LocationDeactivationPeriod.new
if params[:location_deactivation_period].blank?
render "toggle_active", locals: { action: "deactivate" } render "toggle_active", locals: { action: "deactivate" }
else else
@location.run_deactivation_validations! @location_deactivation_period.deactivation_date = toggle_date("deactivation_date")
@location.deactivation_date = deactivation_date @location_deactivation_period.deactivation_date_type = params[:location_deactivation_period][:deactivation_date_type]
@location.deactivation_date_type = params[:location][:deactivation_date_type] @location_deactivation_period.location = @location
if @location.valid? if @location_deactivation_period.valid?
redirect_to scheme_location_deactivate_confirm_path(@location, deactivation_date: @location.deactivation_date, deactivation_date_type: @location.deactivation_date_type) 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 else
render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity
end end
@ -41,18 +43,31 @@ class LocationsController < ApplicationController
end end
def deactivate def deactivate
@location.run_deactivation_validations! if @location.location_deactivation_periods.create!(deactivation_date: params[:deactivation_date]) && reset_location_and_scheme_for_logs!
if @location.location_deactivation_periods.create!(deactivation_date:) && update_affected_logs
flash[:notice] = deactivate_success_notice flash[:notice] = deactivate_success_notice
end end
redirect_to scheme_location_path(@scheme, @location) redirect_to scheme_location_path(@scheme, @location)
end end
def reactivate def new_reactivation
@location_deactivation_period = LocationDeactivationPeriod.deactivations_without_reactivation.first
render "toggle_active", locals: { action: "reactivate" } render "toggle_active", locals: { action: "reactivate" }
end 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 def create
if date_params_missing?(location_params) || valid_date_params?(location_params) if date_params_missing?(location_params) || valid_date_params?(location_params)
@location = Location.new(location_params) @location = Location.new(location_params)
@ -167,7 +182,7 @@ private
end end
def location_params 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[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode]
required_params required_params
end end
@ -185,26 +200,35 @@ private
when :deactivated when :deactivated
"#{@location.name} has been deactivated" "#{@location.name} has been deactivated"
when :deactivating_soon 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
end end
def update_affected_logs def reset_location_and_scheme_for_logs!
@location.lettings_logs.filter_by_before_startdate(deactivation_date.to_time).update!(location: nil, scheme: nil) @location.lettings_logs.filter_by_before_startdate(params[:deactivation_date].to_time).update!(location: nil, scheme: nil)
end end
def deactivation_date def toggle_date(key)
if params[:location].blank? if params[:location_deactivation_period].blank?
return 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 return FormHandler.instance.current_collection_start_date
elsif params[:location][:deactivation_date].present? elsif params[:location_deactivation_period][key.to_sym].present?
return params[:location][:deactivation_date] return params[:location_deactivation_period][key.to_sym]
end end
day = params[:location]["deactivation_date(3i)"] day = params[:location_deactivation_period]["#{key}(3i)"]
month = params[:location]["deactivation_date(2i)"] month = params[:location_deactivation_period]["#{key}(2i)"]
year = params[:location]["deactivation_date(1i)"] year = params[:location_deactivation_period]["#{key}(1i)"]
return nil if [day, month, year].any?(&:blank?) 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) 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)

38
app/controllers/schemes_controller.rb

@ -22,14 +22,16 @@ class SchemesController < ApplicationController
end end
def new_deactivation def new_deactivation
if params[:scheme].blank? @scheme_deactivation_period = SchemeDeactivationPeriod.new
if params[:scheme_deactivation_period].blank?
render "toggle_active", locals: { action: "deactivate" } render "toggle_active", locals: { action: "deactivate" }
else else
@scheme.run_deactivation_validations = true @scheme_deactivation_period.deactivation_date = deactivation_date
@scheme.deactivation_date = deactivation_date @scheme_deactivation_period.deactivation_date_type = params[:scheme_deactivation_period][:deactivation_date_type]
@scheme.deactivation_date_type = params[:scheme][:deactivation_date_type] @scheme_deactivation_period.scheme = @scheme
if @scheme.valid? if @scheme_deactivation_period.validate
redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme.deactivation_date, deactivation_date_type: @scheme.deactivation_date_type) redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme_deactivation_period.deactivation_date, deactivation_date_type: @scheme_deactivation_period.deactivation_date_type)
else else
render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity
end end
@ -42,9 +44,7 @@ class SchemesController < ApplicationController
end end
def deactivate def deactivate
@scheme.run_deactivation_validations! if @scheme.scheme_deactivation_periods.create!(deactivation_date: params[:deactivation_date]) && reset_location_and_scheme_for_logs!
if @scheme.scheme_deactivation_periods.create!(deactivation_date:) && update_affected_logs
flash[:notice] = deactivate_success_notice flash[:notice] = deactivate_success_notice
end end
redirect_to scheme_details_path(@scheme) redirect_to scheme_details_path(@scheme)
@ -299,28 +299,28 @@ private
when :deactivated when :deactivated
"#{@scheme.service_name} has been deactivated" "#{@scheme.service_name} has been deactivated"
when :deactivating_soon 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
end end
def deactivation_date def deactivation_date
if params[:scheme].blank? if params[:scheme_deactivation_period].blank?
return return
elsif params[:scheme][:deactivation_date_type] == "default" elsif params[:scheme_deactivation_period][:deactivation_date_type] == "default"
return FormHandler.instance.current_collection_start_date return FormHandler.instance.current_collection_start_date
elsif params[:scheme][:deactivation_date].present? elsif params[:scheme_deactivation_period][:deactivation_date].present?
return params[:scheme][:deactivation_date] return params[:scheme_deactivation_period][:deactivation_date]
end end
day = params[:scheme]["deactivation_date(3i)"] day = params[:scheme_deactivation_period]["deactivation_date(3i)"]
month = params[:scheme]["deactivation_date(2i)"] month = params[:scheme_deactivation_period]["deactivation_date(2i)"]
year = params[:scheme]["deactivation_date(1i)"] year = params[:scheme_deactivation_period]["deactivation_date(1i)"]
return nil if [day, month, year].any?(&:blank?) 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) Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i)
end end
def update_affected_logs def reset_location_and_scheme_for_logs!
@scheme.lettings_logs.filter_by_before_startdate(deactivation_date.to_time).update!(location: nil, scheme: nil) @scheme.lettings_logs.filter_by_before_startdate(params[:deactivation_date].to_time).update!(location: nil, scheme: nil)
end end
end end

42
app/helpers/locations_helper.rb

@ -42,12 +42,44 @@ module LocationsHelper
base_attributes base_attributes
end 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) def location_availability(location)
availability = "Active from #{location.available_from.to_formatted_s(:govuk_date)}" availability = ""
location.location_deactivation_periods.each do |deactivation| active_periods(location).each do |period|
availability << " to #{(deactivation.deactivation_date - 1.day).to_formatted_s(:govuk_date)}\nDeactivated on #{deactivation.deactivation_date.to_formatted_s(:govuk_date)}" if period.from.present?
availability << "\nActive from #{deactivation.reactivation_date.to_formatted_s(:govuk_date)}" if deactivation.reactivation_date.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 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
end end

17
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

41
app/models/location.rb

@ -1,6 +1,5 @@
class Location < ApplicationRecord class Location < ApplicationRecord
validate :validate_postcode validate :validate_postcode
validate :deactivation_date_errors
validates :units, :type_of_unit, :mobility_type, presence: true validates :units, :type_of_unit, :mobility_type, presence: true
belongs_to :scheme belongs_to :scheme
has_many :lettings_logs, class_name: "LettingsLog" has_many :lettings_logs, class_name: "LettingsLog"
@ -12,7 +11,7 @@ class Location < ApplicationRecord
auto_strip_attributes :name 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_postcode, ->(postcode) { where("REPLACE(postcode, ' ', '') ILIKE ?", "%#{postcode.delete(' ')}%") }
scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") } scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") }
@ -371,44 +370,26 @@ class Location < ApplicationRecord
end end
def available_from def available_from
startdate || created_at startdate || [created_at, FormHandler.instance.current_collection_start_date].min
end end
def status def status
recent_deactivation = location_deactivation_periods.deactivations_without_reactivation.first open_deactivation = location_deactivation_periods.deactivations_without_reactivation.first
return :active if recent_deactivation.blank? recent_deactivation = location_deactivation_periods.order("created_at").last
return :deactivating_soon if Time.zone.now < recent_deactivation.deactivation_date
: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 end
def active? def active?
status == :active status == :active
end end
def run_deactivation_validations! def reactivating_soon?
@run_deactivation_validations = true status == :reactivating_soon
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
end end
private private

46
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 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) } scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) }
end end

28
app/models/scheme.rb

@ -19,12 +19,9 @@ class Scheme < ApplicationRecord
} }
validate :validate_confirmed validate :validate_confirmed
validate :deactivation_date_errors
auto_strip_attributes :service_name auto_strip_attributes :service_name
attr_accessor :deactivation_date_type, :deactivation_date, :run_deactivation_validations
SENSITIVE = { SENSITIVE = {
No: 0, No: 0,
Yes: 1, Yes: 1,
@ -227,29 +224,4 @@ class Scheme < ApplicationRecord
def active? def active?
status == :active status == :active
end 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 end

21
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 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) } scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) }
end end

4
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 %> <% content_for :before_content do %>
<%= govuk_back_link(href: :back) %> <%= govuk_back_link(href: :back) %>
<% end %> <% end %>
@ -6,7 +6,7 @@
<span class="govuk-caption-l"><%= @location.postcode %></span> <span class="govuk-caption-l"><%= @location.postcode %></span>
This change will affect <%= @location.lettings_logs.count %> logs This change will affect <%= @location.lettings_logs.count %> logs
</h1> </h1>
<%= 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 :confirm, value: true %>
<%= f.hidden_field :deactivation_date, value: @deactivation_date %> <%= f.hidden_field :deactivation_date, value: @deactivation_date %>
<%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %> <%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %>

6
app/views/locations/show.html.erb

@ -24,9 +24,9 @@
</div> </div>
</div> </div>
<% if FeatureToggle.location_toggle_enabled? %> <% if FeatureToggle.location_toggle_enabled? %>
<% if @location.active? %> <% if @location.active? || @location.reactivating_soon? %>
<%= govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(scheme_id: @scheme.id, location_id: @location.id), warning: true %> <%= govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(@scheme, @location), warning: true %>
<% else %> <% 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 %>
<% end %> <% end %>

20
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 :title, title %>
<% content_for :before_content do %> <% content_for :before_content do %>
@ -8,25 +8,25 @@
) %> ) %>
<% end %> <% 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| %>
<div class="govuk-grid-row"> <div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds"> <div class="govuk-grid-column-two-thirds">
<% collection_start_date = FormHandler.instance.current_collection_start_date %> <% collection_start_date = FormHandler.instance.current_collection_start_date %>
<%= f.govuk_error_summary %> <%= f.govuk_error_summary %>
<%= f.govuk_radio_buttons_fieldset :deactivation_date_type, <%= f.govuk_radio_buttons_fieldset date_type_question(action),
legend: { text: I18n.t("questions.location.deactivation.apply_from") }, legend: { text: I18n.t("questions.location.toggle_active.apply_from") },
caption: { text: "Deactivate #{@location.postcode}" }, caption: { text: title },
hint: { text: I18n.t("hints.location.deactivation", date: collection_start_date.to_formatted_s(:govuk_date)) } do %> 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.deactivation.existing_logs") %> <%= govuk_warning_text text: I18n.t("warnings.location.#{action}.existing_logs") %>
<%= f.govuk_radio_button :deactivation_date_type, <%= f.govuk_radio_button date_type_question(action),
"default", "default",
label: { text: "From the start of the current collection period (#{collection_start_date.to_formatted_s(:govuk_date)})" } %> 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", "other",
label: { text: "For tenancies starting after a certain date" }, label: { text: "For tenancies starting after a certain date" },
**basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "location") do %> **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" }, legend: { text: "Date", size: "m" },
hint: { text: "For example, 27 3 2022" }, hint: { text: "For example, 27 3 2022" },
width: 20 %> width: 20 %>

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

@ -1,6 +1,6 @@
<% title = "Deactivate #{@scheme.service_name}" %> <% title = "Deactivate #{@scheme.service_name}" %>
<% content_for :title, title %> <% 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 %> <% content_for :before_content do %>
<%= govuk_back_link(href: :back) %> <%= govuk_back_link(href: :back) %>
<% end %> <% end %>

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

@ -6,7 +6,7 @@
href: scheme_details_path(@scheme), href: scheme_details_path(@scheme),
) %> ) %>
<% end %> <% 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| %>
<div class="govuk-grid-row"> <div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds"> <div class="govuk-grid-column-two-thirds">
<% collection_start_date = FormHandler.instance.current_collection_start_date %> <% collection_start_date = FormHandler.instance.current_collection_start_date %>

14
config/locales/en.yml

@ -319,10 +319,14 @@ en:
out_of_range: "The date must be on or after the %{date}" out_of_range: "The date must be on or after the %{date}"
location: location:
deactivation_date: toggle_date:
not_selected: "Select one of the options" not_selected: "Select one of the options"
invalid: "Enter a valid day, month and year" invalid: "Enter a valid day, month and year"
out_of_range: "The date must be on or after the %{date}" 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: soft_validations:
net_income: net_income:
@ -374,7 +378,7 @@ en:
startdate: "When did the first property in this location become available under this scheme? (optional)" 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?" 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?" 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?" apply_from: "When should this change apply?"
scheme: scheme:
deactivation: deactivation:
@ -391,15 +395,17 @@ en:
postcode: "For example, SW1P 4DF." postcode: "For example, SW1P 4DF."
name: "This is how you refer to this location within your organisation" 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." 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: scheme:
deactivation: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed." deactivation: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed."
warnings: warnings:
location: 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." 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." 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: scheme:
deactivation: 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." 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."

2
config/routes.rb

@ -61,8 +61,10 @@ Rails.application.routes.draw do
get "new-deactivation", to: "locations#new_deactivation" get "new-deactivation", to: "locations#new_deactivation"
get "deactivate-confirm", to: "locations#deactivate_confirm" get "deactivate-confirm", to: "locations#deactivate_confirm"
get "reactivate", to: "locations#reactivate" get "reactivate", to: "locations#reactivate"
get "new-reactivation", to: "locations#new_reactivation"
patch "new-deactivation", to: "locations#new_deactivation" patch "new-deactivation", to: "locations#new_deactivation"
patch "deactivate", to: "locations#deactivate" patch "deactivate", to: "locations#deactivate"
patch "reactivate", to: "locations#reactivate"
end end
end end

1
spec/factories/location_deactivation_period.rb

@ -1,5 +1,6 @@
FactoryBot.define do FactoryBot.define do
factory :location_deactivation_period do factory :location_deactivation_period do
deactivation_date { Time.zone.local(2022, 4, 1) }
reactivation_date { nil } reactivation_date { nil }
end end
end end

42
spec/features/schemes_spec.rb

@ -693,8 +693,10 @@ RSpec.describe "Schemes scheme Features" do
context "when I click to see individual scheme" do context "when I click to see individual scheme" do
let(:scheme) { schemes.first } let(:scheme) { schemes.first }
let!(:location) { FactoryBot.create(:location, startdate: Time.zone.local(2022, 4, 4), scheme:) } 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 before do
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location: deactivated_location)
click_link(scheme.service_name) click_link(scheme.service_name)
end end
@ -752,6 +754,46 @@ RSpec.describe "Schemes scheme Features" do
expect(page).to have_current_path("/schemes/#{scheme.id}/locations") expect(page).to have_current_path("/schemes/#{scheme.id}/locations")
end 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 context "when I click to change location name" do
before do before do
click_link(location.postcode) click_link(location.postcode)

183
spec/helpers/locations_helper_spec.rb

@ -47,8 +47,94 @@ RSpec.describe LocationsHelper do
end end
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 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 it "returns correct display attributes" do
attributes = [ attributes = [
@ -59,7 +145,7 @@ RSpec.describe LocationsHelper do
{ name: "Common type of unit", value: location.type_of_unit }, { name: "Common type of unit", value: location.type_of_unit },
{ name: "Mobility type", value: location.mobility_type }, { name: "Mobility type", value: location.mobility_type },
{ name: "Code", value: location.location_code }, { 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 }, { name: "Status", value: :active },
] ]
@ -67,25 +153,110 @@ RSpec.describe LocationsHelper do
end end
context "when viewing availability" do 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 it "displays created_at as availability date if startdate is not present" do
location.update!(startdate: nil) location.update!(startdate: nil)
availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value]
expect(availability_attribute).to eq("Active from #{location.created_at.to_formatted_s(:govuk_date)}") expect(availability_attribute).to eq("Active from #{location.created_at.to_formatted_s(:govuk_date)}")
end 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 end
context "with previous deactivations" do 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 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)) FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 10), reactivation_date: Time.zone.local(2022, 12, 1), location:)
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, 11, 11), reactivation_date: Time.zone.local(2022, 12, 11), location:)
location.reload
end end
it "displays the timeline of availability" do it "displays the timeline of availability" do
availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value] availability_attribute = display_location_attributes(location).find { |x| x[:name] == "Availability" }[:value]
expect(availability_attribute).to eq("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 end
end end

5
spec/helpers/schemes_helper_spec.rb

@ -35,8 +35,9 @@ RSpec.describe SchemesHelper do
context "with previous deactivations" do context "with previous deactivations" do
before 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:)
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, 9, 15), reactivation_date: nil, scheme:)
scheme.reload
end end
it "displays the timeline of availability" do it "displays the timeline of availability" do

41
spec/models/location_spec.rb

@ -113,7 +113,7 @@ RSpec.describe Location, type: :model do
end end
describe "status" do describe "status" do
let(:location) { FactoryBot.build(:location) } let(:location) { FactoryBot.build(:location, startdate: Time.zone.local(2022, 4, 1)) }
before do before do
Timecop.freeze(2022, 6, 7) Timecop.freeze(2022, 6, 7)
@ -129,27 +129,34 @@ RSpec.describe Location, type: :model do
end end
it "returns deactivating soon if deactivation_date is in the future" do 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! location.save!
expect(location.status).to eq(:deactivating_soon) expect(location.status).to eq(:deactivating_soon)
end end
it "returns deactivated if deactivation_date is in the past" do 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! location.save!
expect(location.status).to eq(:deactivated) expect(location.status).to eq(:deactivated)
end end
it "returns deactivated if deactivation_date is today" do 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! location.save!
expect(location.status).to eq(:deactivated) expect(location.status).to eq(:deactivated)
end 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 end
context "when there have been previous deactivations" do context "when there have been previous deactivations" do
before 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 end
it "returns active if the location has no relevant deactivation records" do it "returns active if the location has no relevant deactivation records" do
@ -157,30 +164,36 @@ RSpec.describe Location, type: :model do
end end
it "returns deactivating soon if deactivation_date is in the future" do 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! location.save!
expect(location.status).to eq(:deactivating_soon) expect(location.status).to eq(:deactivating_soon)
end end
it "returns deactivated if deactivation_date is in the past" do 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! location.save!
expect(location.status).to eq(:deactivated) expect(location.status).to eq(:deactivated)
end end
it "returns deactivated if deactivation_date is today" do 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! location.save!
expect(location.status).to eq(:deactivated) expect(location.status).to eq(:deactivated)
end end
end
end
describe "with deactivation_date (but no deactivation_date_type)" do it "returns reactivating soon if the location has a future reactivation date" do
let(:location) { FactoryBot.create(:location, deactivation_date: Date.new(2022, 4, 1)) } 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 it "returns if the location had a deactivation during another deactivation" do
expect(location).to be_valid 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 end
end end

34
spec/models/scheme_spec.rb

@ -109,27 +109,27 @@ RSpec.describe Scheme, type: :model do
end end
it "returns deactivating soon if deactivation_date is in the future" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivating_soon) expect(scheme.status).to eq(:deactivating_soon)
end end
it "returns deactivated if deactivation_date is in the past" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivated) expect(scheme.status).to eq(:deactivated)
end end
it "returns deactivated if deactivation_date is today" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivated) expect(scheme.status).to eq(:deactivated)
end end
end end
context "when there have been previous deactivations" do context "when there have been previous deactivations" do
before 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 end
it "returns active if the scheme has no relevant deactivation records" do it "returns active if the scheme has no relevant deactivation records" do
@ -137,30 +137,22 @@ RSpec.describe Scheme, type: :model do
end end
it "returns deactivating soon if deactivation_date is in the future" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivating_soon) expect(scheme.status).to eq(:deactivating_soon)
end end
it "returns deactivated if deactivation_date is in the past" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivated) expect(scheme.status).to eq(:deactivated)
end end
it "returns deactivated if deactivation_date is today" do 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)) FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:)
scheme.save! scheme.reload
expect(scheme.status).to eq(:deactivated) expect(scheme.status).to eq(:deactivated)
end end
end 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 end

220
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 context "when signed in as a data coordinator" do
let(:user) { FactoryBot.create(:user, :data_coordinator) } let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } 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(:deactivation_date) { Time.utc(2022, 10, 10) }
let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location:, scheme:, startdate:, owning_organisation: user.organisation) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location:, scheme:, startdate:, owning_organisation: user.organisation) }
let(:startdate) { Time.utc(2022, 10, 11) } let(:startdate) { Time.utc(2022, 10, 11) }
let(:add_deactivations) { nil }
before do before do
Timecop.freeze(Time.utc(2022, 10, 10)) Timecop.freeze(Time.utc(2022, 10, 10))
sign_in user sign_in user
add_deactivations
location.save!
patch "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation", params: patch "/schemes/#{scheme.id}/locations/#{location.id}/new-deactivation", params:
end end
@ -1254,7 +1257,7 @@ RSpec.describe LocationsController, type: :request do
end end
context "with default date" do 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 it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
@ -1264,7 +1267,7 @@ RSpec.describe LocationsController, type: :request do
end end
context "with other date" do 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 it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
@ -1274,7 +1277,7 @@ RSpec.describe LocationsController, type: :request do
end end
context "when confirming deactivation" do 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 before do
Timecop.freeze(Time.utc(2022, 10, 10)) Timecop.freeze(Time.utc(2022, 10, 10))
@ -1319,56 +1322,67 @@ RSpec.describe LocationsController, type: :request do
end end
context "when the date is not selected" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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
end end
context "when invalid date is entered" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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
end end
context "when the date is entered is before the beginning of current collection window" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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
end end
context "when the day is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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
end end
context "when the month is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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
end end
context "when the year is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) 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 end
end end
@ -1399,7 +1413,7 @@ RSpec.describe LocationsController, type: :request do
context "when signed in as a data coordinator" do context "when signed in as a data coordinator" do
let(:user) { FactoryBot.create(:user, :data_coordinator) } let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } 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 } let(:add_deactivations) { location.location_deactivation_periods << location_deactivation_period }
before do before do
@ -1424,20 +1438,184 @@ RSpec.describe LocationsController, type: :request do
end end
context "with deactivated location" do 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 it "renders reactivate this location" do
expect(response).to have_http_status(:ok) 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
end end
context "with location that's deactivating soon" do 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 it "renders reactivate this location" do
expect(response).to have_http_status(:ok) 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 end
end end

22
spec/requests/schemes_controller_spec.rb

@ -270,7 +270,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "with deactivated scheme" do 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 it "renders reactivate this scheme" do
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
@ -279,7 +279,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "with scheme that's deactivating soon" do 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 it "renders reactivate this scheme" do
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
@ -1785,7 +1785,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "with default date" do 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 it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
@ -1795,7 +1795,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "with other date" do 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 it "redirects to the confirmation page" do
follow_redirect! follow_redirect!
@ -1805,7 +1805,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when confirming deactivation" do 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 before do
Timecop.freeze(Time.utc(2022, 10, 10)) Timecop.freeze(Time.utc(2022, 10, 10))
@ -1851,7 +1851,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when the date is not selected" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -1860,7 +1860,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when invalid date is entered" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -1869,7 +1869,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when the date is entered is before the beginning of current collection window" do 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 it "displays the new page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -1878,7 +1878,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when the day is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -1887,7 +1887,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when the month is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -1896,7 +1896,7 @@ RSpec.describe SchemesController, type: :request do
end end
context "when the year is not entered" do 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 it "displays page with an error message" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)

Loading…
Cancel
Save