diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index 208394942..21fb3a040 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -22,14 +22,16 @@ class SchemesController < ApplicationController end def new_deactivation - if params[:scheme].blank? + @scheme_deactivation_period = SchemeDeactivationPeriod.new + + if params[:scheme_deactivation_period].blank? render "toggle_active", locals: { action: "deactivate" } else - @scheme.run_deactivation_validations = true - @scheme.deactivation_date = deactivation_date - @scheme.deactivation_date_type = params[:scheme][:deactivation_date_type] - if @scheme.valid? - redirect_to scheme_deactivate_confirm_path(@scheme, deactivation_date: @scheme.deactivation_date, deactivation_date_type: @scheme.deactivation_date_type) + @scheme_deactivation_period.deactivation_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 + 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 end @@ -42,9 +44,7 @@ class SchemesController < ApplicationController end def deactivate - @scheme.run_deactivation_validations! - - if @scheme.scheme_deactivation_periods.create!(deactivation_date:) && update_affected_logs + if SchemeDeactivationPeriod.create!(scheme_id: @scheme.id, deactivation_date: params[:deactivation_date]) && update_affected_logs flash[:notice] = deactivate_success_notice end redirect_to scheme_details_path(@scheme) @@ -299,28 +299,28 @@ private when :deactivated "#{@scheme.service_name} has been deactivated" 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 def deactivation_date - if params[:scheme].blank? + if params[:scheme_deactivation_period].blank? return - elsif params[:scheme][:deactivation_date_type] == "default" + elsif params[:scheme_deactivation_period][:deactivation_date_type] == "default" return FormHandler.instance.current_collection_start_date - elsif params[:scheme][:deactivation_date].present? - return params[:scheme][:deactivation_date] + elsif params[:scheme_deactivation_period][:deactivation_date].present? + return params[:scheme_deactivation_period][:deactivation_date] end - day = params[:scheme]["deactivation_date(3i)"] - month = params[:scheme]["deactivation_date(2i)"] - year = params[:scheme]["deactivation_date(1i)"] + day = params[:scheme_deactivation_period]["deactivation_date(3i)"] + month = params[:scheme_deactivation_period]["deactivation_date(2i)"] + year = params[:scheme_deactivation_period]["deactivation_date(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) end def update_affected_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 diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 3dfe1ff55..8197a147c 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -19,12 +19,9 @@ class Scheme < ApplicationRecord } validate :validate_confirmed - validate :deactivation_date_errors auto_strip_attributes :service_name - attr_accessor :deactivation_date_type, :deactivation_date, :run_deactivation_validations - SENSITIVE = { No: 0, Yes: 1, @@ -227,29 +224,4 @@ class Scheme < ApplicationRecord def active? status == :active 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 diff --git a/app/models/scheme_deactivation_period.rb b/app/models/scheme_deactivation_period.rb index 5caba5c7a..f83a68e62 100644 --- a/app/models/scheme_deactivation_period.rb +++ b/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 + validates_with SchemeDeactivationPeriodValidator + belongs_to :scheme + attr_accessor :deactivation_date_type, :reactivation_date_type + scope :deactivations_without_reactivation, -> { where(reactivation_date: nil) } end diff --git a/app/views/schemes/deactivate_confirm.html.erb b/app/views/schemes/deactivate_confirm.html.erb index 45f7d4341..0cfd454c8 100644 --- a/app/views/schemes/deactivate_confirm.html.erb +++ b/app/views/schemes/deactivate_confirm.html.erb @@ -1,6 +1,6 @@ <% title = "Deactivate #{@scheme.service_name}" %> <% 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 %> <%= govuk_back_link(href: :back) %> <% end %> diff --git a/app/views/schemes/toggle_active.html.erb b/app/views/schemes/toggle_active.html.erb index 11dd2f276..fbb3ebc5f 100644 --- a/app/views/schemes/toggle_active.html.erb +++ b/app/views/schemes/toggle_active.html.erb @@ -6,7 +6,7 @@ href: scheme_details_path(@scheme), ) %> <% 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| %>
<% collection_start_date = FormHandler.instance.current_collection_start_date %> diff --git a/spec/helpers/schemes_helper_spec.rb b/spec/helpers/schemes_helper_spec.rb index 1924a6cc5..9db3639d9 100644 --- a/spec/helpers/schemes_helper_spec.rb +++ b/spec/helpers/schemes_helper_spec.rb @@ -35,8 +35,9 @@ RSpec.describe SchemesHelper do 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) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, scheme:) + scheme.reload end it "displays the timeline of availability" do diff --git a/spec/models/scheme_spec.rb b/spec/models/scheme_spec.rb index d95d867dc..b19e8c992 100644 --- a/spec/models/scheme_spec.rb +++ b/spec/models/scheme_spec.rb @@ -109,27 +109,27 @@ RSpec.describe Scheme, type: :model do 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:) + scheme.reload 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:) + scheme.reload 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:) + scheme.reload 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)) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 6, 5), scheme:) end it "returns active if the scheme has no relevant deactivation records" do @@ -137,30 +137,22 @@ RSpec.describe Scheme, type: :model do 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 8), scheme:) + scheme.reload 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 6), scheme:) + scheme.reload 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! + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 7), scheme:) + scheme.reload 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)) } - - it "is valid" do - expect(scheme).to be_valid - end - end end diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 59d044050..0c3b47f1a 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -270,7 +270,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:ok) @@ -279,7 +279,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:ok) @@ -1785,7 +1785,7 @@ RSpec.describe SchemesController, type: :request do end 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 follow_redirect! @@ -1795,7 +1795,7 @@ RSpec.describe SchemesController, type: :request do end 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 follow_redirect! @@ -1805,7 +1805,7 @@ RSpec.describe SchemesController, type: :request do end 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 Timecop.freeze(Time.utc(2022, 10, 10)) @@ -1851,7 +1851,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity) @@ -1860,7 +1860,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity) @@ -1869,7 +1869,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity) @@ -1878,7 +1878,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity) @@ -1887,7 +1887,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity) @@ -1896,7 +1896,7 @@ RSpec.describe SchemesController, type: :request do end 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 expect(response).to have_http_status(:unprocessable_entity)