diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb
index 4ba300552..12ae4473b 100644
--- a/app/models/form_handler.rb
+++ b/app/models/form_handler.rb
@@ -79,12 +79,12 @@ class FormHandler
def lettings_in_crossover_period?(now: Time.zone.now)
forms = lettings_forms.values
- forms.count { |form| form.start_date < now && now < form.end_date } > 1
+ forms.count { |form| now.between?(form.start_date, form.end_date) } > 1
end
def sales_in_crossover_period?(now: Time.zone.now)
forms = sales_forms.values
- forms.count { |form| form.start_date < now && now < form.end_date } > 1
+ forms.count { |form| now.between?(form.start_date, form.end_date) } > 1
end
def use_fake_forms!
diff --git a/app/models/validations/date_validations.rb b/app/models/validations/date_validations.rb
index 66e472ba0..ee7789171 100644
--- a/app/models/validations/date_validations.rb
+++ b/app/models/validations/date_validations.rb
@@ -33,16 +33,6 @@ module Validations::DateValidations
def validate_startdate(record)
return unless record.startdate && date_valid?("startdate", record)
- created_at = record.created_at || Time.zone.now
-
- if created_at > first_collection_end_date && record.startdate < second_collection_start_date
- record.errors.add :startdate, I18n.t("validations.date.outside_collection_window")
- end
-
- if (record.startdate < first_collection_start_date || record.startdate > second_collection_end_date) && FeatureToggle.startdate_collection_window_validation_enabled?
- record.errors.add :startdate, I18n.t("validations.date.outside_collection_window")
- end
-
if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14
record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after")
end
@@ -68,22 +58,6 @@ module Validations::DateValidations
private
- def first_collection_start_date
- @first_collection_start_date ||= FormHandler.instance.lettings_forms["previous_lettings"].start_date
- end
-
- def first_collection_end_date
- @first_collection_end_date ||= FormHandler.instance.lettings_forms["previous_lettings"].end_date
- end
-
- def second_collection_start_date
- @second_collection_start_date ||= FormHandler.instance.lettings_forms["current_lettings"].start_date
- end
-
- def second_collection_end_date
- @second_collection_end_date ||= FormHandler.instance.lettings_forms["current_lettings"].end_date
- end
-
def is_rsnvac_first_let?(record)
[15, 16, 17].include?(record["rsnvac"])
end
diff --git a/app/models/validations/sales/setup_validations.rb b/app/models/validations/sales/setup_validations.rb
index e7090aabf..e76993907 100644
--- a/app/models/validations/sales/setup_validations.rb
+++ b/app/models/validations/sales/setup_validations.rb
@@ -3,10 +3,10 @@ module Validations::Sales::SetupValidations
include CollectionTimeHelper
def validate_saledate(record)
- return unless record.saledate && date_valid?("saledate", record)
+ return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_collection_window_validation_enabled?
- unless record.saledate.between?(active_collection_start_date, current_collection_end_date) || !FeatureToggle.saledate_collection_window_validation_enabled?
- record.errors.add :saledate, validation_error_message
+ unless record.saledate.between?(active_collection_start_date, current_collection_end_date)
+ record.errors.add :saledate, saledate_validation_error_message
end
end
@@ -20,12 +20,12 @@ private
end
end
- def validation_error_message
+ def saledate_validation_error_message
current_end_year_long = current_collection_end_date.strftime("#{current_collection_end_date.day.ordinalize} %B %Y")
if FormHandler.instance.sales_in_crossover_period?
I18n.t(
- "validations.setup.saledate.previous_and_current_financial_year",
+ "validations.setup.saledate.previous_and_current_collection_year",
previous_start_year_short: previous_collection_start_date.strftime("%y"),
previous_end_year_short: previous_collection_end_date.strftime("%y"),
previous_start_year_long: previous_collection_start_date.strftime("#{previous_collection_start_date.day.ordinalize} %B %Y"),
@@ -34,7 +34,7 @@ private
)
else
I18n.t(
- "validations.setup.saledate.current_financial_year",
+ "validations.setup.saledate.current_collection_year",
current_start_year_short: current_collection_start_date.strftime("%y"),
current_end_year_short: current_collection_end_date.strftime("%y"),
current_start_year_long: current_collection_start_date.strftime("#{current_collection_start_date.day.ordinalize} %B %Y"),
diff --git a/app/models/validations/setup_validations.rb b/app/models/validations/setup_validations.rb
index 93105f9ea..0865ebae6 100644
--- a/app/models/validations/setup_validations.rb
+++ b/app/models/validations/setup_validations.rb
@@ -1,5 +1,14 @@
module Validations::SetupValidations
include Validations::SharedValidations
+ include CollectionTimeHelper
+
+ def validate_startdate_setup(record)
+ return unless record.startdate && date_valid?("startdate", record) && FeatureToggle.startdate_collection_window_validation_enabled?
+
+ unless record.startdate.between?(active_collection_start_date, current_collection_end_date)
+ record.errors.add :startdate, startdate_validation_error_message
+ end
+ end
def validate_irproduct_other(record)
if intermediate_product_rent_type?(record) && record.irproduct_other.blank?
@@ -27,6 +36,37 @@ module Validations::SetupValidations
private
+ def active_collection_start_date
+ if FormHandler.instance.lettings_in_crossover_period?
+ previous_collection_start_date
+ else
+ current_collection_start_date
+ end
+ end
+
+ def startdate_validation_error_message
+ current_end_year_long = current_collection_end_date.strftime("#{current_collection_end_date.day.ordinalize} %B %Y")
+
+ if FormHandler.instance.lettings_in_crossover_period?
+ I18n.t(
+ "validations.setup.startdate.previous_and_current_collection_year",
+ previous_start_year_short: previous_collection_start_date.strftime("%y"),
+ previous_end_year_short: previous_collection_end_date.strftime("%y"),
+ previous_start_year_long: previous_collection_start_date.strftime("#{previous_collection_start_date.day.ordinalize} %B %Y"),
+ current_end_year_short: current_collection_end_date.strftime("%y"),
+ current_end_year_long:,
+ )
+ else
+ I18n.t(
+ "validations.setup.startdate.current_collection_year",
+ current_start_year_short: current_collection_start_date.strftime("%y"),
+ current_end_year_short: current_collection_end_date.strftime("%y"),
+ current_start_year_long: current_collection_start_date.strftime("#{current_collection_start_date.day.ordinalize} %B %Y"),
+ current_end_year_long:,
+ )
+ end
+ end
+
def intermediate_product_rent_type?(record)
record.rent_type == 5
end
diff --git a/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb
index 0253bcc41..e00a7190b 100644
--- a/config/initializers/feature_toggle.rb
+++ b/config/initializers/feature_toggle.rb
@@ -4,11 +4,11 @@ class FeatureToggle
Rails.env.production? || Rails.env.test? || Rails.env.staging?
end
- def self.startdate_two_week_validation_enabled?
+ def self.startdate_collection_window_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging?
end
- def self.startdate_collection_window_validation_enabled?
+ def self.startdate_two_week_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging?
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index af33836a0..f44ba1d41 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -141,7 +141,7 @@ en:
above_min: "%{field} must be at least %{min}"
date:
invalid_date: "Enter a date in the correct format, for example 31 1 2022"
- outside_collection_window: Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023
+ outside_collection_window: Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023
postcode: "Enter a postcode in the correct format, for example AA1 1AA"
location_admin_district: "Select a local authority"
email:
@@ -155,14 +155,18 @@ en:
intermediate_rent_product_name:
blank: "Enter name of other intermediate rent product"
saledate:
- current_financial_year:
- Enter a date within the %{current_start_year_short}/%{current_end_year_short} financial year, which is between %{current_start_year_long} and %{current_end_year_long}
- previous_and_current_financial_year:
- "Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} financial years, which is between %{previous_start_year_long} and %{current_end_year_long}"
+ current_collection_year:
+ Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long}
+ previous_and_current_collection_year:
+ "Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} collection years, which is between %{previous_start_year_long} and %{current_end_year_long}"
type:
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type"
startdate:
+ current_collection_year:
+ Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long}
+ previous_and_current_collection_year:
+ "Enter a date within the %{previous_start_year_short}/%{previous_end_year_short} or %{previous_end_year_short}/%{current_end_year_short} collection years, which is between %{previous_start_year_long} and %{current_end_year_long}"
later_than_14_days_after: "The tenancy start date must not be later than 14 days from today’s date"
before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme"
after_void_date: "Enter a tenancy start date that is after the void date"
diff --git a/db/schema.rb b/db/schema.rb
index daf421930..075cc4b5e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -557,9 +557,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_09_145740) do
t.integer "ethnicbuy2"
t.integer "proplen_asked"
t.string "old_id"
- t.integer "pregblank"
t.integer "buy2living"
t.integer "prevtenbuy2"
+ t.integer "pregblank"
t.integer "nationalbuy2"
t.string "uprn"
t.integer "uprn_known"
diff --git a/spec/components/log_summary_component_spec.rb b/spec/components/log_summary_component_spec.rb
index f8edfb948..99015b6d6 100644
--- a/spec/components/log_summary_component_spec.rb
+++ b/spec/components/log_summary_component_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe LogSummaryComponent, type: :component do
let(:coordinator_user) { FactoryBot.create(:user) }
let(:propcode) { "P3647" }
let(:tenancycode) { "T62863" }
- let(:lettings_log) { FactoryBot.create(:lettings_log, needstype: 1, startdate: Time.utc(2022, 1, 1), tenancycode:, propcode:) }
+ let(:lettings_log) { FactoryBot.create(:lettings_log, needstype: 1, tenancycode:, propcode:, startdate: Time.zone.today) }
let(:sales_log) { FactoryBot.create(:sales_log) }
context "when rendering lettings log for a support user" do
@@ -16,8 +16,8 @@ RSpec.describe LogSummaryComponent, type: :component do
expect(result).to have_text(lettings_log.tenancycode)
expect(result).to have_text(lettings_log.propcode)
expect(result).to have_text("General needs")
- expect(result).to have_text("Tenancy starts 1 January 2022")
- expect(result).to have_text("Created 8 February 2022")
+ expect(result).to have_text("Tenancy starts #{Time.zone.today.strftime('%e %B %Y')}")
+ expect(result).to have_text("Created #{Time.zone.today.strftime('%e %B %Y')}")
expect(result).to have_text("by Danny Rojas")
expect(result).to have_content("Owned by\n DLUHC")
expect(result).to have_content("Managed by\n DLUHC")
diff --git a/spec/factories/lettings_log.rb b/spec/factories/lettings_log.rb
index cb97eed68..b0667b817 100644
--- a/spec/factories/lettings_log.rb
+++ b/spec/factories/lettings_log.rb
@@ -7,7 +7,6 @@ FactoryBot.define do
renewal { 0 }
needstype { 1 }
rent_type { 1 }
- startdate { Time.zone.local(2022, 5, 1) }
end
trait :in_progress do
status { 1 }
@@ -18,7 +17,7 @@ FactoryBot.define do
age2 { 19 }
renewal { 1 }
rent_type { 1 }
- startdate { Time.zone.local(2021, 5, 1) }
+ startdate { Time.zone.today }
end
trait :soft_validations_triggered do
status { 1 }
@@ -36,6 +35,7 @@ FactoryBot.define do
hhmemb { 1 }
end
trait :completed do
+ startdate { Time.zone.today }
status { 2 }
tenancycode { Faker::Name.initials(number: 10) }
age1_known { 0 }
@@ -66,7 +66,7 @@ FactoryBot.define do
rsnvac { 6 }
unittype_gn { 7 }
beds { 3 }
- voiddate { "03/11/2019" }
+ voiddate { 2.days.ago }
offered { 2 }
wchair { 1 }
earnings { 68 }
@@ -132,9 +132,8 @@ FactoryBot.define do
hbrentshortfall { 1 }
tshortfall { 12 }
property_relet { 0 }
- mrcdate { Time.zone.local(2020, 5, 5, 10, 36, 49) }
+ mrcdate { 1.day.ago }
incref { 0 }
- startdate { Time.zone.today }
armedforces { 1 }
builtype { 1 }
unitletas { 2 }
@@ -155,7 +154,7 @@ FactoryBot.define do
sheltered { 0 }
household_charge { 0 }
end
- created_at { Time.utc(2022, 2, 8, 16, 52, 15) }
- updated_at { Time.utc(2022, 2, 8, 16, 52, 15) }
+ created_at { Time.zone.today }
+ updated_at { Time.zone.today }
end
end
diff --git a/spec/features/form/accessible_autocomplete_spec.rb b/spec/features/form/accessible_autocomplete_spec.rb
index 160d32d38..15d23fe32 100644
--- a/spec/features/form/accessible_autocomplete_spec.rb
+++ b/spec/features/form/accessible_autocomplete_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Accessible Autocomplete" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
@@ -64,8 +73,8 @@ RSpec.describe "Accessible Autocomplete" do
let(:scheme) { FactoryBot.create(:scheme, owning_organisation_id: lettings_log.created_by.organisation_id, primary_client_group: "Q", secondary_client_group: "P") }
before do
- FactoryBot.create(:location, scheme:, postcode: "W6 0ST")
- FactoryBot.create(:location, scheme:, postcode: "SE6 1LB")
+ FactoryBot.create(:location, scheme:, postcode: "W6 0ST", startdate: Time.zone.local(2022, 1, 1))
+ FactoryBot.create(:location, scheme:, postcode: "SE6 1LB", startdate: Time.zone.local(2022, 1, 1))
lettings_log.update!(needstype: 2)
visit("/lettings-logs/#{lettings_log.id}/scheme")
end
diff --git a/spec/features/form/check_answers_page_lettings_logs_spec.rb b/spec/features/form/check_answers_page_lettings_logs_spec.rb
index 9062e1abc..97a9ccbec 100644
--- a/spec/features/form/check_answers_page_lettings_logs_spec.rb
+++ b/spec/features/form/check_answers_page_lettings_logs_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Lettings Log Check Answers Page" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2021, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:subsection) { "household-characteristics" }
@@ -152,7 +161,7 @@ RSpec.describe "Lettings Log Check Answers Page" do
context "when viewing setup section answers" do
before do
- FactoryBot.create(:location, scheme:)
+ FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 1, 1))
end
it "displays inferred postcode with the location id" do
diff --git a/spec/features/form/checkboxes_spec.rb b/spec/features/form/checkboxes_spec.rb
index 056ff93cf..dae505bcf 100644
--- a/spec/features/form/checkboxes_spec.rb
+++ b/spec/features/form/checkboxes_spec.rb
@@ -14,6 +14,15 @@ RSpec.describe "Checkboxes" do
end
let(:id) { lettings_log.id }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
before do
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
RequestHelper.stub_http_requests
diff --git a/spec/features/form/conditional_questions_spec.rb b/spec/features/form/conditional_questions_spec.rb
index 52d8886e0..f79b33191 100644
--- a/spec/features/form/conditional_questions_spec.rb
+++ b/spec/features/form/conditional_questions_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Form Conditional Questions" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
@@ -16,6 +25,7 @@ RSpec.describe "Form Conditional Questions" do
:sales_log,
:completed,
created_by: user,
+ saledate: Time.zone.local(2022, 1, 1),
)
end
let(:id) { lettings_log.id }
diff --git a/spec/features/form/form_navigation_spec.rb b/spec/features/form/form_navigation_spec.rb
index 351675804..aa0223616 100644
--- a/spec/features/form/form_navigation_spec.rb
+++ b/spec/features/form/form_navigation_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Form Navigation" do
+ around do |example|
+ Timecop.travel(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
diff --git a/spec/features/form/page_routing_spec.rb b/spec/features/form/page_routing_spec.rb
index eb4f6acc2..312e0752b 100644
--- a/spec/features/form/page_routing_spec.rb
+++ b/spec/features/form/page_routing_spec.rb
@@ -20,95 +20,106 @@ RSpec.describe "Form Page Routing" do
sign_in user
end
- it "can route the user to a different page based on their answer on the current page", js: true do
- visit("/lettings-logs/#{id}/conditional-question")
- # using a question name that is already in the db to avoid
- # having to add a new column to the db for this test
- choose("lettings-log-preg-occ-1-field", allow_label_click: true)
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-yes-page")
- click_link(text: "Back")
- expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question")
- choose("lettings-log-preg-occ-2-field", allow_label_click: true)
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
- end
-
- it "can route based on multiple conditions", js: true do
- visit("/lettings-logs/#{id}/person-1-gender")
- choose("lettings-log-sex1-f-field", allow_label_click: true)
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/person-1-working-situation")
- visit("/lettings-logs/#{id}/conditional-question")
- choose("lettings-log-preg-occ-2-field", allow_label_click: true)
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
- choose("lettings-log-cbl-0-field", allow_label_click: true)
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question/check-answers")
- end
+ context "with 21/22 logs" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
- context "when the answers are inferred", js: true do
- it "shows question if the answer could not be inferred" do
- visit("/lettings-logs/#{id}/property-postcode")
- fill_in("lettings-log-postcode-full-field", with: "PO5 3TE")
+ it "can route the user to a different page based on their answer on the current page", js: true do
+ visit("/lettings-logs/#{id}/conditional-question")
+ # using a question name that is already in the db to avoid
+ # having to add a new column to the db for this test
+ choose("lettings-log-preg-occ-1-field", allow_label_click: true)
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-yes-page")
+ click_link(text: "Back")
+ expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question")
+ choose("lettings-log-preg-occ-2-field", allow_label_click: true)
click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
+ expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
end
- it "shows question if the answer could not be inferred from an empty input" do
- visit("/lettings-logs/#{id}/property-postcode")
+ it "can route based on multiple conditions", js: true do
+ visit("/lettings-logs/#{id}/person-1-gender")
+ choose("lettings-log-sex1-f-field", allow_label_click: true)
click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
+ expect(page).to have_current_path("/lettings-logs/#{id}/person-1-working-situation")
+ visit("/lettings-logs/#{id}/conditional-question")
+ choose("lettings-log-preg-occ-2-field", allow_label_click: true)
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question-no-page")
+ choose("lettings-log-cbl-0-field", allow_label_click: true)
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/conditional-question/check-answers")
end
- it "does not show question if the answer could be inferred" do
- stub_request(:get, /api.postcodes.io/)
- .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
+ context "when the answers are inferred", js: true do
+ it "shows question if the answer could not be inferred" do
+ visit("/lettings-logs/#{id}/property-postcode")
+ fill_in("lettings-log-postcode-full-field", with: "PO5 3TE")
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
+ end
- visit("/lettings-logs/#{id}/property-postcode")
- fill_in("lettings-log-postcode-full-field", with: "P0 5ST")
- click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/property-wheelchair-accessible")
- end
- end
+ it "shows question if the answer could not be inferred from an empty input" do
+ visit("/lettings-logs/#{id}/property-postcode")
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/do-you-know-the-local-authority")
+ end
- context "when answer is invalid" do
- it "shows error with invalid value in the field" do
- visit("/lettings-logs/#{id}/property-postcode")
- fill_in("lettings-log-postcode-full-field", with: "fake_postcode")
- click_button("Save and continue")
+ it "does not show question if the answer could be inferred" do
+ stub_request(:get, /api.postcodes.io/)
+ .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
- expect(page).to have_current_path("/lettings-logs/#{id}/property-postcode")
- expect(find("#lettings-log-postcode-full-field-error").value).to eq("fake_postcode")
+ visit("/lettings-logs/#{id}/property-postcode")
+ fill_in("lettings-log-postcode-full-field", with: "P0 5ST")
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{id}/property-wheelchair-accessible")
+ end
end
- it "does not reset the displayed date" do
- lettings_log.update!(startdate: "2021/10/13")
- visit("/lettings-logs/#{id}/tenancy-start-date")
- fill_in("lettings_log[startdate(1i)]", with: "202")
- fill_in("lettings_log[startdate(2i)]", with: "32")
- fill_in("lettings_log[startdate(3i)]", with: "0")
- click_button("Save and continue")
+ context "when answer is invalid" do
+ it "shows error with invalid value in the field" do
+ visit("/lettings-logs/#{id}/property-postcode")
+ fill_in("lettings-log-postcode-full-field", with: "fake_postcode")
+ click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
- expect(find_field("lettings_log[startdate(3i)]").value).to eq("13")
- expect(find_field("lettings_log[startdate(2i)]").value).to eq("10")
- expect(find_field("lettings_log[startdate(1i)]").value).to eq("2021")
- end
+ expect(page).to have_current_path("/lettings-logs/#{id}/property-postcode")
+ expect(find("#lettings-log-postcode-full-field-error").value).to eq("fake_postcode")
+ end
- it "does not reset the displayed date if it's empty" do
- lettings_log.update!(startdate: nil)
- visit("/lettings-logs/#{id}/tenancy-start-date")
- fill_in("lettings_log[startdate(1i)]", with: "202")
- fill_in("lettings_log[startdate(2i)]", with: "32")
- fill_in("lettings_log[startdate(3i)]", with: "0")
- click_button("Save and continue")
+ it "does not reset the displayed date" do
+ lettings_log.update!(startdate: "2021/10/13")
+ visit("/lettings-logs/#{id}/tenancy-start-date")
+ fill_in("lettings_log[startdate(1i)]", with: "202")
+ fill_in("lettings_log[startdate(2i)]", with: "32")
+ fill_in("lettings_log[startdate(3i)]", with: "0")
+ click_button("Save and continue")
+
+ expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
+ expect(find_field("lettings_log[startdate(3i)]").value).to eq("13")
+ expect(find_field("lettings_log[startdate(2i)]").value).to eq("10")
+ expect(find_field("lettings_log[startdate(1i)]").value).to eq("2021")
+ end
- expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
- expect(find_field("lettings_log[startdate(3i)]").value).to eq(nil)
- expect(find_field("lettings_log[startdate(2i)]").value).to eq(nil)
- expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil)
+ it "does not reset the displayed date if it's empty" do
+ lettings_log.update!(startdate: nil)
+ visit("/lettings-logs/#{id}/tenancy-start-date")
+ fill_in("lettings_log[startdate(1i)]", with: "202")
+ fill_in("lettings_log[startdate(2i)]", with: "32")
+ fill_in("lettings_log[startdate(3i)]", with: "0")
+ click_button("Save and continue")
+
+ expect(page).to have_current_path("/lettings-logs/#{id}/tenancy-start-date")
+ expect(find_field("lettings_log[startdate(3i)]").value).to eq(nil)
+ expect(find_field("lettings_log[startdate(2i)]").value).to eq(nil)
+ expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil)
+ end
end
end
diff --git a/spec/features/form/progressive_total_field_spec.rb b/spec/features/form/progressive_total_field_spec.rb
index 787174c20..cbf50f206 100644
--- a/spec/features/form/progressive_total_field_spec.rb
+++ b/spec/features/form/progressive_total_field_spec.rb
@@ -12,6 +12,15 @@ RSpec.describe "Accessible Autocomplete" do
)
end
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
before do
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
sign_in user
diff --git a/spec/features/form/saving_data_spec.rb b/spec/features/form/saving_data_spec.rb
index 7a7996457..0c7397511 100644
--- a/spec/features/form/saving_data_spec.rb
+++ b/spec/features/form/saving_data_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "Form Saving Data" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
diff --git a/spec/features/form/tasklist_page_spec.rb b/spec/features/form/tasklist_page_spec.rb
index 09d332583..ba06a4051 100644
--- a/spec/features/form/tasklist_page_spec.rb
+++ b/spec/features/form/tasklist_page_spec.rb
@@ -36,18 +36,32 @@ RSpec.describe "Task List" do
:about_completed,
owning_organisation: user.organisation,
managing_organisation: user.organisation,
- startdate: Time.zone.local(2021, 5, 1),
created_by: user,
)
end
let(:id) { lettings_log.id }
let(:status) { lettings_log.status }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
before do
+ Timecop.freeze(Time.zone.local(2021, 5, 1))
+ setup_completed_log.update!(startdate: Time.zone.local(2021, 5, 1))
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
sign_in user
end
+ after do
+ Timecop.unfreeze
+ end
+
it "shows if the section has not been started" do
visit("/lettings-logs/#{empty_lettings_log.id}")
expect(page).to have_content("This log has not been started.")
diff --git a/spec/features/form/validations_spec.rb b/spec/features/form/validations_spec.rb
index 24b2816ce..12e5bb657 100644
--- a/spec/features/form/validations_spec.rb
+++ b/spec/features/form/validations_spec.rb
@@ -2,6 +2,15 @@ require "rails_helper"
require_relative "helpers"
RSpec.describe "validations" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) do
@@ -26,6 +35,8 @@ RSpec.describe "validations" do
status: 1,
declaration: nil,
startdate: Time.zone.local(2021, 5, 1),
+ voiddate: Time.zone.local(2021, 5, 1),
+ mrcdate: Time.zone.local(2021, 5, 1),
)
end
let(:id) { lettings_log.id }
diff --git a/spec/fixtures/exports/general_needs_log.csv b/spec/fixtures/exports/general_needs_log.csv
index 8cc656f19..0185f54e0 100644
--- a/spec/fixtures/exports/general_needs_log.csv
+++ b/spec/fixtures/exports/general_needs_log.csv
@@ -1,2 +1,2 @@
status,tenancycode,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,ppcodenk,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,hhtype,new_old,vacdays,formid,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate
-2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-02-08T16:52:15+00:00,2022-02-08T16:52:15+00:00
+2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00
diff --git a/spec/fixtures/exports/general_needs_log.xml b/spec/fixtures/exports/general_needs_log.xml
index 62542af54..f05de09e3 100644
--- a/spec/fixtures/exports/general_needs_log.xml
+++ b/spec/fixtures/exports/general_needs_log.xml
@@ -142,8 +142,8 @@
{managing_org_id}
DLUHC
1234
- 2022-02-08T16:52:15+00:00
- 2022-02-08T16:52:15+00:00
+ 2022-05-01T00:00:00+01:00
+ 2022-05-01T00:00:00+01:00
1
diff --git a/spec/fixtures/exports/supported_housing_logs.xml b/spec/fixtures/exports/supported_housing_logs.xml
index 69f52161c..0a0ed0981 100644
--- a/spec/fixtures/exports/supported_housing_logs.xml
+++ b/spec/fixtures/exports/supported_housing_logs.xml
@@ -141,8 +141,8 @@
{managing_org_id}
DLUHC
1234
- 2022-02-08T16:52:15+00:00
- 2022-02-08T16:52:15+00:00
+ 2022-05-01T00:00:00+01:00
+ 2022-05-01T00:00:00+01:00
7
1
G
diff --git a/spec/helpers/check_answers_helper_spec.rb b/spec/helpers/check_answers_helper_spec.rb
index d60c79f51..716c93827 100644
--- a/spec/helpers/check_answers_helper_spec.rb
+++ b/spec/helpers/check_answers_helper_spec.rb
@@ -6,6 +6,15 @@ RSpec.describe CheckAnswersHelper do
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:current_user) { FactoryBot.build(:user) }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
describe "display_answered_questions_summary" do
context "when a section hasn't been completed yet" do
it "returns that you have unanswered questions" do
diff --git a/spec/helpers/form_page_error_helper_spec.rb b/spec/helpers/form_page_error_helper_spec.rb
index e2b342a40..ae9d22494 100644
--- a/spec/helpers/form_page_error_helper_spec.rb
+++ b/spec/helpers/form_page_error_helper_spec.rb
@@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe FormPageErrorHelper do
describe "#remove_other_page_errors" do
context "when non base other questions are removed" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let!(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress) }
let!(:form) { lettings_log.form }
diff --git a/spec/helpers/interruption_screen_helper_spec.rb b/spec/helpers/interruption_screen_helper_spec.rb
index f46aca9ae..fba8782da 100644
--- a/spec/helpers/interruption_screen_helper_spec.rb
+++ b/spec/helpers/interruption_screen_helper_spec.rb
@@ -17,6 +17,15 @@ RSpec.describe InterruptionScreenHelper do
)
end
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
describe "display_informative_text" do
context "when 2 out of 2 arguments are given" do
it "returns correct informative text" do
diff --git a/spec/helpers/tasklist_helper_spec.rb b/spec/helpers/tasklist_helper_spec.rb
index f0cec71ad..5d75616ec 100644
--- a/spec/helpers/tasklist_helper_spec.rb
+++ b/spec/helpers/tasklist_helper_spec.rb
@@ -1,7 +1,7 @@
require "rails_helper"
RSpec.describe TasklistHelper do
- let(:now) { Time.utc(2022, 6, 1) }
+ let(:now) { Time.utc(2022, 1, 1) }
around do |example|
Timecop.freeze(now) do
@@ -13,7 +13,7 @@ RSpec.describe TasklistHelper do
describe "with lettings" do
let(:empty_lettings_log) { create(:lettings_log) }
- let(:lettings_log) { build(:lettings_log, :in_progress, needstype: 1) }
+ let(:lettings_log) { build(:lettings_log, :in_progress, needstype: 1, startdate: now) }
describe "get next incomplete section" do
it "returns the first subsection name if it is not completed" do
@@ -27,8 +27,14 @@ RSpec.describe TasklistHelper do
end
describe "get sections count" do
+ let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
+
+ before do
+ allow(FormHandler.instance).to receive(:get_form).and_return(fake_2021_2022_form)
+ end
+
it "returns the total of sections if no status is given" do
- expect(get_subsections_count(empty_lettings_log)).to eq(1)
+ expect(get_subsections_count(empty_lettings_log)).to eq(8)
end
it "returns 0 sections for completed sections if no sections are completed" do
@@ -36,7 +42,7 @@ RSpec.describe TasklistHelper do
end
it "returns the number of not started sections" do
- expect(get_subsections_count(empty_lettings_log, :not_started)).to eq(1)
+ expect(get_subsections_count(empty_lettings_log, :not_started)).to eq(8)
end
it "returns the number of sections in progress" do
@@ -48,41 +54,6 @@ RSpec.describe TasklistHelper do
end
end
- describe "review_log_text" do
- context "when collection_period_open? == true" do
- context "with 2023 deadline" do
- let(:now) { Time.utc(2022, 6, 1) }
- let(:lettings_log) { create(:lettings_log, :completed) }
-
- it "returns relevant text" do
- expect(review_log_text(lettings_log)).to eq(
- "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 1 July 2023.".html_safe,
- )
- end
- end
-
- context "with 2024 deadline" do
- let(:now) { Time.utc(2023, 6, 20) }
- let(:lettings_log) { create(:lettings_log, :completed, national: 18, waityear: 2) }
-
- it "returns relevant text" do
- expect(review_log_text(lettings_log)).to eq(
- "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 July 2024.".html_safe,
- )
- end
- end
- end
-
- context "when collection_period_open? == false" do
- let(:now) { Time.utc(2023, 7, 8) }
- let(:lettings_log) { create(:lettings_log, :completed, startdate: Time.utc(2023, 2, 8)) }
-
- it "returns relevant text" do
- expect(review_log_text(lettings_log)).to eq("This log is from the 2022/2023 collection window, which is now closed.")
- end
- end
- end
-
describe "subsection link" do
let(:lettings_log) { create(:lettings_log, :completed) }
let(:subsection) { lettings_log.form.get_subsection("household_characteristics") }
@@ -130,5 +101,42 @@ RSpec.describe TasklistHelper do
end
end
end
+
+ context "with lettings log" do
+ context "when collection_period_open? == true" do
+ context "with 2023 deadline" do
+ let(:now) { Time.utc(2022, 6, 1) }
+ let(:lettings_log) { create(:lettings_log, :completed) }
+
+ it "returns relevant text" do
+ expect(review_log_text(lettings_log)).to eq(
+ "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 1 July 2023.".html_safe,
+ )
+ end
+ end
+
+ context "with 2024 deadline" do
+ let(:now) { Time.utc(2023, 6, 20) }
+ let(:lettings_log) { create(:lettings_log, :completed, national: 18, waityear: 2) }
+
+ it "returns relevant text" do
+ expect(review_log_text(lettings_log)).to eq(
+ "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 July 2024.".html_safe,
+ )
+ end
+ end
+ end
+
+ context "when collection_period_open? == false" do
+ let(:now) { Time.utc(2022, 6, 1) }
+ let!(:sales_log) { create(:lettings_log, :completed) }
+
+ it "returns relevant text" do
+ Timecop.freeze(now + 1.year) do
+ expect(review_log_text(sales_log)).to eq("This log is from the 2021/2022 collection window, which is now closed.")
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/jobs/email_csv_job_spec.rb b/spec/jobs/email_csv_job_spec.rb
index 5ff0b3355..04776aac7 100644
--- a/spec/jobs/email_csv_job_spec.rb
+++ b/spec/jobs/email_csv_job_spec.rb
@@ -31,7 +31,9 @@ describe EmailCsvJob do
FactoryBot.create(:lettings_log,
:completed,
created_by: user,
- startdate: Time.zone.local(2021, 5, 1))
+ startdate: Time.zone.local(2022, 5, 1),
+ voiddate: Time.zone.local(2022, 5, 1),
+ mrcdate: Time.zone.local(2022, 5, 1))
allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(storage_service).to receive(:write_file)
@@ -104,7 +106,7 @@ describe EmailCsvJob do
it "writes answer labels rather than values" do
expect_csv do |csv|
- expect(csv.second[16]).to eq("Full-time – 30 hours or more")
+ expect(csv.second[19]).to eq("Full-time – 30 hours or more")
end
job.perform(user)
diff --git a/spec/models/form/page_spec.rb b/spec/models/form/page_spec.rb
index 4a870fe46..17bd7dcc9 100644
--- a/spec/models/form/page_spec.rb
+++ b/spec/models/form/page_spec.rb
@@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe Form::Page, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:user) { FactoryBot.create(:user) }
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
diff --git a/spec/models/form/question_spec.rb b/spec/models/form/question_spec.rb
index 48e71c76b..ede6636f7 100644
--- a/spec/models/form/question_spec.rb
+++ b/spec/models/form/question_spec.rb
@@ -3,6 +3,15 @@ require "rails_helper"
RSpec.describe Form::Question, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
let(:section_id) { "rent_and_charges" }
@@ -367,7 +376,7 @@ RSpec.describe Form::Question, type: :model do
end
context "when Sales form" do
- let(:sales_log) { FactoryBot.create(:sales_log, :completed, ethnic_group: 17) }
+ let(:sales_log) { FactoryBot.create(:sales_log, :completed, ethnic_group: 17, saledate: Time.zone.local(2022, 1, 1)) }
let(:question) { sales_log.form.get_question("ethnic_group", sales_log) }
it "returns the inferred label value" do
diff --git a/spec/models/form/subsection_spec.rb b/spec/models/form/subsection_spec.rb
index 46880a33a..3e224dd38 100644
--- a/spec/models/form/subsection_spec.rb
+++ b/spec/models/form/subsection_spec.rb
@@ -4,6 +4,15 @@ require_relative "../../request_helper"
RSpec.describe Form::Subsection, type: :model do
subject(:subsection) { described_class.new(subsection_id, subsection_definition, section) }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:lettings_log) { FactoryBot.build(:lettings_log) }
let(:form) { lettings_log.form }
let(:section_id) { "household" }
diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb
index cd58587dc..cac779e33 100644
--- a/spec/models/form_spec.rb
+++ b/spec/models/form_spec.rb
@@ -1,6 +1,15 @@
require "rails_helper"
RSpec.describe Form, type: :model do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:user) { FactoryBot.build(:user) }
let(:lettings_log) { FactoryBot.build(:lettings_log, :in_progress) }
let(:form) { lettings_log.form }
diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb
index b35ab5bb1..e2431ff92 100644
--- a/spec/models/lettings_log_spec.rb
+++ b/spec/models/lettings_log_spec.rb
@@ -6,6 +6,16 @@ RSpec.describe LettingsLog do
let(:created_by_user) { create(:user) }
let(:owning_organisation) { created_by_user.organisation }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
+ let(:fake_2022_2023_form) { Form.new("spec/fixtures/forms/2022_2023.json") }
+
+ around do |example|
+ Timecop.freeze(Time.utc(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
before do
allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
@@ -33,7 +43,15 @@ RSpec.describe LettingsLog do
let(:lettings_log_2) { build(:lettings_log, startdate: Time.zone.local(2022, 1, 1), created_by: created_by_user) }
let(:lettings_log_year_2) { build(:lettings_log, startdate: Time.zone.local(2023, 5, 1), created_by: created_by_user) }
- it "has returns the correct form based on the start date" do
+ before do
+ Timecop.freeze(2023, 1, 1)
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ it "returns the correct form based on the start date" do
expect(lettings_log.form_name).to be_nil
expect(lettings_log.form).to be_a(Form)
expect(lettings_log_2.form_name).to eq("previous_lettings")
@@ -1477,10 +1495,15 @@ RSpec.describe LettingsLog do
context "when deriving renttype and unitletas" do
before do
+ Timecop.freeze(Time.zone.local(2022, 1, 1))
allow(FeatureToggle).to receive(:startdate_two_week_validation_enabled?).and_return(false)
lettings_log.update!(rent_type:, irproduct_other: "other")
end
+ after do
+ Timecop.unfreeze
+ end
+
context "when the rent_type is Social Rent (0)" do
let(:rent_type) { 0 }
@@ -1497,6 +1520,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as Social rent(1)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1522,6 +1562,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as Affordable Rent basis(2)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1547,6 +1604,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as London Affordable Rent basis(5)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1572,6 +1646,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as Rent to Buy basis(6)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1597,6 +1688,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as London Living Rent basis(7)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1622,6 +1730,23 @@ RSpec.describe LettingsLog do
end
context "and it is a 23/24 form" do
+ before do
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "derives and saves unitletas as Other intermediate rent basis(8)" do
lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1863,7 +1988,11 @@ RSpec.describe LettingsLog do
let(:scheme) { create(:scheme) }
let!(:location) { create(:location, scheme:) }
- before { lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:) }
+ before do
+ Timecop.freeze(Time.zone.local(2022, 4, 2))
+ lettings_log.update!(startdate: Time.zone.local(2022, 4, 2), scheme:)
+ Timecop.unfreeze
+ end
it "derives the scheme location" do
record_from_db = ActiveRecord::Base.connection.execute("select location_id from lettings_logs where id=#{lettings_log.id}").to_a[0]
@@ -1950,9 +2079,16 @@ RSpec.describe LettingsLog do
end
context "and renewal" do
+ before do
+ Timecop.freeze(Time.zone.local(2022, 4, 2))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
let(:scheme) { create(:scheme) }
let(:location) { create(:location, scheme:) }
-
let!(:supported_housing_lettings_log) do
described_class.create!({
managing_organisation: owning_organisation,
@@ -1962,12 +2098,12 @@ RSpec.describe LettingsLog do
scheme_id: scheme.id,
location_id: location.id,
renewal: 1,
- startdate: Time.zone.now,
+ startdate: Time.zone.local(2022, 4, 2),
created_at: Time.utc(2022, 2, 8, 16, 52, 15),
})
end
- it "correcly infers and saves the renewal date" do
+ it "correctly infers and saves the renewal date" do
record_from_db = ActiveRecord::Base.connection.execute("SELECT voiddate from lettings_logs where id=#{supported_housing_lettings_log.id}").to_a[0]
expect(record_from_db["voiddate"].to_i).to eq(supported_housing_lettings_log.startdate.to_i)
end
@@ -2333,6 +2469,15 @@ RSpec.describe LettingsLog do
end
context "and the new location triggers the rent range validation" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 4, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "clears rent values" do
lettings_log.update!(location:, scheme:)
lettings_log.reload
@@ -2467,8 +2612,8 @@ RSpec.describe LettingsLog do
end
describe "scopes" do
- let!(:lettings_log_1) { create(:lettings_log, :in_progress, startdate: Time.utc(2021, 5, 3), created_by: created_by_user) }
- let!(:lettings_log_2) { create(:lettings_log, :completed, startdate: Time.utc(2021, 5, 3), created_by: created_by_user) }
+ let!(:lettings_log_1) { create(:lettings_log, :in_progress, startdate: Time.utc(2021, 5, 3), mrcdate: Time.utc(2021, 5, 3), voiddate: Time.utc(2021, 5, 3), created_by: created_by_user) }
+ let!(:lettings_log_2) { create(:lettings_log, :completed, startdate: Time.utc(2021, 5, 3), mrcdate: Time.utc(2021, 5, 3), voiddate: Time.utc(2021, 5, 3), created_by: created_by_user) }
before do
Timecop.freeze(Time.utc(2022, 6, 3))
@@ -2755,7 +2900,7 @@ RSpec.describe LettingsLog do
context "with values represented as human readable labels" do
before do
Timecop.freeze(Time.utc(2022, 6, 5))
- lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2))
+ lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2), created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15))
expected_content.sub!(/\{id\}/, lettings_log["id"].to_s)
expected_content.sub!(/\{scheme_code\}/, "S#{scheme['id']}")
expected_content.sub!(/\{scheme_service_name\}/, scheme["service_name"].to_s)
@@ -2770,6 +2915,15 @@ RSpec.describe LettingsLog do
expected_content.sub!(/\{location_id\}/, location["id"].to_s)
end
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 6, 5)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
context "with a support user" do
let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download.csv", "r:UTF-8") }
@@ -2790,7 +2944,7 @@ RSpec.describe LettingsLog do
context "with values represented as codes" do
before do
Timecop.freeze(Time.utc(2022, 6, 5))
- lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2))
+ lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2), created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15))
expected_content.sub!(/\{id\}/, lettings_log["id"].to_s)
expected_content.sub!(/\{scheme_code\}/, "S#{scheme.id}")
expected_content.sub!(/\{scheme_service_name\}/, scheme.service_name.to_s)
@@ -2807,6 +2961,15 @@ RSpec.describe LettingsLog do
let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download_codes_only.csv", "r:UTF-8") }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 6, 5)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
it "generates a correct csv from a lettings log" do
expect(described_class.to_csv(codes_only_export: true)).to eq(expected_content)
end
diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb
index 20d1e094c..cd6e38f50 100644
--- a/spec/models/validations/date_validations_spec.rb
+++ b/spec/models/validations/date_validations_spec.rb
@@ -9,18 +9,6 @@ RSpec.describe Validations::DateValidations do
let(:scheme_no_end_date) { FactoryBot.create(:scheme, end_date: nil) }
describe "tenancy start date" do
- it "cannot be before the first collection window start date" do
- record.startdate = Time.zone.local(2020, 1, 1)
- date_validator.validate_startdate(record)
- expect(record.errors["startdate"]).to include(match I18n.t("validations.date.outside_collection_window"))
- end
-
- it "cannot be after the second collection window end date" do
- record.startdate = Time.zone.local(2023, 7, 1, 6)
- date_validator.validate_startdate(record)
- expect(record.errors["startdate"]).to include(match I18n.t("validations.date.outside_collection_window"))
- end
-
it "must be a valid date" do
record.startdate = Time.zone.local(0, 7, 1)
date_validator.validate_startdate(record)
@@ -98,7 +86,7 @@ RSpec.describe Validations::DateValidations do
record.location = location
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -123,7 +111,7 @@ RSpec.describe Validations::DateValidations do
record.location = location
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -150,7 +138,7 @@ RSpec.describe Validations::DateValidations do
record.location = location
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 September 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -177,7 +165,7 @@ RSpec.describe Validations::DateValidations do
record.location = location
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end
end
@@ -194,7 +182,7 @@ RSpec.describe Validations::DateValidations do
record.scheme = scheme
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
+ .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@@ -220,7 +208,7 @@ RSpec.describe Validations::DateValidations do
record.scheme = scheme
date_validator.validate_startdate(record)
expect(record.errors["startdate"])
- .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb
index bdd76cded..c2fe3b963 100644
--- a/spec/models/validations/financial_validations_spec.rb
+++ b/spec/models/validations/financial_validations_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe Validations::FinancialValidations do
end
context "when outstanding rent or charges is yes" do
- let(:record) { FactoryBot.create(:lettings_log, :about_completed) }
+ let(:record) { FactoryBot.create(:lettings_log, :about_completed, startdate: Time.zone.now) }
it "expects that a shortfall is provided" do
record.hbrentshortfall = 1
diff --git a/spec/models/validations/sales/setup_validations_spec.rb b/spec/models/validations/sales/setup_validations_spec.rb
index e5c563c9e..136e239d3 100644
--- a/spec/models/validations/sales/setup_validations_spec.rb
+++ b/spec/models/validations/sales/setup_validations_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end
end
- context "when saledate is in the 22/23 financial year" do
+ context "when saledate is in the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2023, 1, 1)) }
it "does not add an error" do
@@ -27,23 +27,23 @@ RSpec.describe Validations::Sales::SetupValidations do
end
end
- context "when saledate is before the 22/23 financial year" do
+ context "when saledate is before the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 1, 1)) }
it "adds error" do
setup_validator.validate_saledate(record)
- expect(record.errors[:saledate]).to include("Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023")
+ expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end
end
- context "when saledate is after the 22/23 financial year" do
+ context "when saledate is after the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) }
it "adds error" do
setup_validator.validate_saledate(record)
- expect(record.errors[:saledate]).to include("Enter a date within the 22/23 financial year, which is between 1st April 2022 and 31st March 2023")
+ expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
end
end
end
@@ -67,7 +67,7 @@ RSpec.describe Validations::Sales::SetupValidations do
end
end
- context "when saledate is in the 22/23 financial year" do
+ context "when saledate is in the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 1, 1)) }
it "does not add an error" do
@@ -77,23 +77,23 @@ RSpec.describe Validations::Sales::SetupValidations do
end
end
- context "when saledate is before the 22/23 financial year" do
+ context "when saledate is before the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 5, 1)) }
it "adds error" do
setup_validator.validate_saledate(record)
- expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 financial years, which is between 1st April 2023 and 31st March 2025")
+ expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025")
end
end
- context "when saledate is after the 22/23 financial year" do
+ context "when saledate is after the 22/23 collection year" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) }
it "adds error" do
setup_validator.validate_saledate(record)
- expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 financial years, which is between 1st April 2023 and 31st March 2025")
+ expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025")
end
end
end
diff --git a/spec/models/validations/setup_validations_spec.rb b/spec/models/validations/setup_validations_spec.rb
index 326a6936d..69e22f1e2 100644
--- a/spec/models/validations/setup_validations_spec.rb
+++ b/spec/models/validations/setup_validations_spec.rb
@@ -6,13 +6,95 @@ RSpec.describe Validations::SetupValidations do
let(:setup_validator_class) { Class.new { include Validations::SetupValidations } }
let(:record) { FactoryBot.create(:lettings_log) }
+ describe "tenancy start date" do
+ context "when in 22/23 collection" do
+ context "when in the crossover period" do
+ before do
+ allow(Time).to receive(:now).and_return(Time.zone.local(2022, 4, 1))
+ record.created_at = Time.zone.local(2022, 4, 1)
+ end
+
+ it "cannot be before the first collection window start date" do
+ record.startdate = Time.zone.local(2021, 1, 1)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 21/22 or 22/23 collection years, which is between 1st April 2021 and 31st March 2023")
+ end
+
+ it "cannot be after the second collection window end date" do
+ record.startdate = Time.zone.local(2023, 7, 1, 6)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 21/22 or 22/23 collection years, which is between 1st April 2021 and 31st March 2023")
+ end
+ end
+
+ context "when after the crossover period" do
+ before do
+ allow(Time).to receive(:now).and_return(Time.zone.local(2023, 1, 1))
+ record.created_at = Time.zone.local(2023, 1, 1)
+ end
+
+ it "cannot be before the first collection window start date" do
+ record.startdate = Time.zone.local(2022, 1, 1)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
+ end
+
+ it "cannot be after the second collection window end date" do
+ record.startdate = Time.zone.local(2023, 7, 1, 6)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023")
+ end
+ end
+ end
+
+ context "when in 23/24 collection" do
+ context "when in the crossover period" do
+ before do
+ allow(Time).to receive(:now).and_return(Time.zone.local(2023, 4, 1))
+ record.created_at = Time.zone.local(2023, 4, 1)
+ end
+
+ it "cannot be before the first collection window start date" do
+ record.startdate = Time.zone.local(2022, 1, 1)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 or 23/24 collection years, which is between 1st April 2022 and 31st March 2024")
+ end
+
+ it "cannot be after the second collection window end date" do
+ record.startdate = Time.zone.local(2024, 7, 1, 6)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 22/23 or 23/24 collection years, which is between 1st April 2022 and 31st March 2024")
+ end
+ end
+
+ context "when after the crossover period" do
+ before do
+ allow(Time).to receive(:now).and_return(Time.zone.local(2024, 1, 1))
+ record.created_at = Time.zone.local(2024, 1, 1)
+ end
+
+ it "cannot be before the first collection window start date" do
+ record.startdate = Time.zone.local(2023, 1, 1)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 23/24 collection year, which is between 1st April 2023 and 31st March 2024")
+ end
+
+ it "cannot be after the second collection window end date" do
+ record.startdate = Time.zone.local(2024, 7, 1, 6)
+ setup_validator.validate_startdate_setup(record)
+ expect(record.errors["startdate"]).to include(match "Enter a date within the 23/24 collection year, which is between 1st April 2023 and 31st March 2024")
+ end
+ end
+ end
+ end
+
describe "#validate_irproduct" do
it "adds an error when the intermediate rent product name is not provided but the rent type was given as other intermediate rent product" do
record.rent_type = 5
record.irproduct_other = nil
setup_validator.validate_irproduct_other(record)
expect(record.errors["irproduct_other"])
- .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
+ .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
end
it "adds an error when the intermediate rent product name is blank but the rent type was given as other intermediate rent product" do
@@ -20,7 +102,7 @@ RSpec.describe Validations::SetupValidations do
record.irproduct_other = ""
setup_validator.validate_irproduct_other(record)
expect(record.errors["irproduct_other"])
- .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
+ .to include(match I18n.t("validations.setup.intermediate_rent_product_name.blank"))
end
it "Does not add an error when the intermediate rent product name is provided and the rent type was given as other intermediate rent product" do
@@ -46,7 +128,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
- .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -71,7 +153,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
- .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -98,7 +180,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
- .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end
end
@@ -115,7 +197,7 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
- .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
+ .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@@ -141,7 +223,7 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme
setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"])
- .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon", name: scheme.service_name, date: "4 September 2022"))
end
it "produces no error when tenancy start date is during an active scheme period" do
@@ -168,7 +250,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["location_id"])
- .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.deactivated", postcode: location.postcode, date: "4 June 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -193,7 +275,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["location_id"])
- .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.reactivating_soon", postcode: location.postcode, date: "4 August 2022"))
end
it "produces no error when tenancy start date is during an active location period" do
@@ -220,7 +302,7 @@ RSpec.describe Validations::SetupValidations do
record.location = location
setup_validator.validate_location(record)
expect(record.errors["location_id"])
- .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
+ .to include(match I18n.t("validations.setup.startdate.location.activating_soon", postcode: location.postcode, date: "15 September 2022"))
end
end
end
diff --git a/spec/models/validations/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb
index 9ca9436fb..3ce2b4527 100644
--- a/spec/models/validations/soft_validations_spec.rb
+++ b/spec/models/validations/soft_validations_spec.rb
@@ -207,6 +207,14 @@ RSpec.describe Validations::SoftValidations do
end
describe "major repairs date soft validations" do
+ before do
+ Timecop.freeze(Time.zone.local(2022, 2, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
context "when the major repairs date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do
record.update!(startdate: Time.zone.local(2022, 2, 1), mrcdate: Time.zone.local(2013, 2, 1))
@@ -223,6 +231,14 @@ RSpec.describe Validations::SoftValidations do
end
describe "void date soft validations" do
+ before do
+ Timecop.freeze(Time.zone.local(2022, 2, 1))
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
context "when the void date is within 10 years of the tenancy start date" do
it "shows the interruption screen" do
record.update!(startdate: Time.zone.local(2022, 2, 1), voiddate: Time.zone.local(2013, 2, 1))
diff --git a/spec/models/validations/tenancy_validations_spec.rb b/spec/models/validations/tenancy_validations_spec.rb
index 2d008e6e3..8f7d79e29 100644
--- a/spec/models/validations/tenancy_validations_spec.rb
+++ b/spec/models/validations/tenancy_validations_spec.rb
@@ -3,6 +3,10 @@ require "rails_helper"
RSpec.describe Validations::TenancyValidations do
subject(:tenancy_validator) { validator_class.new }
+ before do
+ Timecop.freeze(Time.zone.local(2021, 5, 1))
+ end
+
let(:validator_class) { Class.new { include Validations::TenancyValidations } }
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), needstype: 1, rent_type: 1) }
@@ -117,6 +121,14 @@ RSpec.describe Validations::TenancyValidations do
end
context "when the collection start year is 2022 or later" do
+ before do
+ Timecop.freeze(2022, 5, 1)
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1), needstype: 1, rent_type: 1) }
context "when type of tenancy is Secure - fixed term" do
@@ -260,6 +272,14 @@ RSpec.describe Validations::TenancyValidations do
describe "joint tenancy validation" do
context "when the data inputter has said that there is only one member in the household" do
+ before do
+ Timecop.freeze(2022, 5, 1)
+ end
+
+ after do
+ Timecop.unfreeze
+ end
+
let(:record) { FactoryBot.create(:lettings_log, startdate: Time.zone.local(2022, 5, 1)) }
let(:expected_error) { I18n.t("validations.tenancy.not_joint") }
let(:hhmemb_expected_error) { I18n.t("validations.tenancy.joint_more_than_one_member") }
diff --git a/spec/requests/form_controller_spec.rb b/spec/requests/form_controller_spec.rb
index d5a8dbcf8..9dce39af2 100644
--- a/spec/requests/form_controller_spec.rb
+++ b/spec/requests/form_controller_spec.rb
@@ -17,7 +17,6 @@ RSpec.describe FormController, type: :request do
:lettings_log,
:about_completed,
status: 1,
- startdate: Time.zone.local(2021, 10, 10),
created_by: user,
)
end
@@ -26,7 +25,6 @@ RSpec.describe FormController, type: :request do
:lettings_log,
:completed,
created_by: user,
- startdate: Time.zone.local(2021, 5, 1),
)
end
let(:headers) { { "Accept" => "text/html" } }
@@ -204,10 +202,13 @@ RSpec.describe FormController, type: :request do
describe "GET" do
context "with form pages" do
context "when forms exist for multiple years" do
- let(:lettings_log_year_1) { create(:lettings_log, startdate: Time.zone.local(2021, 5, 1), owning_organisation: organisation, created_by: user) }
+ let(:lettings_log_year_1) { create(:lettings_log, owning_organisation: organisation, created_by: user) }
let(:lettings_log_year_2) { create(:lettings_log, :about_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) }
before do
+ Timecop.freeze(Time.zone.local(2021, 5, 1))
+ lettings_log_year_1.update!(startdate: Time.zone.local(2021, 5, 1))
+ Timecop.unfreeze
allow(lettings_log_year_1.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
end
@@ -663,6 +664,15 @@ RSpec.describe FormController, type: :request do
end
let(:referrer) { "/lettings-logs/#{completed_lettings_log.id}/net-income-value-check?referrer=check_answers" }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
before do
completed_lettings_log.update!(ecstat1: 1, earnings: 130, hhmemb: 1) # we're not routing to that page, so it gets cleared?
allow(completed_lettings_log).to receive(:net_income_soft_validation_triggered?).and_return(true)
diff --git a/spec/requests/lettings_logs_controller_spec.rb b/spec/requests/lettings_logs_controller_spec.rb
index 116c88c4c..c5ee2a6ab 100644
--- a/spec/requests/lettings_logs_controller_spec.rb
+++ b/spec/requests/lettings_logs_controller_spec.rb
@@ -333,6 +333,13 @@ RSpec.describe LettingsLogsController, type: :request do
end
context "with year filter" do
+ around do |example|
+ Timecop.freeze(2022, 3, 1) do
+ example.run
+ end
+ Timecop.unfreeze
+ end
+
let!(:lettings_log_2021) do
FactoryBot.create(:lettings_log, :in_progress,
created_by: user,
@@ -364,6 +371,8 @@ RSpec.describe LettingsLogsController, type: :request do
context "with year and status filter" do
before do
+ Timecop.freeze(Time.zone.local(2022, 3, 1))
+ lettings_log_2021.update!(startdate: Time.zone.local(2022, 3, 1))
Timecop.freeze(Time.zone.local(2022, 12, 1))
end
@@ -374,7 +383,6 @@ RSpec.describe LettingsLogsController, type: :request do
let!(:lettings_log_2021) do
FactoryBot.create(:lettings_log, :in_progress,
owning_organisation: organisation,
- startdate: Time.zone.local(2022, 3, 1),
managing_organisation: organisation,
created_by: user)
end
@@ -383,6 +391,7 @@ RSpec.describe LettingsLogsController, type: :request do
owning_organisation: organisation,
mrcdate: Time.zone.local(2022, 2, 1),
startdate: Time.zone.local(2022, 12, 1),
+ voiddate: Time.zone.local(2022, 2, 1),
tenancy: 6,
managing_organisation: organisation,
created_by: user)
@@ -846,6 +855,10 @@ RSpec.describe LettingsLogsController, type: :request do
before do
sign_in user
get "/lettings-logs/#{lettings_log.id}", headers:, params: {}
+ Timecop.freeze(2021, 4, 1)
+ completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1), voiddate: Time.zone.local(2021, 4, 1), mrcdate: Time.zone.local(2021, 4, 1))
+ completed_lettings_log.reload
+ Timecop.unfreeze
end
it "shows the tasklist for lettings logs you have access to" do
@@ -871,9 +884,6 @@ RSpec.describe LettingsLogsController, type: :request do
end
it "displays a closed collection window message for previous collection year logs" do
- completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1))
- completed_lettings_log.reload
-
get "/lettings-logs/#{completed_lettings_log.id}", headers:, params: {}
expect(completed_lettings_log.form.end_date).to eq(Time.zone.local(2022, 7, 1))
expect(completed_lettings_log.status).to eq("completed")
@@ -940,19 +950,22 @@ RSpec.describe LettingsLogsController, type: :request do
end
context "when accessing the check answers page" do
+ before do
+ Timecop.freeze(2021, 4, 1)
+ completed_lettings_log.update!(startdate: Time.zone.local(2021, 4, 1), voiddate: Time.zone.local(2021, 4, 1), mrcdate: Time.zone.local(2021, 4, 1))
+ Timecop.unfreeze
+ stub_request(:get, /api.postcodes.io/)
+ .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
+ sign_in user
+ end
+
let(:postcode_lettings_log) do
FactoryBot.create(:lettings_log,
created_by: user,
postcode_known: "No")
end
let(:id) { postcode_lettings_log.id }
- let(:completed_lettings_log) { FactoryBot.create(:lettings_log, :completed, owning_organisation: user.organisation, managing_organisation: user.organisation, created_by: user, startdate: Time.zone.local(2021, 4, 1)) }
-
- before do
- stub_request(:get, /api.postcodes.io/)
- .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
- sign_in user
- end
+ let(:completed_lettings_log) { FactoryBot.create(:lettings_log, :completed, owning_organisation: user.organisation, managing_organisation: user.organisation, created_by: user) }
it "shows the inferred la" do
lettings_log = FactoryBot.create(:lettings_log,
@@ -1154,6 +1167,15 @@ RSpec.describe LettingsLogsController, type: :request do
end
context "with an invalid lettings log params" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
let(:params) { { age1: 200 } }
it "returns 422" do
diff --git a/spec/requests/sales_logs_controller_spec.rb b/spec/requests/sales_logs_controller_spec.rb
index e45fee440..1d68b045b 100644
--- a/spec/requests/sales_logs_controller_spec.rb
+++ b/spec/requests/sales_logs_controller_spec.rb
@@ -231,11 +231,10 @@ RSpec.describe SalesLogsController, type: :request do
end
context "with year and status filter" do
- before do
- Timecop.freeze(Time.zone.local(2022, 12, 1))
- end
-
- after do
+ around do |example|
+ Timecop.freeze(2022, 12, 1) do
+ example.run
+ end
Timecop.unfreeze
end
diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb
index 3cc244456..b1064acd5 100644
--- a/spec/services/csv/lettings_log_csv_service_spec.rb
+++ b/spec/services/csv/lettings_log_csv_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
before do
- LettingsLog.create!(startdate: "2021-10-10", created_at: Time.utc(2022, 2, 8, 16, 52, 15))
+ LettingsLog.create!(startdate: Time.zone.today, created_at: Time.utc(2022, 2, 8, 16, 52, 15))
allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form)
end
diff --git a/spec/services/exports/lettings_log_export_service_spec.rb b/spec/services/exports/lettings_log_export_service_spec.rb
index 55897c354..7c17f95dc 100644
--- a/spec/services/exports/lettings_log_export_service_spec.rb
+++ b/spec/services/exports/lettings_log_export_service_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Exports::LettingsLogExportService do
end
context "and one lettings log is available for export" do
- let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.utc(2022, 2, 2, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
+ let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
it "generates a ZIP export file with the expected filename" do
expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args)
@@ -161,7 +161,7 @@ RSpec.describe Exports::LettingsLogExportService do
context "when this is a second export (partial)" do
before do
- start_time = Time.zone.local(2022, 4, 1)
+ start_time = Time.zone.local(2022, 6, 1)
LogsExport.new(started_at: start_time).save!
end
@@ -237,7 +237,7 @@ RSpec.describe Exports::LettingsLogExportService do
let(:csv_export_file) { File.open("spec/fixtures/exports/general_needs_log.csv", "r:UTF-8") }
let(:expected_csv_filename) { "export_2022_05_01.csv" }
- let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.utc(2022, 2, 2, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
+ let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenancycode: "BZ737", startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4) }
it "generates an CSV export file with the expected content" do
expected_content = replace_entity_ids(lettings_log, csv_export_file.read)
@@ -256,7 +256,7 @@ RSpec.describe Exports::LettingsLogExportService do
let(:scheme) { FactoryBot.create(:scheme, :export, owning_organisation: organisation) }
let(:location) { FactoryBot.create(:location, :export, scheme:, startdate: Time.zone.local(2021, 4, 1)) }
- let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, created_by: user, owning_organisation: organisation, startdate: Time.utc(2022, 2, 2, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) }
+ let(:lettings_log) { FactoryBot.create(:lettings_log, :completed, :export, :sh, scheme:, location:, created_by: user, owning_organisation: organisation, startdate: Time.zone.local(2022, 2, 2, 10, 36, 49), voiddate: Time.zone.local(2019, 11, 3), mrcdate: Time.zone.local(2020, 5, 5, 10, 36, 49), underoccupation_benefitcap: 4, sheltered: 1) }
before do
FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2021, 4, 1), units: nil)
diff --git a/spec/services/imports/lettings_logs_field_import_service_spec.rb b/spec/services/imports/lettings_logs_field_import_service_spec.rb
index 685617041..0c55139e8 100644
--- a/spec/services/imports/lettings_logs_field_import_service_spec.rb
+++ b/spec/services/imports/lettings_logs_field_import_service_spec.rb
@@ -16,6 +16,15 @@ RSpec.describe Imports::LettingsLogsFieldImportService do
let(:old_user_id) { "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa" }
let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
def open_file(directory, filename)
File.open("#{directory}/#{filename}.xml")
end
@@ -27,7 +36,7 @@ RSpec.describe Imports::LettingsLogsFieldImportService do
FactoryBot.create(:user, old_user_id:, organisation:)
# Stub the form handler to use the real form
- allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
+ allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2021_2022_form)
WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
.to_return(status: 200, body: '{"status":200,"result":{"codes":{"admin_district":"E08000035"}}}', headers: {})
diff --git a/spec/services/imports/lettings_logs_import_service_spec.rb b/spec/services/imports/lettings_logs_import_service_spec.rb
index 846c266a5..bfd907620 100644
--- a/spec/services/imports/lettings_logs_import_service_spec.rb
+++ b/spec/services/imports/lettings_logs_import_service_spec.rb
@@ -1,348 +1,333 @@
require "rails_helper"
RSpec.describe Imports::LettingsLogsImportService do
- subject(:lettings_log_service) { described_class.new(storage_service, logger) }
+ context "with 21/22 logs" do
+ subject(:lettings_log_service) { described_class.new(storage_service, logger) }
- let(:storage_service) { instance_double(Storage::S3Service) }
- let(:logger) { instance_double(ActiveSupport::Logger) }
-
- let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
- let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
- let(:fixture_directory) { "spec/fixtures/imports/logs" }
-
- let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
- let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
- let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
- let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
-
- def open_file(directory, filename)
- File.open("#{directory}/#{filename}.xml")
- end
-
- before do
- WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
- .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
-
- allow(Organisation).to receive(:find_by).and_return(nil)
- allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
- allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
-
- # Created by users
- FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
- FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
-
- # Location setup
- FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
- FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
- FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
-
- # Stub the form handler to use the real form
- allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
- allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2022_2023_form)
- end
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
- context "when importing lettings logs" do
- let(:remote_folder) { "lettings_logs" }
- let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
- let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
- let(:lettings_log_id3) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
- let(:lettings_log_id4) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
- let(:sales_log) { "shared_ownership_sales_log" }
+ let(:storage_service) { instance_double(Storage::S3Service) }
+ let(:logger) { instance_double(ActiveSupport::Logger) }
- before do
- # Stub the S3 file listing and download
- allow(storage_service).to receive(:list_files)
- .and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{lettings_log_id4}.xml #{remote_folder}/#{sales_log}.xml])
- allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
- allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id2}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id2), open_file(fixture_directory, lettings_log_id2))
- allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id3}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id3), open_file(fixture_directory, lettings_log_id3))
- allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id4}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id4), open_file(fixture_directory, lettings_log_id4))
- allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{sales_log}.xml")
- .and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
- end
+ let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
+ let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
+ let(:fixture_directory) { "spec/fixtures/imports/logs" }
- it "successfully create all lettings logs" do
- expect(logger).not_to receive(:error)
- expect(logger).not_to receive(:warn)
- expect(logger).not_to receive(:info)
- expect { lettings_log_service.create_logs(remote_folder) }
- .to change(LettingsLog, :count).by(4)
- end
+ let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
+ let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
+ let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
+ let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
- it "only updates existing lettings logs" do
- expect(logger).not_to receive(:error)
- expect(logger).not_to receive(:warn)
- expect(logger).to receive(:info).with(/Updating lettings log/).exactly(4).times
- expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
- .to change(LettingsLog, :count).by(4)
+ def open_file(directory, filename)
+ File.open("#{directory}/#{filename}.xml")
end
- it "creates organisation relationship once" do
- expect(logger).not_to receive(:error)
- expect(logger).not_to receive(:warn)
- expect { lettings_log_service.create_logs(remote_folder) }
- .to change(OrganisationRelationship, :count).by(1)
+ before do
+ WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
+ .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
+
+ allow(Organisation).to receive(:find_by).and_return(nil)
+ allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
+ allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
+
+ # Created by users
+ FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
+ FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
+
+ # Location setup
+ FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
+ FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
+ FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
+
+ # Stub the form handler to use the real form
+ allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2021_2022_form)
+ allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
+ allow(FormHandler.instance).to receive(:get_form).with("next_lettings").and_return(real_2022_2023_form)
end
- context "when there are status discrepancies" do
- let(:lettings_log_id5) { "893ufj2s-lq77-42m4-rty6-ej09gh585uy1" }
- let(:lettings_log_id6) { "5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd" }
- let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id5) }
- let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
+ context "when importing lettings logs" do
+ let(:remote_folder) { "lettings_logs" }
+ let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
+ let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
+ let(:lettings_log_id3) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+ let(:sales_log) { "shared_ownership_sales_log" }
before do
+ # Stub the S3 file listing and download
+ allow(storage_service).to receive(:list_files)
+ .and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{sales_log}.xml])
allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id5}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id5), open_file(fixture_directory, lettings_log_id5))
+ .with("#{remote_folder}/#{lettings_log_id}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
allow(storage_service).to receive(:get_file_io)
- .with("#{remote_folder}/#{lettings_log_id6}.xml")
- .and_return(open_file(fixture_directory, lettings_log_id6), open_file(fixture_directory, lettings_log_id6))
+ .with("#{remote_folder}/#{lettings_log_id2}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id2), open_file(fixture_directory, lettings_log_id2))
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{lettings_log_id3}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id3), open_file(fixture_directory, lettings_log_id3))
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{sales_log}.xml")
+ .and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
end
- it "the logger logs a warning with the lettings log's old id/filename" do
- expect(logger).to receive(:warn).with(/is not completed/).once
- expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id5} is incomplete but status should be complete/).once
-
- lettings_log_service.send(:create_log, lettings_log_xml)
+ it "successfully create all lettings logs" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect(logger).not_to receive(:info)
+ expect { lettings_log_service.create_logs(remote_folder) }
+ .to change(LettingsLog, :count).by(3)
end
- it "on completion the ids of all logs with status discrepancies are logged in a warning" do
- allow(storage_service).to receive(:list_files)
- .and_return(%W[#{remote_folder}/#{lettings_log_id5}.xml #{remote_folder}/#{lettings_log_id6}.xml])
- expect(logger).to receive(:warn).with(/is not completed/).twice
- expect(logger).to receive(:warn).with(/is incomplete but status should be complete/).twice
- expect(logger).to receive(:warn).with(/The following lettings logs had status discrepancies: \[893ufj2s-lq77-42m4-rty6-ej09gh585uy1, 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd\]/)
-
- lettings_log_service.create_logs(remote_folder)
+ it "only updates existing lettings logs" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect(logger).to receive(:info).with(/Updating lettings log/).exactly(3).times
+ expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
+ .to change(LettingsLog, :count).by(3)
end
- end
- end
- context "when importing a specific log" do
- let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
- let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
- let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
+ it "creates organisation relationship once" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect { lettings_log_service.create_logs(remote_folder) }
+ .to change(OrganisationRelationship, :count).by(1)
+ end
- context "and the void date is after the start date" do
- before { lettings_log_xml.at_xpath("//xmlns:VYEAR").content = 2023 }
+ context "when there are status discrepancies" do
+ let(:lettings_log_id5) { "893ufj2s-lq77-42m4-rty6-ej09gh585uy1" }
+ let(:lettings_log_id6) { "5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd" }
+ let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id5) }
+ let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
- it "does not import the voiddate" do
- expect(logger).to receive(:warn).with(/is not completed/)
- expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id} is incomplete but status should be complete/)
+ before do
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{lettings_log_id5}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id5), open_file(fixture_directory, lettings_log_id5))
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{lettings_log_id6}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id6), open_file(fixture_directory, lettings_log_id6))
+ end
- lettings_log_service.send(:create_log, lettings_log_xml)
+ it "the logger logs a warning with the lettings log's old id/filename" do
+ expect(logger).to receive(:warn).with(/is not completed/).once
+ expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id5} is incomplete but status should be complete/).once
- lettings_log = LettingsLog.where(old_id: lettings_log_id).first
- expect(lettings_log&.voiddate).to be_nil
- end
- end
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ end
- context "and the organisation legacy ID does not exist" do
- before { lettings_log_xml.at_xpath("//xmlns:OWNINGORGID").content = 99_999 }
+ it "on completion the ids of all logs with status discrepancies are logged in a warning" do
+ allow(storage_service).to receive(:list_files)
+ .and_return(%W[#{remote_folder}/#{lettings_log_id5}.xml #{remote_folder}/#{lettings_log_id6}.xml])
+ expect(logger).to receive(:warn).with(/is not completed/).twice
+ expect(logger).to receive(:warn).with(/is incomplete but status should be complete/).twice
+ expect(logger).to receive(:warn).with(/The following lettings logs had status discrepancies: \[893ufj2s-lq77-42m4-rty6-ej09gh585uy1, 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd\]/)
- it "raises an exception" do
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .to raise_error(RuntimeError, "Organisation not found with legacy ID 99999")
+ lettings_log_service.create_logs(remote_folder)
+ end
end
end
- context "and a person is under 16" do
- before { lettings_log_xml.at_xpath("//xmlns:P2Age").content = 14 }
+ context "when importing a specific log" do
+ let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" }
+ let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
+ let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
+
+ context "and the void date is after the start date" do
+ before { lettings_log_xml.at_xpath("//xmlns:VYEAR").content = 2023 }
- context "when the economic status is set to refuse" do
- before { lettings_log_xml.at_xpath("//xmlns:P2Eco").content = "10) Refused" }
+ it "does not import the voiddate" do
+ expect(logger).to receive(:warn).with(/is not completed/)
+ expect(logger).to receive(:warn).with(/lettings log with old id:#{lettings_log_id} is incomplete but status should be complete/)
- it "sets the economic status to child under 16" do
- # The update is done when calculating derived variables
- expect(logger).to receive(:warn).with(/Differences found when saving log/)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.where(old_id: lettings_log_id).first
- expect(lettings_log&.ecstat2).to be(9)
+ expect(lettings_log&.voiddate).to be_nil
end
end
- context "when the relationship to lead tenant is set to refuse" do
- before { lettings_log_xml.at_xpath("//xmlns:P2Rel").content = "Refused" }
-
- it "sets the relationship to lead tenant to child" do
- lettings_log_service.send(:create_log, lettings_log_xml)
+ context "and the organisation legacy ID does not exist" do
+ before { lettings_log_xml.at_xpath("//xmlns:OWNINGORGID").content = 99_999 }
- lettings_log = LettingsLog.where(old_id: lettings_log_id).first
- expect(lettings_log&.relat2).to eq("C")
+ it "raises an exception" do
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .to raise_error(RuntimeError, "Organisation not found with legacy ID 99999")
end
end
- end
- context "and this is an internal transfer that is in-progress with invalid answers" do
- before do
- lettings_log_xml.at_xpath("//meta:status").content = "submitted-invalid"
- lettings_log_xml.at_xpath("//xmlns:P2Age").content = 999
- end
+ context "and a person is under 16" do
+ before { lettings_log_xml.at_xpath("//xmlns:P2Age").content = 14 }
- it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Answer cannot be over 16/)
- expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Person 2’s age must be between/)
- expect(logger).to receive(:warn).with(/Removing field ecstat2 from log triggering validation: Answer cannot be ‘child under 16’/)
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
- end
+ context "when the economic status is set to refuse" do
+ before { lettings_log_xml.at_xpath("//xmlns:P2Eco").content = "10) Refused" }
- it "clears out the invalid answers" do
- allow(logger).to receive(:warn)
+ it "sets the economic status to child under 16" do
+ # The update is done when calculating derived variables
+ expect(logger).to receive(:warn).with(/Differences found when saving log/)
+ lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ lettings_log = LettingsLog.where(old_id: lettings_log_id).first
+ expect(lettings_log&.ecstat2).to be(9)
+ end
+ end
- expect(lettings_log).not_to be_nil
- expect(lettings_log.age2).to be_nil
- expect(lettings_log.ecstat2).to be_nil
- end
- end
+ context "when the relationship to lead tenant is set to refuse" do
+ before { lettings_log_xml.at_xpath("//xmlns:P2Rel").content = "Refused" }
- context "and it has zero earnings" do
- before do
- lettings_log_xml.at_xpath("//meta:status").content = "submitted"
- lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 0
- end
+ it "sets the relationship to lead tenant to child" do
+ lettings_log_service.send(:create_log, lettings_log_xml)
- it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Where the income is 0, set earnings and income to blank and set incref to refused/)
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
+ lettings_log = LettingsLog.where(old_id: lettings_log_id).first
+ expect(lettings_log&.relat2).to eq("C")
+ end
+ end
end
- it "clears out the invalid answers" do
- allow(logger).to receive(:warn)
+ context "and this is an internal transfer that is in-progress with invalid answers" do
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted-invalid"
+ lettings_log_xml.at_xpath("//xmlns:P2Age").content = 999
+ end
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Answer cannot be over 16/)
+ expect(logger).to receive(:warn).with(/Removing field age2 from log triggering validation: Person 2’s age must be between/)
+ expect(logger).to receive(:warn).with(/Removing field ecstat2 from log triggering validation: Answer cannot be ‘child under 16’/)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
- expect(lettings_log).not_to be_nil
- expect(lettings_log.earnings).to be_nil
- expect(lettings_log.incref).to eq(1)
- expect(lettings_log.net_income_known).to eq(2)
- end
- end
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
- context "and an invalid tenancy length for tenancy type" do
- before do
- lettings_log_xml.at_xpath("//meta:status").content = "submitted"
- lettings_log_xml.at_xpath("//xmlns:_2cYears").content = "1"
- lettings_log_xml.at_xpath("//xmlns:Q2b").content = "4"
- end
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing tenancylength as invalid/)
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.age2).to be_nil
+ expect(lettings_log.ecstat2).to be_nil
+ end
end
- it "clears out the invalid answers" do
- allow(logger).to receive(:warn)
+ context "and it has zero earnings" do
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted"
+ lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 0
+ end
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Where the income is 0, set earnings and income to blank and set incref to refused/)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
- expect(lettings_log).not_to be_nil
- expect(lettings_log.tenancylength).to be_nil
- expect(lettings_log.tenancy).to be_nil
- end
- end
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
- context "and an lead tenant must be under 20 if childrens home or foster care" do
- before do
- lettings_log_xml.at_xpath("//meta:status").content = "submitted"
- lettings_log_xml.at_xpath("//xmlns:Q11").content = "13"
- lettings_log_xml.at_xpath("//xmlns:P1Age").content = "22"
- end
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing age1 and prevten as incompatible/)
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.earnings).to be_nil
+ expect(lettings_log.incref).to eq(1)
+ expect(lettings_log.net_income_known).to eq(2)
+ end
end
- it "clears out the invalid answers" do
- allow(logger).to receive(:warn)
+ context "and an invalid tenancy length for tenancy type" do
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted"
+ lettings_log_xml.at_xpath("//xmlns:_2cYears").content = "1"
+ lettings_log_xml.at_xpath("//xmlns:Q2b").content = "4"
+ end
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing tenancylength as invalid/)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
- expect(lettings_log).not_to be_nil
- expect(lettings_log.age1).to be_nil
- expect(lettings_log.prevten).to be_nil
- end
- end
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
- context "and is a carehome but missing carehome charge" do
- let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- before do
- lettings_log_xml.at_xpath("//meta:status").content = "submitted"
- lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id
- scheme2.update!(registered_under_care_act: 2)
- lettings_log_xml.at_xpath("//xmlns:Q18b").content = ""
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.tenancylength).to be_nil
+ expect(lettings_log.tenancy).to be_nil
+ end
end
- it "intercepts the relevant validation error" do
- allow(logger).to receive(:warn)
+ context "and an lead tenant must be under 20 if childrens home or foster care" do
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted"
+ lettings_log_xml.at_xpath("//xmlns:Q11").content = "13"
+ lettings_log_xml.at_xpath("//xmlns:P1Age").content = "22"
+ end
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
- end
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing age1 and prevten as incompatible/)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
- it "clears out the invalid answers" do
- allow(logger).to receive(:warn)
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- expect(lettings_log).not_to be_nil
- expect(lettings_log.is_carehome).to be_truthy
- expect(lettings_log.chcharge).to be_nil
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.age1).to be_nil
+ expect(lettings_log.prevten).to be_nil
+ end
end
- end
- context "and this is an internal transfer from a non social housing" do
- before do
- lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"
- lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
- end
+ context "and is a carehome but missing carehome charge" do
+ let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
- it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is a non social housing/)
- expect { lettings_log_service.send(:create_log, lettings_log_xml) }
- .not_to raise_error
- end
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted"
+ lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id
+ scheme2.update!(registered_under_care_act: 2)
+ lettings_log_xml.at_xpath("//xmlns:Q18b").content = ""
+ end
- it "clears out the referral answer" do
- allow(logger).to receive(:warn)
+ it "intercepts the relevant validation error" do
+ allow(logger).to receive(:warn)
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- expect(lettings_log).not_to be_nil
- expect(lettings_log.referral).to be_nil
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.is_carehome).to be_truthy
+ expect(lettings_log.chcharge).to be_nil
+ end
end
- context "and this is an internal transfer from a previous fixed term tenancy" do
+ context "and this is an internal transfer from a non social housing" do
before do
- lettings_log_xml.at_xpath("//xmlns:Q11").content = "30 Fixed term Local Authority General Needs tenancy"
+ lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"
lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is fixed terms or lifetime/)
+ expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is a non social housing/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
@@ -356,86 +341,202 @@ RSpec.describe Imports::LettingsLogsImportService do
expect(lettings_log).not_to be_nil
expect(lettings_log.referral).to be_nil
end
+
+ context "and this is an internal transfer from a previous fixed term tenancy" do
+ before do
+ lettings_log_xml.at_xpath("//xmlns:Q11").content = "30 Fixed term Local Authority General Needs tenancy"
+ lettings_log_xml.at_xpath("//xmlns:Q16").content = "1 Internal Transfer"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing internal transfer referral since previous tenancy is fixed terms or lifetime/)
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the referral answer" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.referral).to be_nil
+ end
+ end
end
- end
- context "and the net income soft validation is triggered (net_income_value_check)" do
- before do
- lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly"
- lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 890.00
+ context "and the net income soft validation is triggered (net_income_value_check)" do
+ before do
+ lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly"
+ lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 890.00
+ end
+
+ it "completes the log" do
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ expect(lettings_log.status).to eq("completed")
+ end
end
- it "completes the log" do
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- expect(lettings_log.status).to eq("completed")
+ context "and the rent soft validation is triggered (rent_value_check)" do
+ before do
+ lettings_log_xml.at_xpath("//xmlns:Q18ai").content = 200.00
+ lettings_log_xml.at_xpath("//xmlns:Q18av").content = 232.02
+ lettings_log_xml.at_xpath("//xmlns:Q17").content = "1 Weekly for 52 weeks"
+ LaRentRange.create!(
+ start_year: 2021,
+ la: "E08000035",
+ beds: 2,
+ lettype: 1,
+ soft_max: 900,
+ hard_max: 1500,
+ soft_min: 500,
+ hard_min: 100,
+ )
+ end
+
+ it "completes the log" do
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ expect(lettings_log.status).to eq("completed")
+ end
end
- end
- context "and the rent soft validation is triggered (rent_value_check)" do
- before do
- lettings_log_xml.at_xpath("//xmlns:Q18ai").content = 200.00
- lettings_log_xml.at_xpath("//xmlns:Q18av").content = 232.02
- lettings_log_xml.at_xpath("//xmlns:Q17").content = "1 Weekly for 52 weeks"
- LaRentRange.create!(
- start_year: 2021,
- la: "E08000035",
- beds: 2,
- lettype: 1,
- soft_max: 900,
- hard_max: 1500,
- soft_min: 500,
- hard_min: 100,
- )
+ context "and the retirement soft validation is triggered (retirement_value_check)" do
+ before do
+ lettings_log_xml.at_xpath("//xmlns:P1Age").content = 68
+ lettings_log_xml.at_xpath("//xmlns:P1Eco").content = "6) Not Seeking Work"
+ end
+
+ it "completes the log" do
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ expect(lettings_log.status).to eq("completed")
+ end
end
- it "completes the log" do
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- expect(lettings_log.status).to eq("completed")
+ context "and this is a supported housing log with multiple locations under a scheme" do
+ let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+
+ it "sets the scheme and location values" do
+ expect(logger).not_to receive(:warn)
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log.scheme_id).not_to be_nil
+ expect(lettings_log.location_id).not_to be_nil
+ expect(lettings_log.status).to eq("completed")
+ end
end
- end
- context "and the retirement soft validation is triggered (retirement_value_check)" do
- before do
- lettings_log_xml.at_xpath("//xmlns:P1Age").content = 68
- lettings_log_xml.at_xpath("//xmlns:P1Eco").content = "6) Not Seeking Work"
+ context "and this is a supported housing log with a single location under a scheme" do
+ let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+
+ before { lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id }
+
+ it "sets the scheme and location values" do
+ expect(logger).not_to receive(:warn)
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log.scheme_id).not_to be_nil
+ expect(lettings_log.location_id).not_to be_nil
+ expect(lettings_log.status).to eq("completed")
+ end
end
+ end
+ end
- it "completes the log" do
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
- expect(lettings_log.status).to eq("completed")
+ context "with 22/23 logs" do
+ subject(:lettings_log_service) { described_class.new(storage_service, logger) }
+
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
end
+ Timecop.return
+ Singleton.__init__(FormHandler)
end
- context "and this is a supported housing log with multiple locations under a scheme" do
- let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+ let(:storage_service) { instance_double(Storage::S3Service) }
+ let(:logger) { instance_double(ActiveSupport::Logger) }
- it "sets the scheme and location values" do
- expect(logger).not_to receive(:warn)
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") }
+ let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
+ let(:fixture_directory) { "spec/fixtures/imports/logs" }
- expect(lettings_log.scheme_id).not_to be_nil
- expect(lettings_log.location_id).not_to be_nil
- expect(lettings_log.status).to eq("completed")
- end
+ let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
+ let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
+ let(:scheme1) { FactoryBot.create(:scheme, old_visible_id: "0123", owning_organisation: organisation) }
+ let(:scheme2) { FactoryBot.create(:scheme, old_visible_id: "456", owning_organisation: organisation) }
+
+ def open_file(directory, filename)
+ File.open("#{directory}/#{filename}.xml")
end
- context "and this is a supported housing log with a single location under a scheme" do
- let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+ before do
+ WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/)
+ .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {})
+
+ allow(Organisation).to receive(:find_by).and_return(nil)
+ allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
+ allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
+
+ # Created by users
+ FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
+ FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
+
+ # Location setup
+ FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme1.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
+ FactoryBot.create(:location, scheme_id: scheme1.id, startdate: Time.zone.local(2021, 4, 1))
+ FactoryBot.create(:location, old_visible_id: "10", postcode: "LS166FT", scheme_id: scheme2.id, mobility_type: "W", startdate: Time.zone.local(2021, 4, 1))
+
+ # Stub the form handler to use the real form
+ allow(FormHandler.instance).to receive(:get_form).with("current_lettings").and_return(real_2022_2023_form)
+ allow(FormHandler.instance).to receive(:get_form).with("previous_lettings").and_return(real_2021_2022_form)
+ allow(FormHandler.instance).to receive(:get_form).with("next_lettings").and_return(real_2022_2023_form)
+ end
- before { lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id }
+ context "when importing lettings logs" do
+ let(:remote_folder) { "lettings_logs" }
+ let(:lettings_log_id) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
+ let(:sales_log) { "shared_ownership_sales_log" }
- it "sets the scheme and location values" do
+ before do
+ # Stub the S3 file listing and download
+ allow(storage_service).to receive(:list_files)
+ .and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{sales_log}.xml])
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{lettings_log_id}.xml")
+ .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
+ allow(storage_service).to receive(:get_file_io)
+ .with("#{remote_folder}/#{sales_log}.xml")
+ .and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
+ end
+
+ it "successfully create all lettings logs" do
+ expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
- lettings_log_service.send(:create_log, lettings_log_xml)
- lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+ expect(logger).not_to receive(:info)
+ expect { lettings_log_service.create_logs(remote_folder) }
+ .to change(LettingsLog, :count).by(1)
+ end
- expect(lettings_log.scheme_id).not_to be_nil
- expect(lettings_log.location_id).not_to be_nil
- expect(lettings_log.status).to eq("completed")
+ it "only updates existing lettings logs" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect(logger).to receive(:info).with(/Updating lettings log/).once
+ expect { 2.times { lettings_log_service.create_logs(remote_folder) } }
+ .to change(LettingsLog, :count).by(1)
+ end
+
+ it "creates organisation relationship once" do
+ expect(logger).not_to receive(:error)
+ expect(logger).not_to receive(:warn)
+ expect { lettings_log_service.create_logs(remote_folder) }
+ .to change(OrganisationRelationship, :count).by(1)
end
end
end
diff --git a/spec/views/form/page_view_spec.rb b/spec/views/form/page_view_spec.rb
index a7039a9a9..074a7fd6a 100644
--- a/spec/views/form/page_view_spec.rb
+++ b/spec/views/form/page_view_spec.rb
@@ -17,6 +17,15 @@ RSpec.describe "form/page" do
end
end
+ around do |example|
+ Timecop.freeze(Time.zone.local(2022, 1, 1)) do
+ Singleton.__init__(FormHandler)
+ example.run
+ end
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
before do
assign(:log, lettings_log)
assign(:page, page)