Browse Source

CLDC-1917 Add Startdate Validation (#1378)

* feat: add validation with feature flag, typo fix and update tests

* feat: flip feature toggle

* feat: update feature toggle name

* feat: fix form handler inequality

* refactor: linting

* refactor: use between in form handler

* feat: remove feature toggle

* feat: add dynamic date to lettings log factory

* feat: fix log_summary_component_spec.rb tests

* feat: update lettings_log.rb and start fixing lettings_log_spec.rb

* feat: fix more tests

* feat: fix more tests

* feat: fix lettings log import service

* refactor: linting

* feat: fix checkboxes_spec.rb

* feat: fix interruption_screen_helper_spec.rb

* feat: fix check_answers_helper_spec.rb

* feat: fix page_routing_spec.rb

* feat: fix lettings_logs_field_import_service_spec.rb

* feat: fix lettings_log_spec.rb

* feat: fix question_spec.rb

* feat: fix lettings_logs_controller_spec.rb

* feat: fix check_answers_page_lettings_logs_spec.rb

* feat: fix tenancy_validations_spec.rb

* feat: fix validations_spec.rb

* feat: fix accessible_autocomplete_spec.rb

* feat: fix form_navigation_spec.rb

* feat: fix soft_validations_spec.rb

* feat: fix lettings_log_export_service_spec.rb

* feat: fix saving_data_spec.rb

* feat: fix page_spec.rb

* feat: fix form_controller_spec.rb

* refactor: linting

* feat: fix subsection_spec.rb

* feat: fix lettings_log_spec.rb

* feat: fix financial_validations_spec.rb

* feat: fix tasklist_page_spec.rb

* feat: fix conditional_questions_spec.rb

* feat: fix form_page_error_helper_spec.rb and log_summary_component_spec.rb

* feat: fix lettings_log_csv_service_spec.rb

* feat: fix tasklist_helper_spec.rb

* refactor: linting

* refactor: linting

* feat: fix lettings_log_spec.rb

* refactor: linting

* refactor: replace financial year with collection yaer

* feat: respond to PR comments pt. 1

* feat: respond to PR comments pt. 2
revert-1378-CLDC-1917-startdate-validation
natdeanlewissoftwire 2 years ago committed by GitHub
parent
commit
f758d598c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/models/form_handler.rb
  2. 26
      app/models/validations/date_validations.rb
  3. 12
      app/models/validations/sales/setup_validations.rb
  4. 40
      app/models/validations/setup_validations.rb
  5. 4
      config/initializers/feature_toggle.rb
  6. 14
      config/locales/en.yml
  7. 2
      db/schema.rb
  8. 6
      spec/components/log_summary_component_spec.rb
  9. 13
      spec/factories/lettings_log.rb
  10. 13
      spec/features/form/accessible_autocomplete_spec.rb
  11. 11
      spec/features/form/check_answers_page_lettings_logs_spec.rb
  12. 9
      spec/features/form/checkboxes_spec.rb
  13. 10
      spec/features/form/conditional_questions_spec.rb
  14. 9
      spec/features/form/form_navigation_spec.rb
  15. 11
      spec/features/form/page_routing_spec.rb
  16. 9
      spec/features/form/progressive_total_field_spec.rb
  17. 9
      spec/features/form/saving_data_spec.rb
  18. 16
      spec/features/form/tasklist_page_spec.rb
  19. 11
      spec/features/form/validations_spec.rb
  20. 2
      spec/fixtures/exports/general_needs_log.csv
  21. 4
      spec/fixtures/exports/general_needs_log.xml
  22. 4
      spec/fixtures/exports/supported_housing_logs.xml
  23. 9
      spec/helpers/check_answers_helper_spec.rb
  24. 9
      spec/helpers/form_page_error_helper_spec.rb
  25. 9
      spec/helpers/interruption_screen_helper_spec.rb
  26. 86
      spec/helpers/tasklist_helper_spec.rb
  27. 6
      spec/jobs/email_csv_job_spec.rb
  28. 9
      spec/models/form/page_spec.rb
  29. 11
      spec/models/form/question_spec.rb
  30. 9
      spec/models/form/subsection_spec.rb
  31. 9
      spec/models/form_spec.rb
  32. 181
      spec/models/lettings_log_spec.rb
  33. 12
      spec/models/validations/date_validations_spec.rb
  34. 2
      spec/models/validations/financial_validations_spec.rb
  35. 20
      spec/models/validations/sales/setup_validations_spec.rb
  36. 82
      spec/models/validations/setup_validations_spec.rb
  37. 16
      spec/models/validations/soft_validations_spec.rb
  38. 20
      spec/models/validations/tenancy_validations_spec.rb
  39. 16
      spec/requests/form_controller_spec.rb
  40. 44
      spec/requests/lettings_logs_controller_spec.rb
  41. 7
      spec/requests/sales_logs_controller_spec.rb
  42. 2
      spec/services/csv/lettings_log_csv_service_spec.rb
  43. 8
      spec/services/exports/lettings_log_export_service_spec.rb
  44. 11
      spec/services/imports/lettings_logs_field_import_service_spec.rb
  45. 121
      spec/services/imports/lettings_logs_import_service_spec.rb
  46. 9
      spec/views/form/page_view_spec.rb

4
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!

26
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

12
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"),

40
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

4
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

14
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"

2
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"

6
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")

13
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

13
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

11
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

9
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

10
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 }

9
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

11
spec/features/form/page_routing_spec.rb

@ -20,6 +20,16 @@ RSpec.describe "Form Page Routing" do
sign_in user
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
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
@ -111,6 +121,7 @@ RSpec.describe "Form Page Routing" do
expect(find_field("lettings_log[startdate(1i)]").value).to eq(nil)
end
end
end
context "when completing the setup section" do
context "with a supported housing log" do

9
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

9
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

16
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.")

11
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 }

2
spec/fixtures/exports/general_needs_log.csv vendored

@ -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

1 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 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-05-01T00:00:00+01:00 2022-02-08T16:52:15+00:00 2022-05-01T00:00:00+01:00

4
spec/fixtures/exports/general_needs_log.xml vendored

@ -142,8 +142,8 @@
<maningorgid>{managing_org_id}</maningorgid>
<maningorgname>DLUHC</maningorgname>
<manhcnum>1234</manhcnum>
<createddate>2022-02-08T16:52:15+00:00</createddate>
<uploaddate>2022-02-08T16:52:15+00:00</uploaddate>
<createddate>2022-05-01T00:00:00+01:00</createddate>
<uploaddate>2022-05-01T00:00:00+01:00</uploaddate>
<providertype>1</providertype>
</form>
</forms>

4
spec/fixtures/exports/supported_housing_logs.xml vendored

@ -141,8 +141,8 @@
<maningorgid>{managing_org_id}</maningorgid>
<maningorgname>DLUHC</maningorgname>
<manhcnum>1234</manhcnum>
<createddate>2022-02-08T16:52:15+00:00</createddate>
<uploaddate>2022-02-08T16:52:15+00:00</uploaddate>
<createddate>2022-05-01T00:00:00+01:00</createddate>
<uploaddate>2022-05-01T00:00:00+01:00</uploaddate>
<unittype_sh>7</unittype_sh>
<confidential>1</confidential>
<cligrp1>G</cligrp1>

9
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

9
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 }

9
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

86
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

6
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)

9
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 }

11
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

9
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" }

9
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 }

181
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

12
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)

2
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

20
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

82
spec/models/validations/setup_validations_spec.rb

@ -6,6 +6,88 @@ 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

16
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))

20
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") }

16
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)

44
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

7
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))
around do |example|
Timecop.freeze(2022, 12, 1) do
example.run
end
after do
Timecop.unfreeze
end

2
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

8
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)

11
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: {})

121
spec/services/imports/lettings_logs_import_service_spec.rb

@ -1,8 +1,18 @@
require "rails_helper"
RSpec.describe Imports::LettingsLogsImportService do
context "with 21/22 logs" do
subject(:lettings_log_service) { described_class.new(storage_service, logger) }
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(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
@ -37,22 +47,22 @@ RSpec.describe Imports::LettingsLogsImportService do
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("current_lettings").and_return(real_2022_2023_form)
allow(FormHandler.instance).to receive(:get_form).with("next_lettings").and_return(real_2022_2023_form)
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(: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}/#{lettings_log_id4}.xml #{remote_folder}/#{sales_log}.xml])
.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_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
@ -62,9 +72,6 @@ RSpec.describe Imports::LettingsLogsImportService do
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))
@ -75,15 +82,15 @@ RSpec.describe Imports::LettingsLogsImportService do
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)
.to change(LettingsLog, :count).by(3)
end
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(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(4)
.to change(LettingsLog, :count).by(3)
end
it "creates organisation relationship once" do
@ -439,4 +446,98 @@ RSpec.describe Imports::LettingsLogsImportService do
end
end
end
end
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
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("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
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" }
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)
expect(logger).not_to receive(:info)
expect { lettings_log_service.create_logs(remote_folder) }
.to change(LettingsLog, :count).by(1)
end
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
end

9
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)

Loading…
Cancel
Save