Browse Source

Merge branch 'main' into CLDC-3945-update-validation-generation

pull/3011/head
kosiakkatrina 1 month ago committed by GitHub
parent
commit
798ffe2af6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      Gemfile.lock
  2. 6
      app/controllers/form_controller.rb
  3. 10
      app/helpers/bulk_upload/sales_log_to_csv.rb
  4. 19
      app/models/form.rb
  5. 4
      app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb
  6. 4
      app/models/validations/financial_validations.rb
  7. 24
      app/models/validations/sales/financial_validations.rb
  8. 22
      app/models/validations/sales/sale_information_validations.rb
  9. 8
      app/services/bulk_upload/lettings/validator.rb
  10. 9
      app/services/bulk_upload/sales/validator.rb
  11. 4
      app/views/bulk_upload_shared/guidance.html.erb
  12. 6
      config/locales/validations/sales/financial.en.yml
  13. 9
      config/locales/validations/sales/sale_information.en.yml
  14. 6
      docs/Gemfile.lock
  15. 20
      lib/tasks/clear_invalid_benefits.rake
  16. 12
      lib/tasks/clear_invalidated_earnings.rake
  17. 20
      lib/tasks/correct_checkbox_values.rake
  18. 15
      lib/tasks/correct_reasonpref_values.rake
  19. 20
      lib/tasks/correct_rent_type_value.rake
  20. 19
      lib/tasks/recalculate_status_after_sales_over_retirement_age_validation.rake
  21. 24
      lib/tasks/update_created_by_values.rake
  22. 207
      lib/tasks/update_manual_address_entry_selected_prexisting_logs.rake
  23. 1
      spec/features/collection_resources_spec.rb
  24. 19
      spec/features/sales_log_spec.rb
  25. 6
      spec/features/schemes_helpers.rb
  26. 2
      spec/helpers/check_answers_helper_spec.rb
  27. 4
      spec/helpers/guidance_helper_spec.rb
  28. 95
      spec/lib/tasks/clear_invalid_benefits_spec.rb
  29. 111
      spec/lib/tasks/clear_invalidated_earnings_spec.rb
  30. 216
      spec/lib/tasks/correct_checkbox_values_spec.rb
  31. 111
      spec/lib/tasks/correct_reasonpref_values_spec.rb
  32. 254
      spec/lib/tasks/correct_rent_type_value_spec.rb
  33. 4
      spec/lib/tasks/recalculate_invalid_reasonpref_dontknow_spec.rb
  34. 53
      spec/lib/tasks/recalculate_status_after_sales_over_retirement_age_validation_spec.rb
  35. 146
      spec/lib/tasks/update_created_by_values_spec.rb
  36. 211
      spec/lib/tasks/update_manual_address_entry_selected_prexisting_logs_spec.rb
  37. 4
      spec/models/bulk_upload_spec.rb
  38. 6
      spec/models/location_spec.rb
  39. 3
      spec/models/scheme_spec.rb
  40. 52
      spec/models/validations/sales/financial_validations_spec.rb
  41. 157
      spec/models/validations/sales/sale_information_validations_spec.rb
  42. 2
      spec/requests/bulk_upload_sales_logs_controller_spec.rb
  43. 2
      spec/requests/check_errors_controller_spec.rb
  44. 22
      spec/requests/collection_resources_controller_spec.rb
  45. 9
      spec/requests/form_controller_spec.rb
  46. 42
      spec/requests/lettings_logs_controller_spec.rb
  47. 1
      spec/services/bulk_upload/sales/validator_spec.rb
  48. 2
      spec/services/csv/lettings_log_csv_service_spec.rb
  49. 6
      spec/views/form/guidance/_financial_calculations_outright_sale_spec.rb

8
Gemfile.lock

@ -289,13 +289,13 @@ GEM
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.3-arm64-darwin)
nokogiri (1.18.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.3-x86_64-darwin)
nokogiri (1.18.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.3-x86_64-linux-gnu)
nokogiri (1.18.4-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.3-x86_64-linux-musl)
nokogiri (1.18.4-x86_64-linux-musl)
racc (~> 1.4)
notifications-ruby-client (6.0.0)
jwt (>= 1.5, < 3)

6
app/controllers/form_controller.rb

@ -38,7 +38,7 @@ class FormController < ApplicationController
end
error_attributes = @log.errors.map(&:attribute)
Rails.logger.info "User triggered validation(s) on: #{error_attributes.join(', ')}"
@subsection = form.subsection_for_page(@page)
@subsection = @page.subsection
flash[:errors] = @log.errors.each_with_object({}) do |error, result|
if @page.questions.map(&:id).include?(error.attribute.to_s)
result[error.attribute.to_s] = error.message
@ -87,7 +87,7 @@ class FormController < ApplicationController
if @log
page_id = request.path.split("/")[-1].underscore
@page = form.get_page(page_id)
@subsection = form.subsection_for_page(@page)
@subsection = @page.subsection
@pages_with_errors_count = 0
if @page.routed_to?(@log, current_user) || is_referrer_type?("interruption_screen") || adding_answer_from_check_errors_page?
if updated_answer_from_check_errors_page?
@ -274,7 +274,7 @@ private
elsif pages_to_check.any?
return redirect_path_to_question(pages_to_check[0], pages_to_check)
else
return send("#{@log.log_type}_#{form.subsection_for_page(@page).id}_check_answers_path", @log)
return send("#{@log.log_type}_#{@page.subsection.id}_check_answers_path", @log)
end
end
if previous_interruption_screen_page_id.present?

10
app/helpers/bulk_upload/sales_log_to_csv.rb

@ -434,7 +434,7 @@ class BulkUpload::SalesLogToCsv
log.nationality_all_group,
log.ecstat1,
log.buy1livein,
log.relat2,
{ "P" => 1, "X" => 2, "R" => 3 }[log.relat2],
log.age2,
log.sex2,
log.ethnic_group2,
@ -443,19 +443,19 @@ class BulkUpload::SalesLogToCsv
log.buy2livein, # 40
log.hholdcount,
log.relat3,
{ "P" => 1, "X" => 2, "R" => 3 }[log.relat3],
log.age3,
log.sex3,
log.ecstat3,
log.relat4,
{ "P" => 1, "X" => 2, "R" => 3 }[log.relat4],
log.age4,
log.sex4,
log.ecstat4,
log.relat5, # 50
{ "P" => 1, "X" => 2, "R" => 3 }[log.relat5], # 50
log.age5,
log.sex5,
log.ecstat5,
log.relat6,
{ "P" => 1, "X" => 2, "R" => 3 }[log.relat6],
log.age6,
log.sex6,
log.ecstat6,

19
app/models/form.rb

@ -16,6 +16,13 @@ class Form
},
2024 => {
submission_deadline: Time.zone.local(2025, 6, 6),
new_logs_end_date: Time.zone.local(2025, 7, 4),
edit_end_date: Time.zone.local(2025, 8, 1),
},
2025 => {
submission_deadline: Time.zone.local(2026, 6, 5),
new_logs_end_date: Time.zone.local(2026, 7, 3),
edit_end_date: Time.zone.local(2026, 8, 1),
},
:default => {
submission_deadline: ->(start_year) { Time.zone.local(start_year + 1, 6, 1) },
@ -78,14 +85,10 @@ class Form
routed_question || all_questions[0]
end
def subsection_for_page(page)
subsections.find { |s| s.pages.find { |p| p.id == page.id } }
end
def next_page_id(page, log, current_user, ignore_answered: false)
return page.next_unresolved_page_id || :check_answers if log.unresolved
page_ids = subsection_for_page(page).pages.map(&:id)
page_ids = page.subsection.pages.map(&:id)
page_index = page_ids.index(page.id)
page_id = if page.interruption_screen? && log[page.questions[0].id] == 1 && page.routed_to?(log, current_user)
previous_page_id(page, log, current_user)
@ -104,14 +107,14 @@ class Form
def next_page_redirect_path(page, log, current_user, ignore_answered: false)
next_page_id = next_page_id(page, log, current_user, ignore_answered:)
if next_page_id == :check_answers
"#{type}_log_#{subsection_for_page(page).id}_check_answers_path"
"#{type}_log_#{page.subsection.id}_check_answers_path"
else
"#{type}_log_#{next_page_id}_path"
end
end
def previous_page_id(page, log, current_user)
page_ids = subsection_for_page(page).pages.map(&:id)
page_ids = page.subsection.pages.map(&:id)
page_index = page_ids.index(page.id)
return :tasklist if page_index.zero?
@ -126,7 +129,7 @@ class Form
def previous_page_redirect_path(page, log, current_user, referrer)
previous_page_id = previous_page_id(page, log, current_user)
if referrer == "check_answers"
"#{type}_log_#{subsection_for_page(page).id}_check_answers_path"
"#{type}_log_#{page.subsection.id}_check_answers_path"
elsif previous_page_id == :tasklist
"#{type}_log_path"
else

4
app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb

@ -19,9 +19,9 @@ class Form::Sales::Subsections::SharedOwnershipStaircasingTransaction < ::Form::
Form::Sales::Pages::StaircasePrevious.new(nil, nil, self),
Form::Sales::Pages::StaircaseInitialDate.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new("value_shared_ownership_staircase", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_shared_ownership_value_check", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_shared_ownership_value_check_staircasing", nil, self),
Form::Sales::Pages::Equity.new("staircase_equity", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_equity_value_check", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_equity_value_check_staircasing", nil, self),
Form::Sales::Pages::Mortgageused.new("staircase_mortgage_used_shared_ownership", nil, self, ownershipsch: 1),
Form::Sales::Pages::MonthlyRentStaircasingOwned.new(nil, nil, self),
Form::Sales::Pages::MonthlyRentStaircasing.new(nil, nil, self),

4
app/models/validations/financial_validations.rb

@ -159,9 +159,11 @@ module Validations::FinancialValidations
end
def validate_care_home_charges(record)
return unless record.period && record.chcharge
if record.is_carehome?
period = record.form.get_question("period", record).label_from_value(record.period).downcase
if record.chcharge.present? && !weekly_value_in_range(record, "chcharge", 10, 5000)
unless weekly_value_in_range(record, "chcharge", 10, 5000)
max_chcharge = record.weekly_to_value_per_period(5000)
min_chcharge = record.weekly_to_value_per_period(10)

24
app/models/validations/sales/financial_validations.rb

@ -105,16 +105,36 @@ module Validations::Sales::FinancialValidations
end
end
def validate_equity_less_than_staircase_difference(record)
def validate_staircase_difference(record)
return unless record.equity && record.stairbought && record.stairowned
return unless record.saledate && record.form.start_year_2024_or_later?
if record.equity > record.stairowned - record.stairbought
percentage_left = record.stairowned - record.stairbought - record.equity
if percentage_left.negative?
formatted_equity = sprintf("%g", record.equity)
joint_purchase_id = record.joint_purchase? ? "joint_purchase" : "not_joint_purchase"
record.errors.add :equity, I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
elsif record.numstair
# We must use the lowest possible percentage for a staircasing transaction of any saletype, any year since 1980
minimum_percentage_per_staircasing_transaction = 1
previous_staircasing_transactions = record.numstair - 1
if percentage_left < previous_staircasing_transactions * minimum_percentage_per_staircasing_transaction
equity_sum = sprintf("%g", record.stairowned - percentage_left + previous_staircasing_transactions * minimum_percentage_per_staircasing_transaction)
formatted_equity = sprintf("%g", record.equity)
formatted_stairbought = sprintf("%g", record.stairbought)
formatted_stairowned = sprintf("%g", record.stairowned)
record.errors.add :equity, I18n.t("validations.sales.financial.equity.more_than_stairowned_minus_stairbought_minus_prev_staircasing", equity: formatted_equity, bought: formatted_stairbought, numprevstair: previous_staircasing_transactions, equity_sum:, stair_total: formatted_stairowned)
record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.less_than_stairbought_plus_equity_plus_prev_staircasing", equity: formatted_equity, bought: formatted_stairbought, numprevstair: previous_staircasing_transactions, equity_sum:, stair_total: formatted_stairowned)
record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.more_than_stairowned_minus_equity_minus_prev_staircasing", equity: formatted_equity, bought: formatted_stairbought, numprevstair: previous_staircasing_transactions, equity_sum:, stair_total: formatted_stairowned)
record.errors.add :numstair, I18n.t("validations.sales.financial.numstair.too_high_for_stairowned_minus_stairbought_minus_equity", equity: formatted_equity, bought: formatted_stairbought, numprevstair: previous_staircasing_transactions, equity_sum:, stair_total: formatted_stairowned)
end
end
end

22
app/models/validations/sales/sale_information_validations.rb

@ -41,6 +41,28 @@ module Validations::Sales::SaleInformationValidations
if record.initialpurchase < Time.zone.local(1980, 1, 1)
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980")
end
if record.saledate.present? && record.initialpurchase > record.saledate
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")
end
end
def validate_staircasing_last_transaction_date(record)
return unless record.lasttransaction
if record.lasttransaction < Time.zone.local(1980, 1, 1)
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_1980")
end
if record.saledate.present? && record.lasttransaction > record.saledate
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")
end
if record.initialpurchase.present? && record.lasttransaction < record.initialpurchase
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")
end
end
def validate_previous_property_unit_type(record)

8
app/services/bulk_upload/lettings/validator.rb

@ -55,8 +55,10 @@ class BulkUpload::Lettings::Validator
row_parsers.each do |row_parser|
row_parser.log.blank_invalid_non_setup_fields!
end
if any_logs_invalid?
if invalid_row_numbers.any?
Sentry.capture_message("Bulk upload log creation blocked due to invalid logs after blanking non setup fields: #{bulk_upload.id}.")
Rails.logger.error("Lettings bulk upload #{bulk_upload.id} blocked due to invalid logs after blanking on rows #{invalid_row_numbers}")
"logs_invalid"
end
end
@ -101,8 +103,8 @@ private
end
end
def any_logs_invalid?
row_parsers.any? { |row_parser| row_parser.log.invalid? }
def invalid_row_numbers
row_parsers.each_with_index.map { |row_parser, index| index + row_offset + 1 if row_parser.log.invalid? }.compact
end
def csv_parser

9
app/services/bulk_upload/sales/validator.rb

@ -56,8 +56,9 @@ class BulkUpload::Sales::Validator
row_parser.log.blank_invalid_non_setup_fields!
end
if any_logs_invalid?
Sentry.capture_message("Bulk upload log creation blocked due to invalid logs after blanking non setup fields: #{bulk_upload.id}.")
if invalid_row_numbers.any?
Sentry.capture_message("Bulk upload #{bulk_upload.id} had log creation blocked due to invalid logs after blanking non setup fields. First invalid row number: #{invalid_row_numbers.first}.")
Rails.logger.error("Sales bulk upload #{bulk_upload.id} blocked due to invalid logs after blanking on rows #{invalid_row_numbers}")
"logs_invalid"
end
end
@ -98,8 +99,8 @@ private
end
end
def any_logs_invalid?
row_parsers.any? { |row_parser| row_parser.log.invalid? }
def invalid_row_numbers
row_parsers.each_with_index.map { |row_parser, index| index + row_offset + 1 if row_parser.log.invalid? }.compact
end
def csv_parser

4
app/views/bulk_upload_shared/guidance.html.erb

@ -34,8 +34,8 @@
<p class="govuk-body">You can paste your data below the headers or copy the headers and insert them above the data in your file. The bulk upload fields start at column B. Leave column A blank.</p>
<p class="govuk-body">Make sure that each column of data aligns with the corresponding question in the headers. We recommend ordering your data to match the headers, but you can also reorder the headers to match your data. When processing the file, we check what each column of data represents based on the headers above.</p>
<p class="govuk-body"><%= govuk_link_to "Download the lettings bulk upload template (2024 to 2025)", @form.lettings_template_path %></p>
<p class="govuk-body"><%= govuk_link_to "Download the sales bulk upload template (2024 to 2025)", @form.sales_template_path %></p>
<p class="govuk-body"><%= govuk_link_to "Download the lettings bulk upload template (#{@form.year} to #{@form.year + 1})", @form.lettings_template_path %></p>
<p class="govuk-body"><%= govuk_link_to "Download the sales bulk upload template (#{@form.year} to #{@form.year + 1})", @form.sales_template_path %></p>
<% end %>
<%= accordion.with_section(heading_text: "Using the bulk upload specification") do %>

6
config/locales/validations/sales/financial.en.yml

@ -63,6 +63,7 @@ en:
equity_over_stairowned_minus_stairbought:
joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought."
not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought."
more_than_stairowned_minus_stairbought_minus_prev_staircasing: "The initial equity stake is %{equity}%, the percentage bought is %{bought}%, and there have been %{numprevstair} previous staircasing transactions, totalling at least %{equity_sum}%, which is more than the total percentage owned by the buyers (%{stair_total}%). In a staircasing transaction, the total percentage owned must be at least the initial equity stake plus the percentage bought plus a minimum of 1% for each previous staircasing transaction."
stairowned:
equity_over_stairowned_minus_stairbought:
@ -72,6 +73,7 @@ en:
joint_purchase: "Total percentage buyers now own must be more than percentage bought in this transaction."
not_joint_purchase: "Total percentage buyer now owns must be more than percentage bought in this transaction."
percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same."
less_than_stairbought_plus_equity_plus_prev_staircasing: "The initial equity stake is %{equity}%, the percentage bought is %{bought}%, and there have been %{numprevstair} previous staircasing transactions, totalling at least %{equity_sum}%, which is more than the total percentage owned by the buyers (%{stair_total}%). In a staircasing transaction, the total percentage owned must be at least the initial equity stake plus the percentage bought plus a minimum of 1% for each previous staircasing transaction."
stairbought:
equity_over_stairowned_minus_stairbought:
@ -79,6 +81,10 @@ en:
not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought."
percentage_bought_must_be_at_least_threshold: "The minimum percentage share that can be bought in a staircasing transaction for %{shared_ownership_type} is %{threshold}%. Please change your answer or check that you have selected the correct shared ownership type."
percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same."
more_than_stairowned_minus_equity_minus_prev_staircasing: "The initial equity stake is %{equity}%, the percentage bought is %{bought}%, and there have been %{numprevstair} previous staircasing transactions, totalling at least %{equity_sum}%, which is more than the total percentage owned by the buyers (%{stair_total}%). In a staircasing transaction, the total percentage owned must be at least the initial equity stake plus the percentage bought plus a minimum of 1% for each previous staircasing transaction."
numstair:
too_high_for_stairowned_minus_stairbought_minus_equity: "The initial equity stake is %{equity}%, the percentage bought is %{bought}%, and there have been %{numprevstair} previous staircasing transactions, totalling at least %{equity_sum}%, which is more than the total percentage owned by the buyers (%{stair_total}%). In a staircasing transaction, the total percentage owned must be at least the initial equity stake plus the percentage bought plus a minimum of 1% for each previous staircasing transaction."
uprn_selection:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."

9
config/locales/validations/sales/sale_information.en.yml

@ -16,11 +16,20 @@ en:
must_be_after_exdate: "Sale completion date must be after contract exchange date."
must_be_less_than_1_year_from_exdate: "Sale completion date must be less than 1 year after contract exchange date."
mortgage_used_year: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for the selected year."
must_be_after_initial_purchase_date: "Sale completion date for a staircasing transaction must be after the date of the initial purchase of a share."
must_be_after_last_transaction_date: "Sale completion date must be after the date of the last staircasing transaction."
exdate:
must_be_before_saledate: "Contract exchange date must be before sale completion date."
must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before sale completion date."
initialpurchase:
must_be_after_1980: "The initial purchase date must be after January 1, 1980."
must_be_before_last_transaction: "The initial purchase date must be before the last staircasing transaction date."
must_be_before_saledate: "The initial purchase date must be before the date of this sale."
lasttransaction:
must_be_after_1980: "The last staircasing transaction date must be after January 1, 1980."
must_be_after_initial_purchase: "The last staircasing transaction date must be after the initial purchase date."
must_be_before_saledate: "The last staircasing transaction date must be before the date of this sale."
fromprop:
previous_property_type_bedsit: "A bedsit cannot have more than 1 bedroom."
frombeds:

6
docs/Gemfile.lock

@ -210,11 +210,11 @@ GEM
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.19.0)
nokogiri (1.18.3-arm64-darwin)
nokogiri (1.18.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.3-x86_64-darwin)
nokogiri (1.18.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.3-x86_64-linux-gnu)
nokogiri (1.18.4-x86_64-linux-gnu)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)

20
lib/tasks/clear_invalid_benefits.rake

@ -1,20 +0,0 @@
desc "clear benefit value for logs that would trigger the validation"
task clear_invalid_benefits: :environment do
validation_trigger_condition = "ecstat1 = 1 OR ecstat1 = 2 OR (ecstat2 = 1 AND relat2 = 'P') OR (ecstat2 = 2 AND relat2 = 'P') OR (ecstat3 = 1 AND relat3 = 'P') OR (ecstat3 = 2 AND relat3 = 'P') OR (ecstat4 = 1 AND relat4 = 'P') OR (ecstat4 = 2 AND relat4 = 'P') OR (ecstat5 = 1 AND relat5 = 'P') OR (ecstat5 = 2 AND relat5 = 'P') OR (ecstat6 = 1 AND relat6 = 'P') OR (ecstat6 = 2 AND relat6 = 'P') OR (ecstat7 = 1 AND relat7 = 'P') OR (ecstat7 = 2 AND relat7 = 'P') OR (ecstat8 = 1 AND relat8 = 'P') OR (ecstat8 = 2 AND relat8 = 'P')"
LettingsLog.filter_by_year(2024).where(status: "pending", status_cache: "completed", benefits: 1).where(validation_trigger_condition).find_each do |log|
log.benefits = nil
log.status_cache = log.calculate_status
log.skip_update_status = true
unless log.save
Rails.logger.info "Could not save changes to pending lettings log #{log.id}"
end
end
LettingsLog.filter_by_year(2024).visible.where(benefits: 1).where(validation_trigger_condition).find_each do |log|
log.benefits = nil
unless log.save
Rails.logger.info "Could not save changes to lettings log #{log.id}"
end
end
end

12
lib/tasks/clear_invalidated_earnings.rake

@ -1,12 +0,0 @@
desc "Clear earnings for lettings logs that fail validation"
task clear_invalidated_earnings: :environment do
LettingsLog.filter_by_year(2023).find_each do |lettings_log|
lettings_log.validate_net_income(lettings_log)
if lettings_log.errors[:earnings].present?
Rails.logger.info "Clearing earnings for lettings log #{lettings_log.id}, owning_organisation_id: #{lettings_log.owning_organisation_id}, managing_organisation_id: #{lettings_log.managing_organisation_id}, startdate: #{lettings_log.startdate.to_date}, tenancy reference: #{lettings_log.tenancycode}, property reference: #{lettings_log.propcode}, assigned_to: #{lettings_log.assigned_to.email}(#{lettings_log.assigned_to_id}), earnings: #{lettings_log.earnings}, incfreq: #{lettings_log.incfreq}"
lettings_log.earnings = nil
lettings_log.incfreq = nil
lettings_log.save!(validate: false)
end
end
end

20
lib/tasks/correct_checkbox_values.rake

@ -1,20 +0,0 @@
desc "Update BU reasonable preference and illness type checkbox values"
task correct_checkbox_values: :environment do
any_reasonpref_selected = "rp_homeless = 1 OR rp_hardship = 1 OR rp_medwel = 1 OR rp_insan_unsat = 1 OR rp_dontknow = 1"
any_reasonpref_is_null = "rp_homeless IS NULL OR rp_hardship IS NULL OR rp_medwel IS NULL OR rp_insan_unsat IS NULL OR rp_dontknow IS NULL"
LettingsLog.filter_by_year(2024).where(reasonpref: 1).where(any_reasonpref_selected).where(any_reasonpref_is_null).find_each do |lettings_log|
unless lettings_log.save
Rails.logger.info("Failed to save reasonpref for LettingsLog with id #{lettings_log.id}: #{lettings_log.errors.full_messages}")
end
end
any_illness_selected = "illness_type_1 = 1 OR illness_type_2 = 1 OR illness_type_3 = 1 OR illness_type_4 = 1 OR illness_type_5 = 1 OR illness_type_6 = 1 OR illness_type_7 = 1 OR illness_type_8 = 1 OR illness_type_9 = 1 OR illness_type_10 = 1"
any_illness_is_null = "illness_type_1 IS NULL OR illness_type_2 IS NULL OR illness_type_3 IS NULL OR illness_type_4 IS NULL OR illness_type_5 IS NULL OR illness_type_6 IS NULL OR illness_type_7 IS NULL OR illness_type_8 IS NULL OR illness_type_9 IS NULL OR illness_type_10 IS NULL"
LettingsLog.filter_by_year(2024).where(illness: 1).where(any_illness_selected).where(any_illness_is_null).find_each do |lettings_log|
unless lettings_log.save
Rails.logger.info("Failed to save illness for LettingsLog with id #{lettings_log.id}: #{lettings_log.errors.full_messages}")
end
end
end

15
lib/tasks/correct_reasonpref_values.rake

@ -1,15 +0,0 @@
desc "Correct invalid BU reasonable preference values"
task correct_reasonpref_values: :environment do
%w[rp_homeless rp_hardship rp_medwel rp_insan_unsat rp_dontknow].each do |field|
field_invalid = "#{field} != 1 AND #{field} != 0 AND #{field} is NOT NULL"
LettingsLog.filter_by_year(2024).where(field_invalid).find_each do |lettings_log|
lettings_log[field] = 0
unless lettings_log.save
Rails.logger.info("Failed to save reasonpref for LettingsLog with id #{lettings_log.id}: #{lettings_log.errors.full_messages}")
end
end
LettingsLog.filter_by_year(2023).where(field_invalid).update_all("#{field}": 0)
end
end

20
lib/tasks/correct_rent_type_value.rake

@ -1,20 +0,0 @@
desc "Alter rent_type values for bulk uploaded lettings logs for 2024 where they were not mapped correctly"
task correct_rent_type_value: :environment do
affected_uploads = BulkUpload.where(log_type: "lettings", year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied])
affected_uploads.each do |upload|
upload.logs.where.not(rent_type: nil).each do |log|
current_rent_type = log.rent_type
rent_type_at_upload = log.versions.length == 1 ? log.rent_type : log.versions.first.next.reify.rent_type
next unless rent_type_at_upload == current_rent_type
new_rent_type_value = BulkUpload::Lettings::Year2024::RowParser::RENT_TYPE_BU_MAPPING[rent_type_at_upload]
log.rent_type = new_rent_type_value
if log.save
Rails.logger.info("Log #{log.id} rent_type updated from #{rent_type_at_upload} to #{log.rent_type}")
else
Rails.logger.error("Log #{log.id} rent_type could not be updated from #{rent_type_at_upload} to #{log.rent_type}. Error: #{log.errors.full_messages.join(', ')}")
end
end
upload.update!(rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:applied])
end
end

19
lib/tasks/recalculate_status_after_sales_over_retirement_age_validation.rake

@ -1,19 +0,0 @@
desc "Recalculates status for 2024 logs that will trigger new sales over retirement age soft validation"
task recalculate_status_over_retirement: :environment do
validation_trigger_condition = "(ecstat1 != 5 AND age1 > 66) OR (ecstat2 != 5 AND age2 > 66) OR (ecstat3 != 5 AND age3 > 66) OR (ecstat4 != 5 AND age4 > 66) OR (ecstat5 != 5 AND age5 > 66) OR (ecstat6 != 5 AND age6 > 66)"
SalesLog.filter_by_year(2024).where(status: "pending", status_cache: "completed").where(validation_trigger_condition).find_each do |log|
log.status_cache = log.calculate_status
unless log.save
Rails.logger.info "Could not save changes to pending sales log #{log.id}"
end
end
SalesLog.filter_by_year(2024).where(status: "completed").where(validation_trigger_condition).find_each do |log|
log.status = log.calculate_status
unless log.save
Rails.logger.info "Could not save changes to sales log #{log.id}"
end
end
end

24
lib/tasks/update_created_by_values.rake

@ -1,24 +0,0 @@
desc "Updates created_by values for lettings and sales logs"
task update_created_by_values: :environment do
LettingsLog.filter_by_years(%w[2023 2024]).where.not(bulk_upload_id: nil).update_all("created_by_id = (SELECT user_id FROM bulk_uploads WHERE bulk_uploads.id = lettings_logs.bulk_upload_id)")
LettingsLog.filter_by_years(%w[2023 2024]).where(bulk_upload_id: nil, created_by: nil).find_each do |lettings_log|
user = PaperTrail::Version.find_by(item_id: lettings_log.id, item_type: "LettingsLog", event: "create")&.actor
lettings_log.created_by = if user.present? && user.is_a?(User)
user
else
lettings_log.assigned_to
end
lettings_log.save!(touch: false, validate: false)
end
SalesLog.filter_by_years(%w[2023 2024]).where.not(bulk_upload_id: nil).update_all("created_by_id = (SELECT user_id FROM bulk_uploads WHERE bulk_uploads.id = sales_logs.bulk_upload_id)")
SalesLog.filter_by_years(%w[2023 2024]).where(bulk_upload_id: nil, created_by: nil).find_each do |sales_log|
user = PaperTrail::Version.find_by(item_id: sales_log.id, item_type: "SalesLog", event: "create")&.actor
sales_log.created_by = if user.present? && user.is_a?(User)
user
else
sales_log.assigned_to
end
sales_log.save!(touch: false, validate: false)
end
end

207
lib/tasks/update_manual_address_entry_selected_prexisting_logs.rake

@ -1,207 +0,0 @@
namespace :bulk_update do
desc "Update logs with specific criteria and set manual_address_entry_selected to true"
task update_manual_address_entry_selected: :environment do
updated_lettings_logs_count = 0
lettings_postcode_fixed_count = 0
lettings_postcode_fixed_status_changed_count = 0
lettings_postcode_not_fixed_status_changed_count = 0
lettings_postcode_fixed_status_changed_ids = []
lettings_postcode_not_fixed_status_changed_ids = []
lettings_updated_without_issue = 0
updated_sales_logs_count = 0
sales_postcode_fixed_count = 0
sales_postcode_fixed_status_changed_count = 0
sales_postcode_not_fixed_status_changed_count = 0
sales_postcode_fixed_status_changed_ids = []
sales_postcode_not_fixed_status_changed_ids = []
sales_updated_without_issue = 0
lettings_logs = LettingsLog.filter_by_year(2024)
.where(status: %w[in_progress completed])
.where(needstype: 1, manual_address_entry_selected: false, uprn: nil)
.where("(address_line1 IS NOT NULL AND address_line1 != '') OR (address_line2 IS NOT NULL AND address_line2 != '') OR (town_or_city IS NOT NULL AND town_or_city != '') OR (county IS NOT NULL AND county != '') OR (postcode_full IS NOT NULL AND postcode_full != '')")
lettings_logs.find_each do |log|
status_pre_change = log.status
log.manual_address_entry_selected = true
if log.save
updated_lettings_logs_count += 1
Rails.logger.info "manual_address_entry_selected updated for lettings log #{log.id}"
else
Rails.logger.info "Could not save manual_address_entry_selected changes to lettings log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
postcode_fixed = false
if log.postcode_full.nil? && log.address_line1 == log.address_line1_input
log.postcode_full = log.postcode_full_input
if log.save
lettings_postcode_fixed_count += 1
Rails.logger.info "postcode_full updated by address_line1_input for lettings log #{log.id}"
postcode_fixed = true
else
Rails.logger.info "Could not save postcode_full changes to lettings log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
end
if log.postcode_full.nil? && log.creation_method == "bulk upload" && log.address_line1 == log.address_line1_as_entered
log.postcode_full = log.postcode_full_as_entered
if log.save
lettings_postcode_fixed_count += 1
Rails.logger.info "postcode_full updated by address_line1_as_entered for lettings log #{log.id}"
postcode_fixed = true
else
Rails.logger.info "Could not save postcode_full changes to lettings log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
end
status_post_change = log.status
if status_pre_change != status_post_change
if postcode_fixed
lettings_postcode_fixed_status_changed_count += 1
lettings_postcode_fixed_status_changed_ids << log.id
else
lettings_postcode_not_fixed_status_changed_count += 1
lettings_postcode_not_fixed_status_changed_ids << log.id
end
else
lettings_updated_without_issue += 1
end
end
sales_logs = SalesLog.filter_by_year(2024)
.where(status: %w[in_progress completed])
.where(manual_address_entry_selected: false, uprn: nil)
.where("(address_line1 IS NOT NULL AND address_line1 != '') OR (address_line2 IS NOT NULL AND address_line2 != '') OR (town_or_city IS NOT NULL AND town_or_city != '') OR (county IS NOT NULL AND county != '') OR (postcode_full IS NOT NULL AND postcode_full != '')")
sales_logs.find_each do |log|
status_pre_change = log.status
log.manual_address_entry_selected = true
if log.save
updated_sales_logs_count += 1
Rails.logger.info "manual_address_entry_selected updated for sales log #{log.id}"
else
Rails.logger.info "Could not save manual_address_entry_selected changes to sales log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
postcode_fixed = false
if log.postcode_full.nil? && log.address_line1 == log.address_line1_input
log.postcode_full = log.postcode_full_input
if log.save
sales_postcode_fixed_count += 1
Rails.logger.info "postcode_full updated by address_line1_input for sales log #{log.id}"
postcode_fixed = true
else
Rails.logger.info "Could not save postcode_full changes to sales log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
end
if log.postcode_full.nil? && log.creation_method == "bulk upload" && log.address_line1 == log.address_line1_as_entered
log.postcode_full = log.postcode_full_as_entered
if log.save
sales_postcode_fixed_count += 1
Rails.logger.info "postcode_full updated by address_line1_as_entered for sales log #{log.id}"
postcode_fixed = true
else
Rails.logger.info "Could not save postcode_full changes to sales log #{log.id} : #{log.errors.full_messages.join(', ')}"
end
end
status_post_change = log.status
if status_pre_change != status_post_change
if postcode_fixed
sales_postcode_fixed_status_changed_count += 1
sales_postcode_fixed_status_changed_ids << log.id
else
sales_postcode_not_fixed_status_changed_count += 1
sales_postcode_not_fixed_status_changed_ids << log.id
end
else
sales_updated_without_issue += 1
end
end
puts "#{updated_lettings_logs_count} lettings logs were updated."
puts "#{lettings_updated_without_issue} lettings logs were updated without issue."
puts "#{lettings_postcode_fixed_count} lettings logs where postcode fix was applied."
puts "#{lettings_postcode_fixed_status_changed_count} lettings logs with postcode fix and status changed."
puts "#{lettings_postcode_not_fixed_status_changed_count} lettings logs without postcode fix and status changed."
puts "IDs of lettings logs with postcode fix and status changed: [#{lettings_postcode_fixed_status_changed_ids.join(', ')}]"
puts "IDs of lettings logs without postcode fix and status changed: [#{lettings_postcode_not_fixed_status_changed_ids.join(', ')}]"
lettings_postcode_fixed_org_counts = LettingsLog.where(id: lettings_postcode_fixed_status_changed_ids).group(:owning_organisation_id).count
lettings_postcode_fixed_org_counts.each do |org_id, count|
puts "Org #{org_id}: #{count} logs with postcode fix and status changed."
end
lettings_postcode_not_fixed_org_counts = LettingsLog.where(id: lettings_postcode_not_fixed_status_changed_ids).group(:owning_organisation_id).count
lettings_postcode_not_fixed_org_counts.each do |org_id, count|
puts "Org #{org_id}: #{count} logs without postcode fix and status changed."
end
puts "#{updated_sales_logs_count} sales logs were updated."
puts "#{sales_updated_without_issue} sales logs were updated without issue."
puts "#{sales_postcode_fixed_count} sales logs where postcode fix was applied."
puts "#{sales_postcode_fixed_status_changed_count} sales logs with postcode fix and status changed."
puts "#{sales_postcode_not_fixed_status_changed_count} sales logs without postcode fix and status changed."
puts "IDs of sales logs with postcode fix and status changed: [#{sales_postcode_fixed_status_changed_ids.join(', ')}]"
puts "IDs of sales logs without postcode fix and status changed: [#{sales_postcode_not_fixed_status_changed_ids.join(', ')}]"
sales_postcode_fixed_org_counts = SalesLog.where(id: sales_postcode_fixed_status_changed_ids).group(:owning_organisation_id).count
sales_postcode_fixed_org_counts.each do |org_id, count|
puts "Org #{org_id}: #{count} logs with postcode fix and status changed."
end
sales_postcode_not_fixed_org_counts = SalesLog.where(id: sales_postcode_not_fixed_status_changed_ids).group(:owning_organisation_id).count
sales_postcode_not_fixed_org_counts.each do |org_id, count|
puts "Org #{org_id}: #{count} logs without postcode fix and status changed."
end
end
desc "Find logs to fix and update postcode_full if conditions are met"
task update_postcode_full_preexisting_manual_entry_logs: :environment do
updated_count = 0
fixed_count = 0
not_updated_count = 0
not_updated_ids = []
updated_but_not_fixed_ids = []
logs_to_fix = LettingsLog.filter_by_year(2024).where(manual_address_entry_selected: true, uprn: nil, status: "in_progress", postcode_full: nil, updated_at: Time.zone.parse("2025-03-19 16:00:00")..Time.zone.parse("2025-03-19 17:00:00"))
logs_to_fix.find_each do |log|
previous_version = log.versions[-2]
previous_status = previous_version&.reify&.status
if log.address_line1 == log.address_line1_input
log.postcode_full = log.postcode_full_input
elsif log.creation_method == "bulk upload" && log.address_line1 == log.address_line1_as_entered
log.postcode_full = log.postcode_full_as_entered
end
if log.postcode_full.present?
if log.save
Rails.logger.info "Updated postcode_full for lettings log #{log.id}"
updated_count += 1
if log.status == previous_status
fixed_count += 1
else
updated_but_not_fixed_ids << log.id
end
else
Rails.logger.info "Could not save changes to lettings log #{log.id}: #{log.errors.full_messages.join(', ')}"
not_updated_count += 1
not_updated_ids << log.id
end
else
not_updated_count += 1
not_updated_ids << log.id
end
end
puts "#{updated_count} logs updated."
puts "#{fixed_count} logs fixed."
puts "#{not_updated_count} logs not updated."
puts "IDs of logs not updated: [#{not_updated_ids.join(', ')}]"
puts "IDs of logs updated but not fixed: [#{updated_but_not_fixed_ids.join(', ')}]"
end
end

1
spec/features/collection_resources_spec.rb

@ -7,6 +7,7 @@ RSpec.describe "Collection resources" do
before do
# rubocop:disable RSpec/AnyInstance
allow_any_instance_of(CollectionResourcesHelper).to receive(:editable_collection_resource_years).and_return([2024, 2025])
allow_any_instance_of(CollectionResourcesHelper).to receive(:displayed_collection_resource_years).and_return([2024])
# rubocop:enable RSpec/AnyInstance
allow(CollectionResourcesService).to receive(:new).and_return(collection_resources_service)
allow(collection_resources_service).to receive(:upload_collection_resource)

19
spec/features/sales_log_spec.rb

@ -228,9 +228,21 @@ RSpec.describe "Sales Log Features" do
expect(page).to have_current_path("/sales-logs/csv-download?codes_only=false&search=1")
end
end
end
end
context "when I am signed in" do
let(:user) { create(:user, last_sign_in_at: Time.zone.now) }
before do
create(:sales_log, :in_progress, owning_organisation: user.organisation, assigned_to: user)
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
sign_in user
visit("/sales-logs?search=1")
end
context "when displaying the question number in the page header" do
let(:sales_log) { FactoryBot.create(:sales_log, :shared_ownership_setup_complete, jointpur: 2, owning_organisation: user.organisation, assigned_to: user) }
context "when viewing pages within a log" do
let(:sales_log) { FactoryBot.create(:sales_log, :shared_ownership_setup_complete, jointpur: 2, owning_organisation: user.organisation, assigned_to: user, saledate: Time.zone.local(2024, 12, 3)) }
context "when visiting the address page" do
before do
@ -247,13 +259,12 @@ RSpec.describe "Sales Log Features" do
visit("/sales-logs/#{sales_log.id}/about-staircasing-not-joint-purchase")
end
it "displays the question number in the page header" do
it "has the expected content" do
expect(page).to have_content(/Shared ownership scheme\s*About the staircasing transaction/)
end
end
end
end
end
context "when signed in as a support user" do
let(:devise_notify_mailer) { DeviseNotifyMailer.new }

6
spec/features/schemes_helpers.rb

@ -1,4 +1,6 @@
module SchemesHelpers
include CollectionTimeHelper
def fill_in_number_question(lettings_log_id, question, value, path)
visit("/lettings-logs/#{lettings_log_id}/#{path}")
fill_in("lettings-log-#{question.to_s.dasherize}-field", with: value)
@ -74,7 +76,7 @@ module SchemesHelpers
click_button "Save and continue"
choose "location-mobility-type-none-field"
click_button "Save and continue"
fill_in "location_startdate", with: "2/5/2023"
fill_in "location_startdate", with: "2/3/#{current_collection_start_year}"
click_button "Save and continue"
end
@ -93,7 +95,7 @@ module SchemesHelpers
click_button "Save and continue"
choose "location-mobility-type-none-field"
click_button "Save and continue"
fill_in "location_startdate", with: "2/5/2023"
fill_in "location_startdate", with: "2/3/#{current_collection_start_year}"
click_button "Save and continue"
end

2
spec/helpers/check_answers_helper_spec.rb

@ -41,7 +41,7 @@ RSpec.describe CheckAnswersHelper do
describe "#get_answer_label" do
context "when unanswered and bulk upload" do
let(:question) { log.form.questions.sample }
let(:question) { log.form.questions.reject { |q| log.optional_fields.include?(q.id) }.sample }
let(:bulk_upload) { create(:bulk_upload) }
let(:log) { create(:sales_log, creation_method: "bulk upload", bulk_upload:) }

4
spec/helpers/guidance_helper_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe GuidanceHelper do
describe "#question_link" do
context "when question page is routed to" do
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 2) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 2, saledate: Time.zone.local(2024, 5, 3)) }
it "returns an empty string if question is not routed to" do
expect(question_link("mortgage", log, log.assigned_to)).to eq("")
@ -11,7 +11,7 @@ RSpec.describe GuidanceHelper do
end
context "when question page is not routed to" do
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 1) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 1, saledate: Time.zone.local(2024, 5, 3)) }
it "returns a link to the question with correct question number in brakets" do
expect(question_link("mortgage", log, log.assigned_to)).to eq("(<a class=\"govuk-link\" href=\"/sales-logs/#{log.id}/mortgage-amount-shared-ownership\">Q92</a>)")

95
spec/lib/tasks/clear_invalid_benefits_spec.rb

@ -1,95 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "clear_invalid_benefits" do
describe ":clear_invalid_benefits", type: :task do
subject(:task) { Rake::Task["clear_invalid_benefits"] }
before do
Rake.application.rake_require("tasks/clear_invalid_benefits")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and there is a completed lettings log that trips the validation" do
let(:log) { build(:lettings_log, :completed, ecstat1: 1, benefits: 1, assigned_to: create(:user), period: nil) }
before do
log.status = "completed"
log.skip_update_status = true
log.save!(validate: false)
end
it "clear benefits and sets the log to in progress" do
expect(log.reload.benefits).to eq(1)
task.invoke
log.reload
expect(log.benefits).to eq(nil)
expect(log.status).to eq("in_progress")
end
end
context "and there is a lettings log that trips the validation for person 2" do
let(:log) { build(:lettings_log, :completed, ecstat2: 2, benefits: 1, relat2: "P", assigned_to: create(:user), period: nil) }
before do
log.status = "completed"
log.skip_update_status = true
log.save!(validate: false)
end
it "clear benefits and sets the log to in progress" do
expect(log.reload.benefits).to eq(1)
task.invoke
log.reload
expect(log.benefits).to eq(nil)
expect(log.status).to eq("in_progress")
end
end
context "and there is a lettings log that trips the validation for person 8" do
let(:log) { build(:lettings_log, :completed, ecstat8: 1, benefits: 1, relat8: "P", assigned_to: create(:user), period: nil) }
before do
log.status = "completed"
log.skip_update_status = true
log.save!(validate: false)
end
it "clear benefits and sets the log to in progress" do
expect(log.reload.benefits).to eq(1)
task.invoke
log.reload
expect(log.benefits).to eq(nil)
expect(log.status).to eq("in_progress")
end
end
context "and there is a pending lettings log that trips the validation" do
let(:log) { build(:lettings_log, :completed, ecstat1: 1, benefits: 1, assigned_to: create(:user), period: nil) }
before do
log.status = "pending"
log.status_cache = "completed"
log.skip_update_status = true
log.save!(validate: false)
end
it "clears benefits and updates the status cache" do
expect(log.reload.benefits).to eq(1)
task.invoke
log.reload
expect(log.benefits).to eq(nil)
expect(log.status_cache).to eq("in_progress")
end
it "does not change the log status" do
task.invoke
log.reload
expect(log.status).to eq("pending")
end
end
end
end
end

111
spec/lib/tasks/clear_invalidated_earnings_spec.rb

@ -1,111 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "clear_invalidated_earnings" do
describe ":clear_invalidated_earnings", type: :task do
subject(:task) { Rake::Task["clear_invalidated_earnings"] }
before do
Rake.application.rake_require("tasks/clear_invalidated_earnings")
Rake::Task.define_task(:environment)
task.reenable
FormHandler.instance.use_real_forms!
end
context "when the rake task is run" do
context "and there are 2023 logs with invalid earnings" do
let(:user) { create(:user) }
let!(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, voiddate: nil, mrcdate: nil, tenancycode: "123", propcode: "321") }
before do
lettings_log.startdate = Time.zone.local(2023, 4, 4)
lettings_log.incfreq = 1
lettings_log.earnings = 20
lettings_log.hhmemb = 1
lettings_log.ecstat1 = 1
lettings_log.save!(validate: false)
end
it "clears earnings" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.incfreq).to eq(1)
expect(lettings_log.earnings).to eq(20)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
expect(Rails.logger).to receive(:info).with("Clearing earnings for lettings log #{lettings_log.id}, owning_organisation_id: #{lettings_log.owning_organisation_id}, managing_organisation_id: #{lettings_log.managing_organisation_id}, startdate: 2023-04-04, tenancy reference: 123, property reference: 321, assigned_to: #{user.email}(#{user.id}), earnings: 20, incfreq: 1")
task.invoke
lettings_log.reload
expect(lettings_log.incfreq).to eq(nil)
expect(lettings_log.earnings).to eq(nil)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
expect(lettings_log.updated_at).not_to eq(initial_updated_at)
end
end
context "and there are valid 2023 logs" do
let(:user) { create(:user) }
let!(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, voiddate: nil, mrcdate: nil) }
before do
lettings_log.startdate = Time.zone.local(2023, 4, 4)
lettings_log.incfreq = 1
lettings_log.earnings = 95
lettings_log.hhmemb = 1
lettings_log.ecstat1 = 1
lettings_log.save!(validate: false)
end
it "does not update the logs" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.incfreq).to eq(1)
expect(lettings_log.earnings).to eq(95)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
task.invoke
lettings_log.reload
expect(lettings_log.incfreq).to eq(1)
expect(lettings_log.earnings).to eq(95)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
end
context "and there are 2022 logs" do
let(:user) { create(:user) }
let!(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, voiddate: nil, mrcdate: nil) }
before do
lettings_log.startdate = Time.zone.local(2022, 4, 4)
lettings_log.incfreq = 1
lettings_log.earnings = 20
lettings_log.hhmemb = 1
lettings_log.ecstat1 = 1
lettings_log.save!(validate: false)
end
it "does not update the logs" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.incfreq).to eq(1)
expect(lettings_log.earnings).to eq(20)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
task.invoke
lettings_log.reload
expect(lettings_log.incfreq).to eq(1)
expect(lettings_log.earnings).to eq(20)
expect(lettings_log.hhmemb).to eq(1)
expect(lettings_log.ecstat1).to eq(1)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
end
end
end
end

216
spec/lib/tasks/correct_checkbox_values_spec.rb

@ -1,216 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "correct_checkbox_values" do
describe ":correct_checkbox_values", type: :task do
subject(:task) { Rake::Task["correct_checkbox_values"] }
let(:organisation) { create(:organisation, rent_periods: [2]) }
let(:user) { create(:user, organisation:) }
before do
Rake.application.rake_require("tasks/correct_checkbox_values")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and any of the reasonable_preference_reason options are 1" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
it "sets the remaining options to 0" do
log = build(:lettings_log, :completed, reasonpref: 1, rp_homeless: 1, rp_hardship: nil, rp_medwel: nil, rp_insan_unsat: nil, rp_dontknow: nil,
bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).not_to eq(initial_updated_at)
expect(log.status).to eq("completed")
expect(log.rp_homeless).to be(1)
expect(log.rp_hardship).to be(0)
expect(log.rp_medwel).to be(0)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(0)
end
it "updates the reasonable preference reason values on a pending log" do
log = build(:lettings_log, :completed, status: "pending", reasonpref: 1, rp_homeless: 1, rp_hardship: nil, rp_medwel: 1, rp_insan_unsat: nil, rp_dontknow: nil, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rp_homeless).to be(1)
expect(log.rp_hardship).to be(0)
expect(log.rp_medwel).to be(1)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update logs if all unselected reasonable preference reason are alredy 0" do
log = build(:lettings_log, :completed, reasonpref: 1, rp_homeless: 0, rp_hardship: 1, rp_medwel: 0, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("completed")
task.invoke
log.reload
expect(log.status).to eq("completed")
expect(log.updated_at).to eq(initial_updated_at)
end
it "updates the reasonable preference reason values if some of the checkbox values are nil" do
log = build(:lettings_log, :completed, status: "pending", reasonpref: 1, rp_homeless: 0, rp_hardship: nil, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rp_homeless).to be(0)
expect(log.rp_hardship).to be(0)
expect(log.rp_medwel).to be(1)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update the reasonable preference reason values on a 2023 log" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2023, 6, 6), reasonpref: 1, rp_homeless: 0, rp_hardship: nil, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update and logs error if a validation triggers" do
log = build(:lettings_log, :completed, postcode_full: "0", reasonpref: 1, rp_homeless: 0, rp_hardship: nil, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
end
end
context "and any of the illness_type options are 1" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
it "sets the remaining options to 0" do
log = build(:lettings_log, :completed, illness: 1, illness_type_1: 1, illness_type_2: nil, illness_type_3: nil, illness_type_4: nil, illness_type_5: nil, illness_type_6: nil, illness_type_7: nil, illness_type_8: nil, illness_type_9: nil, illness_type_10: nil,
bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).not_to eq(initial_updated_at)
expect(log.status).to eq("completed")
expect(log.illness_type_1).to be(1)
expect(log.illness_type_2).to be(0)
expect(log.illness_type_3).to be(0)
expect(log.illness_type_4).to be(0)
expect(log.illness_type_5).to be(0)
expect(log.illness_type_6).to be(0)
expect(log.illness_type_7).to be(0)
expect(log.illness_type_8).to be(0)
expect(log.illness_type_9).to be(0)
expect(log.illness_type_10).to be(0)
end
it "updates the reasonable preference reason values on a pending log" do
log = build(:lettings_log, :completed, status: "pending", illness: 1, illness_type_1: 1, illness_type_2: nil, illness_type_3: nil, illness_type_4: nil, illness_type_5: nil, illness_type_6: nil, illness_type_7: nil, illness_type_8: nil, illness_type_9: nil, illness_type_10: nil, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.illness_type_1).to be(1)
expect(log.illness_type_2).to be(0)
expect(log.illness_type_3).to be(0)
expect(log.illness_type_4).to be(0)
expect(log.illness_type_5).to be(0)
expect(log.illness_type_6).to be(0)
expect(log.illness_type_7).to be(0)
expect(log.illness_type_8).to be(0)
expect(log.illness_type_9).to be(0)
expect(log.illness_type_10).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update logs if all unselected reasonable preference reason are alredy 0" do
log = build(:lettings_log, :completed, illness: 1, illness_type_1: 0, illness_type_2: 1, illness_type_3: 0, illness_type_4: 0, illness_type_5: 0, illness_type_6: 0, illness_type_7: 0, illness_type_8: 0, illness_type_9: 0, illness_type_10: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("completed")
task.invoke
log.reload
expect(log.status).to eq("completed")
expect(log.updated_at).to eq(initial_updated_at)
end
it "updates the reasonable preference reason values if some of the checkbox values are nil" do
log = build(:lettings_log, :completed, status: "pending", illness: 1, illness_type_1: 0, illness_type_2: nil, illness_type_3: 1, illness_type_4: 0, illness_type_5: 0, illness_type_6: nil, illness_type_7: nil, illness_type_8: nil, illness_type_9: nil, illness_type_10: nil, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.illness_type_1).to be(0)
expect(log.illness_type_2).to be(0)
expect(log.illness_type_3).to be(1)
expect(log.illness_type_4).to be(0)
expect(log.illness_type_5).to be(0)
expect(log.illness_type_6).to be(0)
expect(log.illness_type_7).to be(0)
expect(log.illness_type_8).to be(0)
expect(log.illness_type_9).to be(0)
expect(log.illness_type_10).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update the reasonable preference reason values on a 2023 log" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2023, 6, 6), illness: 1, illness_type_1: 0, illness_type_2: nil, illness_type_3: 1, illness_type_4: 0, illness_type_5: 0, illness_type_6: nil, illness_type_7: nil, illness_type_8: nil, illness_type_9: nil, illness_type_10: nil, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update and logs error if a validation triggers" do
log = build(:lettings_log, :completed, postcode_full: "0", illness: 1, illness_type_1: 0, illness_type_2: nil, illness_type_3: 1, illness_type_4: 0, illness_type_5: 0, illness_type_6: nil, illness_type_7: nil, illness_type_8: nil, illness_type_9: nil, illness_type_10: nil, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
end
end
end
end
end

111
spec/lib/tasks/correct_reasonpref_values_spec.rb

@ -1,111 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "correct_reasonpref_values" do
describe ":correct_reasonpref_values", type: :task do
subject(:task) { Rake::Task["correct_reasonpref_values"] }
let(:organisation) { create(:organisation, rent_periods: [2]) }
let(:user) { create(:user, organisation:) }
before do
Rake.application.rake_require("tasks/correct_reasonpref_values")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and any of the reasonable_preference_reason options are not 1, 0 or nil" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
it "sets the options to 0" do
log = build(:lettings_log, :completed, reasonpref: 1, rp_homeless: -2, rp_hardship: 2, rp_medwel: 3, rp_insan_unsat: 4, rp_dontknow: 1,
bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).not_to eq(initial_updated_at)
expect(log.status).to eq("completed")
expect(log.rp_homeless).to be(0)
expect(log.rp_hardship).to be(0)
expect(log.rp_medwel).to be(0)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(1)
end
it "updates the reasonable preference reason values on a pending log" do
log = build(:lettings_log, :completed, status: "pending", reasonpref: 1, rp_homeless: -2, rp_hardship: 1, rp_medwel: 3, rp_insan_unsat: 4, rp_dontknow: 2, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rp_homeless).to be(0)
expect(log.rp_hardship).to be(1)
expect(log.rp_medwel).to be(0)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update logs with valid values" do
log = build(:lettings_log, :completed, reasonpref: 1, rp_homeless: 0, rp_hardship: 1, rp_medwel: 0, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("completed")
task.invoke
log.reload
expect(log.status).to eq("completed")
expect(log.updated_at).to eq(initial_updated_at)
end
it "updates the reasonable preference reason values if some of the checkbox values are valid" do
log = build(:lettings_log, :completed, status: "pending", reasonpref: 1, rp_homeless: 0, rp_hardship: 2, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rp_homeless).to be(0)
expect(log.rp_hardship).to be(0)
expect(log.rp_medwel).to be(1)
expect(log.rp_insan_unsat).to be(0)
expect(log.rp_dontknow).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "updates the reasonable preference reason values on a 2023 log" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2023, 6, 6), reasonpref: 1, rp_homeless: 0, rp_hardship: 2, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
expect(log.rp_hardship).to eq(0)
end
it "does not update and logs error if a validation triggers" do
log = build(:lettings_log, :completed, postcode_full: "0", reasonpref: 1, rp_homeless: 0, rp_hardship: 2, rp_medwel: 1, rp_insan_unsat: 0, rp_dontknow: 0, bulk_upload:, assigned_to: user)
log.save!(validate: false)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.updated_at).to eq(initial_updated_at)
end
end
end
end
end

254
spec/lib/tasks/correct_rent_type_value_spec.rb

@ -1,254 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "correct_rent_type_value" do
describe ":correct_rent_type_value", type: :task do
subject(:task) { Rake::Task["correct_rent_type_value"] }
before do
Rake.application.rake_require("tasks/correct_rent_type_value")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and rent_type is 1" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
let(:bulk_upload_2023) { create(:bulk_upload, :lettings, year: 2023, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
before do
bulk_upload.save!
end
it "updates the rent_type value on a log where it was set to 1 on create" do
log = create(:lettings_log, :completed, rent_type: 1, bulk_upload:)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("completed")
expect(log.updated_at).not_to eq(initial_updated_at)
expect(bulk_upload.reload.rent_type_fix_status).to eq(BulkUpload.rent_type_fix_statuses[:applied])
end
it "updates the rent_type value on a pending log where it was set to 1 on create" do
log = build(:lettings_log, :completed, rent_type: 1, bulk_upload:, status: "pending")
log.save!
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
expect(bulk_upload.reload.rent_type_fix_status).to eq(BulkUpload.rent_type_fix_statuses[:applied])
end
it "updates the rent_type value on a deleted log where it was set to 1 on create" do
log = create(:lettings_log, :completed, rent_type: 1, bulk_upload:, discarded_at: Time.zone.yesterday)
initial_updated_at = log.updated_at
expect(log.status).to eq("deleted")
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("deleted")
expect(log.updated_at).not_to eq(initial_updated_at)
expect(bulk_upload.reload.rent_type_fix_status).to eq(BulkUpload.rent_type_fix_statuses[:applied])
end
it "updates the rent_type value on a log where it was set to 1 on create and other fields have since changed" do
log = create(:lettings_log, :completed, rent_type: 1, bulk_upload:)
log.update!(tenancycode: "abc")
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("completed")
expect(log.updated_at).not_to eq(initial_updated_at)
expect(bulk_upload.reload.rent_type_fix_status).to eq(BulkUpload.rent_type_fix_statuses[:applied])
end
it "does not update the rent_type value on a log if it has since been changed" do
log = create(:lettings_log, :completed, rent_type: 1, bulk_upload:)
log.update!(rent_type: 0)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("completed")
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update the rent_type value on a 2023 log turned 2024" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2023, 6, 6), rent_type: 1, bulk_upload: bulk_upload_2023)
log.save!(validate: false)
log.address_line1_input = log.address_line1
log.postcode_full_input = log.postcode_full
log.nationality_all_group = 826
log.uprn = "10033558653"
log.uprn_selection = 1
log.startdate = Time.zone.today
log.save!
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update and logs error if a validation triggers" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2021, 6, 6), rent_type: 1, bulk_upload:)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(Rails.logger).to receive(:error).with(/Log #{log.id} rent_type could not be updated from 1 to 0. Error: /)
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.updated_at).to eq(initial_updated_at)
end
context "when the rent_type_fix_status is not_needed" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_needed]) }
before do
bulk_upload.save!
end
it "does not update the rent_type values on logs" do
log = create(:lettings_log, :completed, rent_type: 1, bulk_upload:)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.updated_at).to eq(initial_updated_at)
expect(bulk_upload.reload.rent_type_fix_status).to eq(BulkUpload.rent_type_fix_statuses[:not_needed])
end
end
end
context "and rent_type is 2" do
let(:bulk_upload) { create(:bulk_upload, :lettings, year: 2024, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
let(:bulk_upload_2023) { create(:bulk_upload, :lettings, year: 2023, rent_type_fix_status: BulkUpload.rent_type_fix_statuses[:not_applied]) }
before do
bulk_upload.save!
end
it "updates the rent_type value on a log where it was set to 2 on create" do
log = create(:lettings_log, :completed, rent_type: 2, bulk_upload:)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.status).to eq("completed")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "updates the rent_type value on a pending log where it was set to 2 on create" do
log = build(:lettings_log, :completed, rent_type: 2, bulk_upload:, status: "pending")
log.save!
initial_updated_at = log.updated_at
expect(log.status).to eq("pending")
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.status).to eq("pending")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "updates the rent_type value on a deleted log where it was set to 2 on create" do
log = create(:lettings_log, :completed, rent_type: 2, bulk_upload:, discarded_at: Time.zone.yesterday)
initial_updated_at = log.updated_at
expect(log.status).to eq("deleted")
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.status).to eq("deleted")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "updates the rent_type value on a log where it was set to 2 on create and other fields have since changed" do
log = create(:lettings_log, :completed, rent_type: 2, bulk_upload:)
log.update!(tenancycode: "abc")
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(1)
expect(log.status).to eq("completed")
expect(log.updated_at).not_to eq(initial_updated_at)
end
it "does not update the rent_type value on a log if it has since been changed" do
log = create(:lettings_log, :completed, rent_type: 2, bulk_upload:)
log.update!(rent_type: 0)
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(0)
expect(log.status).to eq("completed")
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update the rent_type value on a 2023 log turned 2024" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2023, 6, 6), rent_type: 2, bulk_upload: bulk_upload_2023)
log.save!(validate: false)
log.address_line1_input = log.address_line1
log.postcode_full_input = log.postcode_full
log.nationality_all_group = 826
log.uprn = "10033558653"
log.uprn_selection = 1
log.startdate = Time.zone.today
log.save!
initial_updated_at = log.updated_at
task.invoke
log.reload
expect(log.rent_type).to be(2)
expect(log.updated_at).to eq(initial_updated_at)
end
it "does not update and logs error if a validation triggers" do
log = build(:lettings_log, :completed, startdate: Time.zone.local(2021, 6, 6), rent_type: 2, bulk_upload:)
log.save!(validate: false)
initial_updated_at = log.updated_at
expect(Rails.logger).to receive(:error).with(/Log #{log.id} rent_type could not be updated from 2 to 1. Error: /)
task.invoke
log.reload
expect(log.rent_type).to be(2)
expect(log.updated_at).to eq(initial_updated_at)
end
end
end
end
end

4
spec/lib/tasks/recalculate_invalid_reasonpref_dontknow_spec.rb

@ -10,14 +10,14 @@ RSpec.describe "recalculate_invalid_reasonpref_dontknow" do
task.reenable
end
let(:invalid_logs) { create_list(:lettings_log, 5, :completed, reasonpref: 1, rp_dontknow: 1, rp_homeless: 1, rp_insan_unsat: rand(2), rp_medwel: rand(2), rp_hardship: rand(2), updated_at: Time.zone.local(2024, 4, 2, 12, 0, 0)) }
let(:invalid_logs) { create_list(:lettings_log, 5, :completed, reasonpref: 1, rp_dontknow: 1, rp_homeless: 1, rp_insan_unsat: rand(2), rp_medwel: rand(2), rp_hardship: rand(2), updated_at: Time.zone.local(2024, 4, 2, 12, 0, 0), startdate: Time.zone.local(2024, rand(4..12), rand(1..30))) }
let(:pre_2024_invalid_logs) do
create_list(:lettings_log, 5, :completed, reasonpref: 1, rp_dontknow: 1, rp_homeless: 1, rp_insan_unsat: rand(2), rp_medwel: rand(2), rp_hardship: rand(2)).each do |log|
log.startdate = Time.zone.local(rand(2021..2023), 4, 1)
log.save!(validate: false)
end
end
let(:valid_logs) { create_list(:lettings_log, 3, :completed, reasonpref: 1, rp_dontknow: 0, rp_homeless: 1, rp_insan_unsat: 1, rp_medwel: rand(2), rp_hardship: rand(2), updated_at: Time.zone.local(2024, 4, 2, 12, 0, 0)) }
let(:valid_logs) { create_list(:lettings_log, 3, :completed, reasonpref: 1, rp_dontknow: 0, rp_homeless: 1, rp_insan_unsat: 1, rp_medwel: rand(2), rp_hardship: rand(2), updated_at: Time.zone.local(2024, 4, 2, 12, 0, 0), startdate: Time.zone.local(2024, rand(4..12), rand(1..30))) }
it "updates the logs from 2024/25 with invalid rp_dontknow values" do
invalid_logs.each do |log|

53
spec/lib/tasks/recalculate_status_after_sales_over_retirement_age_validation_spec.rb

@ -1,53 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "recalculate_status_after_sales_over_retirement_age_validation" do
describe ":recalculate_status_over_retirement", type: :task do
subject(:task) { Rake::Task["recalculate_status_over_retirement"] }
before do
Rake.application.rake_require("tasks/recalculate_status_after_sales_over_retirement_age_validation")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and there is a completed sales log that trips the validation" do
let(:log) { create(:sales_log, :completed, ecstat1: 1, age1: 67) }
before do
log.status = "completed"
log.save!
end
it "sets the log to in progress" do
task.invoke
log.reload
expect(log.status).to eq("in_progress")
end
end
context "and there is a pending sales log that trips the validation" do
let(:log) { create(:sales_log, :completed, ecstat2: 1, age2: 70) }
before do
log.status = "pending"
log.status_cache = "completed"
log.save!
end
it "updates the status cache" do
task.invoke
log.reload
expect(log.status_cache).to eq("in_progress")
end
it "does not change the log status" do
task.invoke
log.reload
expect(log.status).to eq("pending")
end
end
end
end
end

146
spec/lib/tasks/update_created_by_values_spec.rb

@ -1,146 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "update_created_by_values" do
describe ":update_created_by_values", type: :task do
subject(:task) { Rake::Task["update_created_by_values"] }
before do
Rake.application.rake_require("tasks/update_created_by_values")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
let(:user) { create(:user) }
context "with bulk upload id" do
let(:bulk_upload) { create(:bulk_upload) }
let(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, bulk_upload_id: bulk_upload.id, updated_at: Time.zone.yesterday) }
let(:sales_log) { create(:sales_log, :completed, assigned_to: user, bulk_upload_id: bulk_upload.id, updated_at: Time.zone.yesterday) }
it "updates created_by to bulk upload user id for lettings log" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.created_by_id).to eq(user.id)
expect(lettings_log.assigned_to_id).to eq(user.id)
task.invoke
lettings_log.reload
expect(lettings_log.created_by_id).to eq(bulk_upload.user_id)
expect(lettings_log.assigned_to_id).to eq(user.id)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
it "updates created_by to bulk upload user id for sales log" do
initial_updated_at = sales_log.updated_at
expect(sales_log.created_by_id).to eq(user.id)
expect(sales_log.assigned_to_id).to eq(user.id)
task.invoke
sales_log.reload
expect(sales_log.created_by_id).to eq(bulk_upload.user_id)
expect(sales_log.assigned_to_id).to eq(user.id)
expect(sales_log.updated_at).to eq(initial_updated_at)
end
end
context "without bulk upload id" do
context "and version whodunnit exists for create" do
let(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
let(:sales_log) { create(:sales_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
let(:other_user) { create(:user, organisation: user.organisation) }
before do
PaperTrail::Version.find_by(item_id: lettings_log.id, item_type: "LettingsLog", event: "create").update!(whodunnit: other_user.to_global_id.uri.to_s)
PaperTrail::Version.find_by(item_id: sales_log.id, item_type: "SalesLog", event: "create").update!(whodunnit: other_user.to_global_id.uri.to_s)
end
it "updates created_by to create whodunnit for lettings" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.created_by_id).to eq(nil)
expect(lettings_log.assigned_to_id).to eq(user.id)
task.invoke
lettings_log.reload
expect(lettings_log.created_by_id).to eq(other_user.id)
expect(lettings_log.assigned_to_id).to eq(user.id)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
it "updates created_by to create whodunnit for sales" do
initial_updated_at = sales_log.updated_at
expect(sales_log.created_by_id).to eq(nil)
expect(sales_log.assigned_to_id).to eq(user.id)
task.invoke
sales_log.reload
expect(sales_log.created_by_id).to eq(other_user.id)
expect(sales_log.assigned_to_id).to eq(user.id)
expect(sales_log.updated_at).to eq(initial_updated_at)
end
end
context "and version whodunnit does not exist for create" do
let(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
let(:sales_log) { create(:sales_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
before do
PaperTrail::Version.find_by(item_id: lettings_log.id, event: "create").update!(whodunnit: nil)
PaperTrail::Version.find_by(item_id: sales_log.id, event: "create").update!(whodunnit: nil)
end
it "sets created_by to assigned_to for lettings" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.created_by_id).to eq(nil)
expect(lettings_log.assigned_to_id).to eq(user.id)
task.invoke
lettings_log.reload
expect(lettings_log.created_by_id).to eq(user.id)
expect(lettings_log.assigned_to_id).to eq(user.id)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
it "sets created_by to assigned_to for sales" do
initial_updated_at = sales_log.updated_at
expect(sales_log.created_by_id).to eq(nil)
expect(sales_log.assigned_to_id).to eq(user.id)
task.invoke
sales_log.reload
expect(sales_log.created_by_id).to eq(user.id)
expect(sales_log.assigned_to_id).to eq(user.id)
expect(sales_log.updated_at).to eq(initial_updated_at)
end
end
context "and version whodunnit is not a User for create" do
let(:lettings_log) { create(:lettings_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
let(:sales_log) { create(:sales_log, :completed, assigned_to: user, created_by_id: nil, updated_at: Time.zone.yesterday) }
let(:other_user) { create(:user, organisation: user.organisation) }
before do
PaperTrail::Version.find_by(item_id: lettings_log.id, item_type: "LettingsLog", event: "create").update!(whodunnit: other_user.email)
PaperTrail::Version.find_by(item_id: sales_log.id, item_type: "SalesLog", event: "create").update!(whodunnit: other_user.email)
end
it "sets created_by to assigned_to for lettings" do
initial_updated_at = lettings_log.updated_at
expect(lettings_log.created_by_id).to eq(nil)
expect(lettings_log.assigned_to_id).to eq(user.id)
task.invoke
lettings_log.reload
expect(lettings_log.created_by_id).to eq(user.id)
expect(lettings_log.assigned_to_id).to eq(user.id)
expect(lettings_log.updated_at).to eq(initial_updated_at)
end
it "sets created_by to assigned_to for sales" do
initial_updated_at = sales_log.updated_at
expect(sales_log.created_by_id).to eq(nil)
expect(sales_log.assigned_to_id).to eq(user.id)
task.invoke
sales_log.reload
expect(sales_log.created_by_id).to eq(user.id)
expect(sales_log.assigned_to_id).to eq(user.id)
expect(sales_log.updated_at).to eq(initial_updated_at)
end
end
end
end
end
end

211
spec/lib/tasks/update_manual_address_entry_selected_prexisting_logs_spec.rb

@ -1,211 +0,0 @@
require "rails_helper"
require "rake"
RSpec.describe "update_manual_address_entry_selected_preexisting_logs_spec", type: :task do
before do
Rake.application.rake_require("tasks/update_manual_address_entry_selected_prexisting_logs")
Rake::Task.define_task(:environment)
task.reenable
end
describe "bulk_update:update_manual_address_entry_selected" do
let(:task) { Rake::Task["bulk_update:update_manual_address_entry_selected"] }
let(:lettings_log_uprn_entered) do
build(:lettings_log, :completed, startdate: Time.zone.local(2024, 6, 1), needstype: 1, manual_address_entry_selected: false)
end
let(:lettings_log_uprn_found) do
build(:lettings_log, :completed, startdate: Time.zone.local(2024, 9, 1), needstype: 1, manual_address_entry_selected: false, address_line1_input: "1 Test Street", postcode_full_input: "SW1 1AA")
end
let(:lettings_log_address_fields_not_entered) do
build(:lettings_log, :inprogress_without_address_fields, startdate: Time.zone.local(2024, 9, 1), needstype: 1)
end
let(:lettings_log_address_manually_entered) do
build(:lettings_log, :completed_without_uprn, startdate: Time.zone.local(2024, 12, 1), needstype: 1)
end
let(:sales_log_uprn_entered) do
build(:sales_log, :completed, saledate: Time.zone.local(2024, 12, 1), manual_address_entry_selected: false)
end
let(:sales_log_uprn_found) do
build(:sales_log, :completed, saledate: Time.zone.local(2024, 7, 1), manual_address_entry_selected: false, address_line1_input: "1 Test Street", postcode_full_input: "SW1 1AA")
end
let(:sales_log_address_fields_not_entered) do
build(:sales_log, :inprogress_without_address_fields, saledate: Time.zone.local(2024, 12, 30))
end
let(:sales_log_address_manually_entered) do
build(:sales_log, :completed_without_uprn, saledate: Time.zone.local(2024, 12, 30))
end
context "when running the task" do
context "when logs do not meet the criteria" do
before do
lettings_log_uprn_found.save!(validate: false)
lettings_log_uprn_entered.save!(validate: false)
lettings_log_address_fields_not_entered.save!(validate: false)
sales_log_uprn_found.save!(validate: false)
sales_log_uprn_entered.save!(validate: false)
sales_log_address_fields_not_entered.save!(validate: false)
end
it "does not update logs with a UPRN entered" do
task.invoke
lettings_log_uprn_entered.reload
sales_log_uprn_entered.reload
expect(lettings_log_uprn_entered.manual_address_entry_selected).to be false
expect(lettings_log_uprn_entered.uprn).to eq("10033558653")
expect(sales_log_uprn_entered.manual_address_entry_selected).to be false
expect(sales_log_uprn_entered.uprn).to eq("10033558653")
end
it "does not update logs with a UPRN found" do
task.invoke
lettings_log_uprn_found.reload
sales_log_uprn_found.reload
expect(lettings_log_uprn_found.manual_address_entry_selected).to be false
expect(lettings_log_uprn_found.uprn).to eq("10033558653")
expect(sales_log_uprn_found.manual_address_entry_selected).to be false
expect(sales_log_uprn_found.uprn).to eq("10033558653")
end
it "does not update logs with no UPRN or address fields entered" do
task.invoke
lettings_log_address_fields_not_entered.reload
sales_log_address_fields_not_entered.reload
expect(lettings_log_address_fields_not_entered.manual_address_entry_selected).to be false
expect(sales_log_address_fields_not_entered.manual_address_entry_selected).to be false
end
end
context "when logs do meet the criteria" do
before do
lettings_log_address_manually_entered.manual_address_entry_selected = false
lettings_log_address_manually_entered.save!(validate: false)
sales_log_address_manually_entered.manual_address_entry_selected = false
sales_log_address_manually_entered.save!(validate: false)
end
it "updates logs with an address manually entered" do
expect(lettings_log_address_manually_entered.manual_address_entry_selected).to be false
expect(lettings_log_address_manually_entered.address_line1).to eq("1 Test Street")
expect(lettings_log_address_manually_entered.address_line2).to eq("Testville")
expect(lettings_log_address_manually_entered.town_or_city).to eq("Testford")
expect(lettings_log_address_manually_entered.postcode_full).to eq("SW1 1AA")
expect(sales_log_address_manually_entered.manual_address_entry_selected).to be false
expect(sales_log_address_manually_entered.address_line1).to eq("1 Test Street")
expect(sales_log_address_manually_entered.address_line2).to eq("Testville")
expect(sales_log_address_manually_entered.town_or_city).to eq("Testford")
expect(sales_log_address_manually_entered.postcode_full).to eq("SW1 1AA")
task.invoke
lettings_log_address_manually_entered.reload
sales_log_address_manually_entered.reload
expect(lettings_log_address_manually_entered.manual_address_entry_selected).to be true
expect(lettings_log_address_manually_entered.address_line1).to eq("1 Test Street")
expect(lettings_log_address_manually_entered.address_line2).to eq("Testville")
expect(lettings_log_address_manually_entered.town_or_city).to eq("Testford")
expect(lettings_log_address_manually_entered.postcode_full).to eq("SW1 1AA")
expect(sales_log_address_manually_entered.manual_address_entry_selected).to be true
expect(sales_log_address_manually_entered.address_line1).to eq("1 Test Street")
expect(sales_log_address_manually_entered.address_line2).to eq("Testville")
expect(sales_log_address_manually_entered.town_or_city).to eq("Testford")
expect(sales_log_address_manually_entered.postcode_full).to eq("SW1 1AA")
end
end
end
end
describe "bulk_update:update_postcode_full_preexisting_manual_entry_logs" do
let(:task) { Rake::Task["bulk_update:update_postcode_full_preexisting_manual_entry_logs"] }
let(:lettings_log_to_fix) do
build(:lettings_log, :inprogress_without_address_fields, startdate: Time.zone.local(2024, 6, 1), updated_at: Time.zone.parse("2025-03-19 16:30:00"))
end
let(:bu_lettings_log_to_fix) do
build(:lettings_log, :inprogress_without_address_fields, startdate: Time.zone.local(2024, 6, 1), creation_method: "bulk upload", updated_at: Time.zone.parse("2025-03-19 16:30:00"))
end
let(:lettings_log_not_to_fix) do
build(:lettings_log, :inprogress_without_address_fields, startdate: Time.zone.local(2024, 6, 1), updated_at: Time.zone.parse("2025-03-19 15:30:00"))
end
before do
lettings_log_to_fix.manual_address_entry_selected = true
lettings_log_to_fix.address_line1 = "1 Test Street"
lettings_log_to_fix.address_line2 = "Testville"
lettings_log_to_fix.town_or_city = "Testford"
lettings_log_to_fix.postcode_full = nil
lettings_log_to_fix.address_line1_input = "1 Test Street"
lettings_log_to_fix.postcode_full_input = "SW1 2BB"
lettings_log_to_fix.save!(validate: false)
bu_lettings_log_to_fix.manual_address_entry_selected = true
bu_lettings_log_to_fix.address_line1 = "1 Test Street"
bu_lettings_log_to_fix.address_line2 = "Testville"
bu_lettings_log_to_fix.town_or_city = "Testford"
bu_lettings_log_to_fix.postcode_full = nil
bu_lettings_log_to_fix.address_line1_as_entered = "1 Test Street"
bu_lettings_log_to_fix.postcode_full_as_entered = "SW1 2BB"
bu_lettings_log_to_fix.save!(validate: false)
lettings_log_not_to_fix.postcode_full = nil
lettings_log_not_to_fix.save!(validate: false)
end
context "when running the task" do
it "updates logs that meet the criteria" do
expect(lettings_log_to_fix.postcode_full).to be_nil
expect(lettings_log_to_fix.address_line1).to eq("1 Test Street")
expect(lettings_log_to_fix.address_line2).to eq("Testville")
expect(lettings_log_to_fix.town_or_city).to eq("Testford")
expect(lettings_log_to_fix.address_line1_input).to eq("1 Test Street")
expect(lettings_log_to_fix.postcode_full_input).to eq("SW1 2BB")
expect(bu_lettings_log_to_fix.postcode_full).to be_nil
expect(bu_lettings_log_to_fix.address_line1_input).to be_nil
expect(bu_lettings_log_to_fix.address_line1).to eq("1 Test Street")
expect(bu_lettings_log_to_fix.address_line2).to eq("Testville")
expect(bu_lettings_log_to_fix.town_or_city).to eq("Testford")
expect(bu_lettings_log_to_fix.address_line1_as_entered).to eq("1 Test Street")
expect(bu_lettings_log_to_fix.postcode_full_as_entered).to eq("SW1 2BB")
task.invoke
lettings_log_to_fix.reload
bu_lettings_log_to_fix.reload
expect(lettings_log_to_fix.postcode_full).to eq(lettings_log_to_fix.postcode_full_input)
expect(lettings_log_to_fix.postcode_full).to eq("SW1 2BB")
expect(bu_lettings_log_to_fix.postcode_full).to eq(bu_lettings_log_to_fix.postcode_full_as_entered)
expect(bu_lettings_log_to_fix.postcode_full).to eq("SW1 2BB")
end
it "does not update logs that do not meet the criteria" do
task.invoke
lettings_log_not_to_fix.reload
expect(lettings_log_not_to_fix.postcode_full).to be_nil
end
end
end
end

4
spec/models/bulk_upload_spec.rb

@ -29,10 +29,10 @@ RSpec.describe BulkUpload, type: :model do
end
context "with a sales log bulk upload" do
let(:log) { build(:sales_log, :saledate_today, bulk_upload:) }
let(:log) { build(:sales_log, saledate: Time.zone.local(2025, 4, 2), bulk_upload:) }
it "has the correct number of value checks to be set as confirmed" do
expect(bulk_upload.fields_to_confirm(log)).to match_array %w[value_value_check monthly_charges_value_check percentage_discount_value_check income1_value_check income2_value_check combined_income_value_check retirement_value_check old_persons_shared_ownership_value_check buyer_livein_value_check student_not_child_value_check wheel_value_check mortgage_value_check savings_value_check deposit_value_check staircase_bought_value_check stairowned_value_check hodate_check shared_ownership_deposit_value_check extrabor_value_check grant_value_check discounted_sale_value_check deposit_and_mortgage_value_check multiple_partners_value_check partner_under_16_value_check]
expect(bulk_upload.fields_to_confirm(log)).to match_array %w[value_value_check monthly_charges_value_check percentage_discount_value_check income1_value_check income2_value_check combined_income_value_check retirement_value_check old_persons_shared_ownership_value_check buyer_livein_value_check wheel_value_check mortgage_value_check savings_value_check deposit_value_check staircase_bought_value_check stairowned_value_check hodate_check shared_ownership_deposit_value_check extrabor_value_check grant_value_check discounted_sale_value_check deposit_and_mortgage_value_check multiple_partners_value_check partner_under_16_value_check]
end
end
end

6
spec/models/location_spec.rb

@ -1016,16 +1016,14 @@ RSpec.describe Location, type: :model do
end
it "returns reactivating soon if the location has a future reactivation date" do
deactivation_period = FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.yesterday, reactivation_date: Time.zone.tomorrow, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.yesterday, reactivation_date: Time.zone.tomorrow, location:)
location.save!
expect(deactivation_period.deactivation_date).to eq(Time.zone.yesterday)
expect(location.status).to eq(:reactivating_soon)
end
it "returns reactivating soon if the location had a deactivation during another deactivation" do
deactivation_period = FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.today - 1.month, reactivation_date: Time.zone.today + 2.days, location:)
FactoryBot.create(:location_deactivation_period, deactivation_date: Time.zone.today - 1.month, reactivation_date: Time.zone.today + 2.days, location:)
location.save!
expect(deactivation_period.deactivation_date).to eq(Time.zone.today - 1.month)
expect(location.status).to eq(:reactivating_soon)
end

3
spec/models/scheme_spec.rb

@ -433,9 +433,8 @@ RSpec.describe Scheme, type: :model do
end
it "returns reactivating soon if the scheme had a deactivation during another deactivation" do
deactivation_period = FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.today - 2.months, reactivation_date: Time.zone.today + 2.days, scheme:)
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.today - 2.months, reactivation_date: Time.zone.today + 2.days, scheme:)
scheme.save!
expect(deactivation_period.deactivation_date).to eq(Time.zone.today - 2.months)
expect(scheme.status).to eq(:reactivating_soon)
end

52
spec/models/validations/sales/financial_validations_spec.rb

@ -427,7 +427,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
end
end
describe "#validate_equity_less_than_staircase_difference" do
describe "#validate_staircase_difference" do
let(:record) { FactoryBot.build(:sales_log, saledate:) }
context "with a log in the 23/24 collection year" do
@ -437,7 +437,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = 2
record.stairowned = 3
record.equity = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
end
@ -450,7 +450,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairowned = 3
record.equity = 2
record.jointpur = 1
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 0.5))
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 0.5))
expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 0.5))
@ -461,25 +461,25 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairowned = 3
record.equity = 2.5
record.jointpur = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2.5, staircase_difference: 1.0))
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2.5, staircase_difference: 1.0))
expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2.5, staircase_difference: 1.0))
end
it "does not add errors if equity is less than stairowned - stairbought" do
it "does not add errors if equity is less than stairowned - stairbought and stairnum is nil" do
record.stairbought = 2
record.stairowned = 10
record.equity = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if equity is equal stairowned - stairbought" do
it "does not add errors if equity is equal stairowned - stairbought and stairnum is nil" do
record.stairbought = 2
record.stairowned = 10
record.equity = 8
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
@ -487,7 +487,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = nil
record.stairowned = 10
record.equity = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
@ -495,7 +495,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = 2
record.stairowned = nil
record.equity = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
@ -503,7 +503,37 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = 2
record.stairowned = 10
record.equity = 0
financial_validator.validate_equity_less_than_staircase_difference(record)
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "adds errors if stairnum is present and stairowned is not enough more than stairbought + equity" do
record.stairowned = 20
record.stairbought = 10
record.equity = 9
record.numstair = 3
financial_validator.validate_staircase_difference(record)
expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.more_than_stairowned_minus_stairbought_minus_prev_staircasing", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.equity.more_than_stairowned_minus_stairbought_minus_prev_staircasing", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.equity.more_than_stairowned_minus_stairbought_minus_prev_staircasing", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
expect(record.errors["numstair"]).to include(I18n.t("validations.sales.financial.equity.more_than_stairowned_minus_stairbought_minus_prev_staircasing", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
end
it "does not add errors if stairnum is present and stairowned is enough more than stairbought + equity" do
record.stairowned = 25
record.stairbought = 10
record.equity = 9
record.numstair = 3
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if stairnum is present and stairowned exactly equals minimum" do
record.stairowned = 20
record.stairbought = 10
record.equity = 9
record.numstair = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
end

157
spec/models/validations/sales/sale_information_validations_spec.rb

@ -182,6 +182,163 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
end
describe "#validate_staircasing_initial_purchase_date" do
context "when initial purchase date blank" do
let(:record) { build(:sales_log, initialpurchase: nil) }
it "does not add an error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).not_to be_present
end
end
context "when initial purchase date in 1979" do
let(:record) { build(:sales_log, initialpurchase: Date.new(1979, 12, 31)) }
it "adds an error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).to be_present
end
end
context "when initial purchase date in 1980" do
let(:record) { build(:sales_log, initialpurchase: Date.new(1980, 1, 1)) }
it "does not add an error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).not_to be_present
end
end
context "when initial purchase date before saledate" do
let(:record) { build(:sales_log, initialpurchase: 2.months.ago, saledate: 1.month.ago) }
it "does not add the error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).not_to be_present
end
end
context "when initial purchase date after saledate" do
let(:record) { build(:sales_log, initialpurchase: 1.month.ago, saledate: 2.months.ago) }
it "adds error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")])
expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")])
end
end
context "when initial purchase date == saledate" do
let(:record) { build(:sales_log, initialpurchase: Time.zone.parse("2023-07-01"), saledate: Time.zone.parse("2023-07-01")) }
it "does not add an error" do
sale_information_validator.validate_staircasing_initial_purchase_date(record)
expect(record.errors[:initialpurchase]).not_to be_present
end
end
end
describe "#validate_staircasing_last_transaction_date" do
context "when last transaction date blank" do
let(:record) { build(:sales_log, lasttransaction: nil) }
it "does not add an error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
context "when last transaction date in 1979" do
let(:record) { build(:sales_log, lasttransaction: Date.new(1979, 12, 31)) }
it "adds an error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).to be_present
end
end
context "when last transaction date in 1980" do
let(:record) { build(:sales_log, lasttransaction: Date.new(1980, 1, 1)) }
it "does not add an error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
context "when last transaction date before saledate" do
let(:record) { build(:sales_log, lasttransaction: 2.months.ago, saledate: 1.month.ago) }
it "does not add the error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
context "when last transaction date after saledate" do
let(:record) { build(:sales_log, lasttransaction: 1.month.ago, saledate: 2.months.ago) }
it "adds error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")])
expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")])
end
end
context "when last transaction date == saledate" do
let(:record) { build(:sales_log, lasttransaction: Time.zone.parse("2023-07-01"), saledate: Time.zone.parse("2023-07-01")) }
it "does not add an error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
context "when last transaction date after initial purchase date" do
let(:record) { build(:sales_log, initialpurchase: 2.months.ago, lasttransaction: 1.month.ago) }
it "does not add the error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
context "when last transaction date before initial purchase date" do
let(:record) { build(:sales_log, initialpurchase: 1.month.ago, lasttransaction: 2.months.ago) }
it "adds error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")])
expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")])
end
end
context "when last transaction date == initial purchase date" do
let(:record) { build(:sales_log, lasttransaction: Time.zone.parse("2023-07-01"), initialpurchase: Time.zone.parse("2023-07-01")) }
it "does not add an error" do
sale_information_validator.validate_staircasing_last_transaction_date(record)
expect(record.errors[:lasttransaction]).not_to be_present
end
end
end
describe "#validate_previous_property_unit_type" do
context "when number of bedrooms is <= 1" do
let(:record) { FactoryBot.build(:sales_log, frombeds: 1, fromprop: 2) }

2
spec/requests/bulk_upload_sales_logs_controller_spec.rb

@ -68,7 +68,7 @@ RSpec.describe BulkUploadSalesLogsController, type: :request do
end
it "shows guidance page with correct title" do
get "/sales-logs/bulk-upload-logs/guidance?form%5Byear%5D=2023", params: {}
get "/sales-logs/bulk-upload-logs/guidance?form%5Byear%5D=#{previous_collection_start_year}", params: {}
expect(response.body).to include("How to upload logs in bulk")
end

2
spec/requests/check_errors_controller_spec.rb

@ -4,7 +4,7 @@ RSpec.describe CheckErrorsController, type: :request do
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :data_coordinator) }
let(:lettings_log) { create(:lettings_log, :setup_completed, assigned_to: user) }
let(:sales_log) { create(:sales_log, :shared_ownership_setup_complete, assigned_to: user) }
let(:sales_log) { create(:sales_log, :shared_ownership_setup_complete, staircase: 2, assigned_to: user) }
describe "check errors page" do
context "when user is not signed in" do

22
spec/requests/collection_resources_controller_spec.rb

@ -118,10 +118,21 @@ RSpec.describe CollectionResourcesController, type: :request do
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification"))
end
context "when the collection year has not started yet" do
before do
Timecop.freeze(Time.zone.local(2025, 3, 1))
get collection_resources_path
end
after do
Timecop.return
end
it "displays next year banner" do
expect(page).to have_content("The 2025 to 2026 collection resources are not yet available to users.")
expect(page).to have_link("Release the 2025 to 2026 collection resources to users", href: confirm_mandatory_collection_resources_release_path(year: 2025))
end
end
context "when there are additional resources" do
let!(:collection_resource) { create(:collection_resource, :additional, year: 2025, short_display_name: "additional resource", download_filename: "additional.pdf") }
@ -161,11 +172,22 @@ RSpec.describe CollectionResourcesController, type: :request do
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification"))
end
context "when the collection year has not started yet" do
before do
Timecop.freeze(Time.zone.local(2025, 3, 1))
get collection_resources_path
end
after do
Timecop.return
end
it "displays next year banner" do
expect(page).to have_content("The 2025 to 2026 collection resources are not yet available to users.")
expect(page).to have_content("Once you have uploaded all the required 2025 to 2026 collection resources, you will be able to release them to users.")
end
end
end
context "when there are additional resources" do
let!(:collection_resource) { create(:collection_resource, :additional, year: 2025, short_display_name: "additional resource", download_filename: "additional.pdf") }

9
spec/requests/form_controller_spec.rb

@ -1640,7 +1640,6 @@ RSpec.describe FormController, type: :request do
end
context "when coming from check answers page" do
let(:sales_log) { create(:sales_log, ownershipsch: 3, assigned_to: user) }
let(:lettings_log_referrer) { "/lettings-logs/#{lettings_log.id}/needs-type?referrer=check_answers" }
let(:sales_log_referrer) { "/sales-logs/#{sales_log.id}/ownership-scheme?referrer=check_answers" }
@ -1674,6 +1673,14 @@ RSpec.describe FormController, type: :request do
end
context "and changing an answer" do
before do
Timecop.freeze(2024, 5, 6)
end
after do
Timecop.return
end
it "navigates to follow-up questions when required" do
post "/lettings-logs/#{lettings_log.id}/needs-type", params: lettings_log_form_needs_type_params, headers: headers.merge({ "HTTP_REFERER" => lettings_log_referrer })
expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/scheme?referrer=check_answers")

42
spec/requests/lettings_logs_controller_spec.rb

@ -1218,8 +1218,20 @@ RSpec.describe LettingsLogsController, type: :request do
end
end
context "when a lettings log is for a renewal of supported housing" do
let(:lettings_log) { create(:lettings_log, :startdate_today, assigned_to: user, renewal: 1, needstype: 2, rent_type: 3, postcode_known: 0) }
context "when a lettings log is for a renewal of supported housing in 2024" do
let(:lettings_log) { create(:lettings_log, :startdate_today, assigned_to: user, renewal: 1, needstype: 2, rent_type: 3, postcode_known: 0, startdate: Time.zone.local(2024, 10, 20)) }
before do
Timecop.freeze(2024, 10, 15)
Singleton.__init__(FormHandler)
lettings_log.startdate = Time.zone.local(2024, 10, 20)
lettings_log.save!
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "does not show property information" do
get lettings_log_path(lettings_log)
@ -1232,6 +1244,32 @@ RSpec.describe LettingsLogsController, type: :request do
end
end
context "when a lettings log is for a renewal of supported housing in 2025" do
let(:lettings_log) { create(:lettings_log, :startdate_today, assigned_to: user, renewal: 1, needstype: 2, rent_type: 3, postcode_known: 0) }
before do
Timecop.freeze(2025, 10, 15)
Singleton.__init__(FormHandler)
lettings_log.startdate = Time.zone.local(2025, 10, 20)
lettings_log.save!
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
it "shows property information" do
get lettings_log_path(lettings_log)
expect(page).to have_content "Tenancy information"
expect(page).to have_content "Property information"
end
it "does not crash the app if postcode_known is not nil" do
expect { get lettings_log_path(lettings_log) }.not_to raise_error
end
end
context "with lettings logs that are not owned or managed by your organisation" do
before do
sign_in user

1
spec/services/bulk_upload/sales/validator_spec.rb

@ -138,6 +138,7 @@ RSpec.describe BulkUpload::Sales::Validator do
context "with an invalid 2024 csv" do
before do
log.owning_organisation = nil
log.saledate = Time.zone.local(2024, 10, 10)
file.write(log_to_csv.default_field_numbers_row)
file.write(log_to_csv.to_csv_row)
file.rewind

2
spec/services/csv/lettings_log_csv_service_spec.rb

@ -117,7 +117,7 @@ RSpec.describe Csv::LettingsLogCsvService do
context "when exporting with human readable labels" do
let(:export_type) { "labels" }
let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) }
let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312, startdate: Time.zone.local(2024, 11, 1)) }
it "gives answer to radio questions as labels" do
relat2_column_index = attribute_line.index("relat2")

6
spec/views/form/guidance/_financial_calculations_outright_sale_spec.rb

@ -6,7 +6,7 @@ RSpec.describe "form/guidance/_financial_calculations_outright_sale.html.erb" do
let(:fragment) { Capybara::Node::Simple.new(rendered) }
context "when mortgage used is not answered" do
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: nil, discount: 30) }
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: nil, discount: 30, saledate: Time.zone.local(2024, 11, 1)) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }
@ -18,7 +18,7 @@ RSpec.describe "form/guidance/_financial_calculations_outright_sale.html.erb" do
end
context "when mortgage used is no" do
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: 2, discount: nil) }
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: 2, discount: nil, saledate: Time.zone.local(2024, 11, 1)) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }
@ -32,7 +32,7 @@ RSpec.describe "form/guidance/_financial_calculations_outright_sale.html.erb" do
end
context "when mortgage used is yes" do
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: 1, mortgage: nil, discount: 30) }
let(:log) { create(:sales_log, :outright_sale_setup_complete, ownershipsch: 3, type: 10, mortgageused: 1, mortgage: nil, discount: 30, saledate: Time.zone.local(2024, 11, 1)) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }

Loading…
Cancel
Save