Browse Source

feat: add scheme reactivation behaviour

pull/1023/head
natdeanlewissoftwire 4 years ago
parent
commit
1aa0550a7b
  1. 47
      app/controllers/schemes_controller.rb
  2. 42
      app/helpers/schemes_helper.rb
  3. 17
      app/helpers/toggle_active_scheme_helper.rb
  4. 17
      app/models/scheme.rb
  5. 35
      app/models/scheme_deactivation_period.rb
  6. 4
      app/views/schemes/deactivate_confirm.html.erb
  7. 4
      app/views/schemes/show.html.erb
  8. 18
      app/views/schemes/toggle_active.html.erb
  9. 20
      config/locales/en.yml
  10. 2
      config/routes.rb

47
app/controllers/schemes_controller.rb

@ -27,10 +27,10 @@ class SchemesController < ApplicationController
if params[:scheme_deactivation_period].blank?
render "toggle_active", locals: { action: "deactivate" }
else
@scheme_deactivation_period.deactivation_date = deactivation_date
@scheme_deactivation_period.deactivation_date = toggle_date("deactivation_date")
@scheme_deactivation_period.deactivation_date_type = params[:scheme_deactivation_period][:deactivation_date_type]
@scheme_deactivation_period.scheme = @scheme
if @scheme_deactivation_period.validate
if @scheme_deactivation_period.valid?
redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme_deactivation_period.deactivation_date, deactivation_date_type: @scheme_deactivation_period.deactivation_date_type)
else
render "toggle_active", locals: { action: "deactivate" }, status: :unprocessable_entity
@ -50,10 +50,25 @@ class SchemesController < ApplicationController
redirect_to scheme_details_path(@scheme)
end
def reactivate
def new_reactivation
@scheme_deactivation_period = SchemeDeactivationPeriod.deactivations_without_reactivation.first
render "toggle_active", locals: { action: "reactivate" }
end
def reactivate
@scheme_deactivation_period = SchemeDeactivationPeriod.deactivations_without_reactivation.first
@scheme_deactivation_period.reactivation_date = toggle_date("reactivation_date")
@scheme_deactivation_period.reactivation_date_type = params[:scheme_deactivation_period][:reactivation_date_type]
if @scheme_deactivation_period.update(reactivation_date: toggle_date("reactivation_date"))
flash[:notice] = reactivate_success_notice
redirect_to scheme_details_path(@scheme)
else
render "toggle_active", locals: { action: "reactivate" }, status: :unprocessable_entity
end
end
def new
@scheme = Scheme.new
end
@ -239,8 +254,7 @@ private
:support_type,
:arrangement_type,
:intended_stay,
:confirmed,
:deactivation_date)
:confirmed)
if arrangement_type_changed_to_different_org?(required_params)
required_params[:managing_organisation_id] = nil
@ -303,18 +317,27 @@ private
end
end
def deactivation_date
def reactivate_success_notice
case @scheme.status
when :active
"#{@scheme.service_name} has been reactivated"
when :reactivating_soon
"#{@scheme.service_name} will reactivate on #{toggle_date('reactivation_date').to_time.to_formatted_s(:govuk_date)}"
end
end
def toggle_date(key)
if params[:scheme_deactivation_period].blank?
return
elsif params[:scheme_deactivation_period][:deactivation_date_type] == "default"
elsif params[:scheme_deactivation_period]["#{key}_type".to_sym] == "default"
return FormHandler.instance.current_collection_start_date
elsif params[:scheme_deactivation_period][:deactivation_date].present?
return params[:scheme_deactivation_period][:deactivation_date]
elsif params[:scheme_deactivation_period][key.to_sym].present?
return params[:scheme_deactivation_period][key.to_sym]
end
day = params[:scheme_deactivation_period]["deactivation_date(3i)"]
month = params[:scheme_deactivation_period]["deactivation_date(2i)"]
year = params[:scheme_deactivation_period]["deactivation_date(1i)"]
day = params[:scheme_deactivation_period]["#{key}(3i)"]
month = params[:scheme_deactivation_period]["#{key}(2i)"]
year = params[:scheme_deactivation_period]["#{key}(1i)"]
return nil if [day, month, year].any?(&:blank?)
Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i)

42
app/helpers/schemes_helper.rb

@ -27,12 +27,44 @@ module SchemesHelper
base_attributes
end
ActivePeriod = Struct.new(:from, :to)
def active_periods(scheme)
periods = [ActivePeriod.new(scheme.available_from, nil)]
sorted_deactivation_periods = remove_nested_periods(scheme.scheme_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 scheme_availability(scheme)
availability = "Active from #{scheme.available_from.to_formatted_s(:govuk_date)}"
scheme.scheme_deactivation_periods.each do |deactivation|
availability << " to #{(deactivation.deactivation_date - 1.day).to_formatted_s(:govuk_date)}\nDeactivated on #{deactivation.deactivation_date.to_formatted_s(:govuk_date)}"
availability << "\nActive from #{deactivation.reactivation_date.to_formatted_s(:govuk_date)}" if deactivation.reactivation_date.present?
availability = ""
active_periods(scheme).each do |period|
if period.from.present?
availability << "\nActive from #{period.from.to_formatted_s(:govuk_date)}"
availability << " to #{(period.to - 1.day).to_formatted_s(:govuk_date)}\nDeactivated on #{period.to.to_formatted_s(:govuk_date)}" if period.to.present?
end
end
availability
availability.strip
end
private
def remove_overlapping_and_empty_periods(periods)
periods.select { |period| period.from.present? && (period.to.nil? || period.from < period.to) }
end
def remove_nested_periods(periods)
periods.select { |inner_period| periods.none? { |outer_period| is_nested?(inner_period, outer_period) } }
end
def is_nested?(inner, outer)
return false if inner == outer
return false if [inner.deactivation_date, inner.reactivation_date, outer.deactivation_date, outer.reactivation_date].any?(&:blank?)
[inner.deactivation_date, inner.reactivation_date].all? { |date| date.between?(outer.deactivation_date, outer.reactivation_date) }
end
end

17
app/helpers/toggle_active_scheme_helper.rb

@ -0,0 +1,17 @@
module ToggleActiveSchemeHelper
def toggle_scheme_form_path(action, scheme)
if action == "deactivate"
scheme_new_deactivation_path(scheme)
else
scheme_reactivate_path(scheme)
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

17
app/models/scheme.rb

@ -210,18 +210,25 @@ class Scheme < ApplicationRecord
end
def available_from
created_at
[created_at, FormHandler.instance.current_collection_start_date].min
end
def status
recent_deactivation = scheme_deactivation_periods.deactivations_without_reactivation.first
return :active if recent_deactivation.blank?
return :deactivating_soon if Time.zone.now < recent_deactivation.deactivation_date
open_deactivation = scheme_deactivation_periods.deactivations_without_reactivation.first
recent_deactivation = scheme_deactivation_periods.order("created_at").last
:deactivated
return :deactivated if open_deactivation&.deactivation_date.present? && Time.zone.now >= open_deactivation.deactivation_date
return :deactivating_soon if open_deactivation&.deactivation_date.present? && Time.zone.now < open_deactivation.deactivation_date
return :reactivating_soon if recent_deactivation&.reactivation_date.present? && Time.zone.now < recent_deactivation.reactivation_date
:active
end
def active?
status == :active
end
def reactivating_soon?
status == :reactivating_soon
end
end

35
app/models/scheme_deactivation_period.rb

@ -1,15 +1,40 @@
class SchemeDeactivationPeriodValidator < ActiveModel::Validator
def validate(record)
scheme = record.scheme
recent_deactivation = scheme.scheme_deactivation_periods.deactivations_without_reactivation.first
if recent_deactivation.present?
validate_reactivation(record, recent_deactivation, scheme)
else
validate_deactivation(record, scheme)
end
end
def validate_reactivation(record, recent_deactivation, scheme)
if record.reactivation_date.blank?
if record.reactivation_date_type.blank?
record.errors.add(:reactivation_date_type, message: I18n.t("validations.scheme.toggle_date.not_selected"))
elsif record.reactivation_date_type == "other"
record.errors.add(:reactivation_date, message: I18n.t("validations.scheme.toggle_date.invalid"))
end
elsif !record.reactivation_date.between?(scheme.available_from, Time.zone.local(2200, 1, 1))
record.errors.add(:reactivation_date, message: I18n.t("validations.scheme.toggle_date.out_of_range", date: scheme.available_from.to_formatted_s(:govuk_date)))
elsif record.reactivation_date < recent_deactivation.deactivation_date
record.errors.add(:reactivation_date, message: I18n.t("validations.scheme.reactivation.before_deactivation", date: recent_deactivation.deactivation_date.to_formatted_s(:govuk_date)))
end
end
def validate_deactivation(record, scheme)
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"))
record.errors.add(:deactivation_date_type, message: I18n.t("validations.scheme.toggle_date.not_selected"))
elsif record.deactivation_date_type == "other"
record.errors.add(:deactivation_date, message: I18n.t("validations.scheme.deactivation_date.invalid"))
record.errors.add(:deactivation_date, message: I18n.t("validations.scheme.toggle_date.invalid"))
end
elsif scheme.scheme_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.scheme.deactivation.during_deactivated_period"))
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)))
unless record.deactivation_date.between?(scheme.available_from, Time.zone.local(2200, 1, 1))
record.errors.add(:deactivation_date, message: I18n.t("validations.scheme.toggle_date.out_of_range", date: scheme.available_from.to_formatted_s(:govuk_date)))
end
end
end

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

@ -1,5 +1,3 @@
<% title = "Deactivate #{@scheme.service_name}" %>
<% content_for :title, title %>
<%= form_with model: @scheme_deactivation_period, url: scheme_deactivate_path(@scheme), method: "patch", local: true do |f| %>
<% content_for :before_content do %>
<%= govuk_back_link(href: :back) %>
@ -8,7 +6,7 @@
<span class="govuk-caption-l"><%= @scheme.service_name %></span>
This change will affect <%= @scheme.lettings_logs.count %> logs
</h1>
<%= govuk_warning_text text: I18n.t("warnings.scheme.deactivation.review_logs") %>
<%= govuk_warning_text text: I18n.t("warnings.scheme.deactivate.review_logs") %>
<%= f.hidden_field :confirm, value: true %>
<%= f.hidden_field :deactivation_date, value: @deactivation_date %>
<%= f.hidden_field :deactivation_date_type, value: @deactivation_date_type %>

4
app/views/schemes/show.html.erb

@ -26,9 +26,9 @@
<% end %>
<% if FeatureToggle.scheme_toggle_enabled? %>
<% if @scheme.active? %>
<% if @scheme.active? || @scheme.reactivating_soon?%>
<%= govuk_button_link_to "Deactivate this scheme", scheme_new_deactivation_path(@scheme), warning: true %>
<% else %>
<%= govuk_button_link_to "Reactivate this scheme", scheme_reactivate_path(@scheme) %>
<%= govuk_button_link_to "Reactivate this scheme", scheme_new_reactivation_path(@scheme) %>
<% end %>
<% end %>

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

@ -1,29 +1,31 @@
<% title = "#{action.humanize} #{@scheme.service_name}" %>
<% content_for :title, title %>
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: scheme_details_path(@scheme),
) %>
<% end %>
<%= form_with model: @scheme_deactivation_period, url: scheme_new_deactivation_path(@scheme), method: "patch", local: true do |f| %>
<%= form_with model: @scheme_deactivation_period, url: toggle_scheme_form_path(action, @scheme), method: "patch", local: true do |f| %>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<% collection_start_date = FormHandler.instance.current_collection_start_date %>
<%= f.govuk_error_summary %>
<%= f.govuk_radio_buttons_fieldset :deactivation_date_type,
legend: { text: I18n.t("questions.scheme.deactivation.apply_from") },
<%= f.govuk_radio_buttons_fieldset date_type_question(action),
legend: { text: I18n.t("questions.scheme.toggle_active.apply_from") },
caption: { text: title },
hint: { text: I18n.t("hints.scheme.deactivation", date: collection_start_date.to_formatted_s(:govuk_date)) } do %>
<%= govuk_warning_text text: I18n.t("warnings.scheme.deactivation.existing_logs") %>
<%= f.govuk_radio_button :deactivation_date_type,
hint: { text: I18n.t("hints.scheme.toggle_active", date: collection_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),
"default",
label: { text: "From the start of the current collection period (#{collection_start_date.to_formatted_s(:govuk_date)})" } %>
<%= f.govuk_radio_button :deactivation_date_type,
<%= f.govuk_radio_button date_type_question(action),
"other",
label: { text: "For tenancies starting after a certain date" },
**basic_conditional_html_attributes({ "deactivation_date" => %w[other] }, "scheme") do %>
<%= f.govuk_date_field :deactivation_date,
<%= f.govuk_date_field date_question(action),
legend: { text: "Date", size: "m" },
hint: { text: "For example, 27 3 2022" },
width: 20 %>

20
config/locales/en.yml

@ -313,10 +313,16 @@ en:
missing: "You must show the DLUHC privacy notice to the tenant before you can submit this log."
scheme:
deactivation_date:
toggle_date:
not_selected: "Select one of the options"
invalid: "Enter a valid day, month and year"
out_of_range: "The date must be on or after the %{date}"
reactivation:
before_deactivation: "This scheme was deactivated on %{date}\nThe reactivation date must be on or after deactivation date"
deactivation:
during_deactivated_period: "The scheme is already deactivated during this date, please enter a different date"
location:
toggle_date:
@ -325,7 +331,7 @@ en:
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:
deactivation:
during_deactivated_period: "The location is already deactivated during this date, please enter a different date"
soft_validations:
@ -381,7 +387,7 @@ en:
toggle_active:
apply_from: "When should this change apply?"
scheme:
deactivation:
toggle_active:
apply_from: "When should this change apply?"
descriptions:
location:
@ -397,19 +403,21 @@ en:
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."
toggle_active: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed."
scheme:
deactivation: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed."
toggle_active: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed."
warnings:
location:
deactivate:
existing_logs: "It will not be possible to add logs with this location if their tenancy start date is on or after the date you enter. Any existing logs may be affected."
review_logs: "Your data providers will need to review these logs and answer a few questions again. We’ll email each log creator with a list of logs that need updating."
reactivate:
reactivate:
existing_logs: "You’ll be able to add logs with this location if their tenancy start date is on or after the date you enter."
scheme:
deactivation:
deactivate:
existing_logs: "It will not be possible to add logs with this scheme if their tenancy start date is on or after the date you enter. Any existing logs may be affected."
review_logs: "Your data providers will need to review these logs and answer a few questions again. We’ll email each log creator with a list of logs that need updating."
reactivate:
existing_logs: "You’ll be able to add logs with this scheme if their tenancy start date is on or after the date you enter."
test:
one_argument: "This is based on the tenant’s work situation: %{ecstat1}"

2
config/routes.rb

@ -52,8 +52,10 @@ Rails.application.routes.draw do
get "new-deactivation", to: "schemes#new_deactivation"
get "deactivate-confirm", to: "schemes#deactivate_confirm"
get "reactivate", to: "schemes#reactivate"
get "new-reactivation", to: "schemes#new_reactivation"
patch "new-deactivation", to: "schemes#new_deactivation"
patch "deactivate", to: "schemes#deactivate"
patch "reactivate", to: "schemes#reactivate"
resources :locations do
get "edit-name", to: "locations#edit_name"

Loading…
Cancel
Save