Browse Source

Multiple scheme deactivations (#1004)

* Remove deactivation date from schemes and add scheme deactivation periods table

* Update affected logs when a scheme gets deactivated

* Update status method

* Display availability timeline

* Update flash notice message
pull/1008/head
kosiakkatrina 2 years ago committed by GitHub
parent
commit
752103404f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      app/controllers/schemes_controller.rb
  2. 11
      app/helpers/schemes_helper.rb
  3. 2
      app/models/lettings_log.rb
  4. 10
      app/models/scheme.rb
  5. 3
      app/models/scheme_deactivation_period.rb
  6. 10
      db/migrate/20221117103841_add_scheme_deactivations.rb
  7. 13
      db/migrate/20221117103855_remove_deactivation_date_from_schemes.rb
  8. 18
      db/schema.rb
  9. 5
      spec/factories/scheme_deactivation_period.rb
  10. 25
      spec/helpers/schemes_helper_spec.rb
  11. 40
      spec/models/scheme_spec.rb
  12. 42
      spec/requests/schemes_controller_spec.rb

8
app/controllers/schemes_controller.rb

@ -44,7 +44,7 @@ class SchemesController < ApplicationController
def deactivate
@scheme.run_deactivation_validations!
if @scheme.update!(deactivation_date:)
if @scheme.scheme_deactivation_periods.create!(deactivation_date:) && update_affected_logs
flash[:notice] = deactivate_success_notice
end
redirect_to scheme_details_path(@scheme)
@ -299,7 +299,7 @@ private
when :deactivated
"#{@scheme.service_name} has been deactivated"
when :deactivating_soon
"#{@scheme.service_name} will deactivate on #{@scheme.deactivation_date.to_formatted_s(:govuk_date)}"
"#{@scheme.service_name} will deactivate on #{deactivation_date.to_time.to_formatted_s(:govuk_date)}"
end
end
@ -319,4 +319,8 @@ private
Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i)
end
def update_affected_logs
@scheme.lettings_logs.filter_by_before_startdate(deactivation_date.to_time).update!(location: nil, scheme: nil)
end
end

11
app/helpers/schemes_helper.rb

@ -14,7 +14,7 @@ module SchemesHelper
{ name: "Secondary client group", value: scheme.secondary_client_group },
{ name: "Level of support given", value: scheme.support_type },
{ name: "Intended length of stay", value: scheme.intended_stay },
{ name: "Availability", value: "Available from #{scheme.available_from.to_formatted_s(:govuk_date)}" },
{ name: "Availability", value: scheme_availability(scheme) },
]
if FeatureToggle.scheme_toggle_enabled?
@ -26,4 +26,13 @@ module SchemesHelper
end
base_attributes
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?
end
availability
end
end

2
app/models/lettings_log.rb

@ -45,7 +45,7 @@ class LettingsLog < Log
.or(filter_by_postcode(param))
.or(filter_by_id(param))
}
scope :filter_by_before_startdate, ->(date) { left_joins(:location).where("lettings_logs.startdate >= ?", date) }
scope :filter_by_before_startdate, ->(date) { where("lettings_logs.startdate >= ?", date) }
AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze
OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenancycode propcode].freeze

10
app/models/scheme.rb

@ -3,6 +3,7 @@ class Scheme < ApplicationRecord
belongs_to :managing_organisation, optional: true, class_name: "Organisation"
has_many :locations, dependent: :delete_all
has_many :lettings_logs, class_name: "LettingsLog", dependent: :delete_all
has_many :scheme_deactivation_periods, class_name: "SchemeDeactivationPeriod"
has_paper_trail
@ -22,7 +23,7 @@ class Scheme < ApplicationRecord
auto_strip_attributes :service_name
attr_accessor :deactivation_date_type, :run_deactivation_validations
attr_accessor :deactivation_date_type, :deactivation_date, :run_deactivation_validations
SENSITIVE = {
No: 0,
@ -216,8 +217,9 @@ class Scheme < ApplicationRecord
end
def status
return :active if deactivation_date.blank?
return :deactivating_soon if Time.zone.now < deactivation_date
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
:deactivated
end
@ -245,7 +247,7 @@ class Scheme < ApplicationRecord
end
else
collection_start_date = FormHandler.instance.current_collection_start_date
unless deactivation_date.between?(collection_start_date, Date.new(2200, 1, 1))
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

3
app/models/scheme_deactivation_period.rb

@ -0,0 +1,3 @@
class SchemeDeactivationPeriod < ApplicationRecord
scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) }
end

10
db/migrate/20221117103841_add_scheme_deactivations.rb

@ -0,0 +1,10 @@
class AddSchemeDeactivations < ActiveRecord::Migration[7.0]
def change
create_table :scheme_deactivation_periods do |t|
t.datetime :deactivation_date
t.datetime :reactivation_date
t.belongs_to :scheme
t.timestamps
end
end
end

13
db/migrate/20221117103855_remove_deactivation_date_from_schemes.rb

@ -0,0 +1,13 @@
class RemoveDeactivationDateFromSchemes < ActiveRecord::Migration[7.0]
def up
change_table :schemes, bulk: true do |t|
t.remove :deactivation_date
end
end
def down
change_table :schemes, bulk: true do |t|
t.column :deactivation_date, :datetime
end
end
end

18
db/schema.rb

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_11_15_113437) do
ActiveRecord::Schema[7.0].define(version: 2022_11_17_103855) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -372,20 +372,29 @@ ActiveRecord::Schema[7.0].define(version: 2022_11_15_113437) do
t.integer "la_known"
t.integer "income1"
t.integer "income1nk"
t.integer "details_known_2"
t.integer "details_known_3"
t.integer "details_known_4"
t.integer "age4"
t.integer "age4_known"
t.integer "age5"
t.integer "age5_known"
t.integer "age6"
t.integer "age6_known"
t.integer "details_known_2"
t.integer "details_known_3"
t.integer "details_known_4"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id"
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"
end
create_table "scheme_deactivation_periods", force: :cascade do |t|
t.datetime "deactivation_date"
t.datetime "reactivation_date"
t.bigint "scheme_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["scheme_id"], name: "index_scheme_deactivation_periods_on_scheme_id"
end
create_table "schemes", force: :cascade do |t|
t.string "service_name"
t.bigint "owning_organisation_id", null: false
@ -406,7 +415,6 @@ ActiveRecord::Schema[7.0].define(version: 2022_11_15_113437) do
t.string "old_visible_id"
t.integer "total_units"
t.boolean "confirmed"
t.datetime "deactivation_date"
t.index ["managing_organisation_id"], name: "index_schemes_on_managing_organisation_id"
t.index ["owning_organisation_id"], name: "index_schemes_on_owning_organisation_id"
end

5
spec/factories/scheme_deactivation_period.rb

@ -0,0 +1,5 @@
FactoryBot.define do
factory :scheme_deactivation_period do
reactivation_date { nil }
end
end

25
spec/helpers/schemes_helper_spec.rb

@ -18,10 +18,33 @@ RSpec.describe SchemesHelper do
{ name: "Secondary client group", value: scheme.secondary_client_group },
{ name: "Level of support given", value: scheme.support_type },
{ name: "Intended length of stay", value: scheme.intended_stay },
{ name: "Availability", value: "Available from 8 August 2022" },
{ name: "Availability", value: "Active from 8 August 2022" },
{ name: "Status", value: :active },
]
expect(display_scheme_attributes(scheme)).to eq(attributes)
end
context "when viewing availability" do
context "with are no deactivations" do
it "displays created_at as availability date" do
availability_attribute = display_scheme_attributes(scheme).find { |x| x[:name] == "Availability" }[:value]
expect(availability_attribute).to eq("Active from #{scheme.created_at.to_formatted_s(:govuk_date)}")
end
end
context "with previous deactivations" do
before do
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1))
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil)
end
it "displays the timeline of availability" do
availability_attribute = display_scheme_attributes(scheme).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")
end
end
end
end
end

40
spec/models/scheme_spec.rb

@ -99,34 +99,58 @@ RSpec.describe Scheme, type: :model do
Timecop.freeze(2022, 6, 7)
end
context "when there have not been any previous deactivations" do
it "returns active if the scheme is not deactivated" do
scheme.deactivation_date = nil
scheme.deactivation_date_type = nil
expect(scheme.status).to eq(:active)
end
it "returns deactivating soon if deactivation_date is in the future" do
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8))
scheme.save!
expect(scheme.status).to eq(:deactivating_soon)
end
it "returns deactivated if deactivation_date is in the past" do
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6))
scheme.save!
expect(scheme.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is today" do
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7))
scheme.save!
expect(scheme.status).to eq(:deactivated)
end
end
context "when there have been previous deactivations" do
before do
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 6, 5))
end
it "returns active if the scheme has no relevant deactivation records" do
expect(scheme.status).to eq(:active)
end
it "returns deactivating soon if deactivation_date is in the future" do
scheme.deactivation_date = Time.zone.local(2022, 8, 8)
scheme.deactivation_date_type = "other"
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8))
scheme.save!
expect(scheme.status).to eq(:deactivating_soon)
end
it "returns deactivated if deactivation_date is in the past" do
scheme.deactivation_date = Time.zone.local(2022, 4, 8)
scheme.deactivation_date_type = "other"
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6))
scheme.save!
expect(scheme.status).to eq(:deactivated)
end
it "returns deactivated if deactivation_date is today" do
scheme.deactivation_date = Time.zone.local(2022, 6, 7)
scheme.deactivation_date_type = "other"
scheme.scheme_deactivation_periods << FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7))
scheme.save!
expect(scheme.status).to eq(:deactivated)
end
end
end
describe "with deactivation_date (but no deactivation_date_type)" do
let(:scheme) { FactoryBot.create(:scheme, deactivation_date: Date.new(2022, 4, 1)) }

42
spec/requests/schemes_controller_spec.rb

@ -246,19 +246,18 @@ RSpec.describe SchemesController, type: :request do
context "when looking at scheme details" do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
let(:add_deactivations) { scheme.scheme_deactivation_periods << scheme_deactivation_period }
before do
Timecop.freeze(Time.utc(2022, 10, 10))
sign_in user
scheme.deactivation_date = deactivation_date
scheme.deactivation_date_type = deactivation_date_type
add_deactivations
scheme.save!
get "/schemes/#{scheme.id}"
end
context "with active scheme" do
let(:deactivation_date) { nil }
let(:deactivation_date_type) { nil }
let(:add_deactivations) {}
it "renders deactivate this scheme" do
expect(response).to have_http_status(:ok)
@ -267,8 +266,7 @@ RSpec.describe SchemesController, type: :request do
end
context "with deactivated scheme" do
let(:deactivation_date) { Time.utc(2022, 10, 9) }
let(:deactivation_date_type) { "other" }
let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 9)) }
it "renders reactivate this scheme" do
expect(response).to have_http_status(:ok)
@ -277,8 +275,7 @@ RSpec.describe SchemesController, type: :request do
end
context "with scheme that's deactivating soon" do
let(:deactivation_date) { Time.utc(2022, 10, 12) }
let(:deactivation_date_type) { "other" }
let(:scheme_deactivation_period) { FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 12)) }
it "renders reactivate this scheme" do
expect(response).to have_http_status(:ok)
@ -1768,8 +1765,10 @@ RSpec.describe SchemesController, type: :request do
context "when signed in as a data coordinator" do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) }
let(:startdate) { Time.utc(2021, 1, 2) }
let!(:location) { FactoryBot.create(:location, scheme:) }
let(:deactivation_date) { Time.utc(2022, 10, 10) }
let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location:, scheme:, startdate:, owning_organisation: user.organisation) }
let(:startdate) { Time.utc(2022, 10, 11) }
before do
Timecop.freeze(Time.utc(2022, 10, 10))
@ -1812,7 +1811,30 @@ RSpec.describe SchemesController, type: :request do
expect(response).to have_http_status(:ok)
expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
scheme.reload
expect(scheme.deactivation_date).to eq(deactivation_date)
expect(scheme.scheme_deactivation_periods.count).to eq(1)
expect(scheme.scheme_deactivation_periods.first.deactivation_date).to eq(deactivation_date)
end
context "and a log startdate is after scheme deactivation date" do
it "clears the scheme and scheme answers" do
expect(lettings_log.scheme).to eq(scheme)
expect(lettings_log.scheme).to eq(scheme)
lettings_log.reload
expect(lettings_log.scheme).to eq(nil)
expect(lettings_log.scheme).to eq(nil)
end
end
context "and a log startdate is before scheme deactivation date" do
let(:startdate) { Time.utc(2022, 10, 9) }
it "does not update the log" do
expect(lettings_log.scheme).to eq(scheme)
expect(lettings_log.scheme).to eq(scheme)
lettings_log.reload
expect(lettings_log.scheme).to eq(scheme)
expect(lettings_log.scheme).to eq(scheme)
end
end
end

Loading…
Cancel
Save