Browse Source

Merge branch 'main' into dependabot/bundler/docs/nokogiri-1.18.9

pull/3091/head
Samuel Young 2 months ago
parent
commit
1803202b33
  1. 2
      .github/workflows/review_pipeline.yml
  2. 120
      Gemfile.lock
  3. 3
      app/controllers/form_controller.rb
  4. 4
      app/helpers/collection_time_helper.rb
  5. 1
      app/models/form/lettings/questions/brent_4_weekly.rb
  6. 1
      app/models/form/lettings/questions/brent_bi_weekly.rb
  7. 1
      app/models/form/lettings/questions/brent_monthly.rb
  8. 1
      app/models/form/lettings/questions/brent_weekly.rb
  9. 1
      app/models/form/lettings/questions/chcharge_4_weekly.rb
  10. 1
      app/models/form/lettings/questions/chcharge_bi_weekly.rb
  11. 1
      app/models/form/lettings/questions/chcharge_monthly.rb
  12. 1
      app/models/form/lettings/questions/chcharge_weekly.rb
  13. 1
      app/models/form/lettings/questions/earnings.rb
  14. 1
      app/models/form/lettings/questions/pscharge_4_weekly.rb
  15. 1
      app/models/form/lettings/questions/pscharge_bi_weekly.rb
  16. 1
      app/models/form/lettings/questions/pscharge_monthly.rb
  17. 1
      app/models/form/lettings/questions/pscharge_weekly.rb
  18. 1
      app/models/form/lettings/questions/scharge_4_weekly.rb
  19. 1
      app/models/form/lettings/questions/scharge_bi_weekly.rb
  20. 1
      app/models/form/lettings/questions/scharge_monthly.rb
  21. 1
      app/models/form/lettings/questions/scharge_weekly.rb
  22. 1
      app/models/form/lettings/questions/supcharg_4_weekly.rb
  23. 1
      app/models/form/lettings/questions/supcharg_bi_weekly.rb
  24. 1
      app/models/form/lettings/questions/supcharg_monthly.rb
  25. 1
      app/models/form/lettings/questions/supcharg_weekly.rb
  26. 1
      app/models/form/lettings/questions/tcharge_4_weekly.rb
  27. 1
      app/models/form/lettings/questions/tcharge_bi_weekly.rb
  28. 1
      app/models/form/lettings/questions/tcharge_monthly.rb
  29. 1
      app/models/form/lettings/questions/tcharge_weekly.rb
  30. 1
      app/models/form/lettings/questions/tshortfall.rb
  31. 3
      app/models/form/question.rb
  32. 1
      app/models/form/sales/questions/buyer1_income.rb
  33. 1
      app/models/form/sales/questions/buyer2_income.rb
  34. 1
      app/models/form/sales/questions/deposit_amount.rb
  35. 1
      app/models/form/sales/questions/deposit_discount.rb
  36. 1
      app/models/form/sales/questions/grant.rb
  37. 1
      app/models/form/sales/questions/leasehold_charges.rb
  38. 1
      app/models/form/sales/questions/management_fee.rb
  39. 1
      app/models/form/sales/questions/monthly_rent.rb
  40. 1
      app/models/form/sales/questions/monthly_rent_after_staircasing.rb
  41. 1
      app/models/form/sales/questions/monthly_rent_before_staircasing.rb
  42. 1
      app/models/form/sales/questions/mortgage_amount.rb
  43. 1
      app/models/form/sales/questions/purchase_price.rb
  44. 1
      app/models/form/sales/questions/savings.rb
  45. 1
      app/models/form/sales/questions/service_charge.rb
  46. 1
      app/models/form/sales/questions/value.rb
  47. 2
      app/models/validations/soft_validations.rb
  48. 2
      app/services/merge/merge_organisations_service.rb
  49. 13
      docs/infrastructure.md
  50. 14
      spec/features/sales_log_spec.rb
  51. 8
      spec/helpers/guidance_helper_spec.rb
  52. 2
      spec/helpers/merge_requests_helper_spec.rb
  53. 11
      spec/lib/tasks/recalculate_invalid_reasonpref_dontknow_spec.rb
  54. 7
      spec/lib/tasks/update_manual_address_entry_selected_prexisting_logs_spec.rb
  55. 2
      spec/models/lettings_log_derived_fields_spec.rb
  56. 6
      spec/models/log_spec.rb
  57. 92
      spec/models/sales_log_spec.rb
  58. 2
      spec/models/scheme_spec.rb
  59. 4
      spec/models/validations/date_validations_spec.rb
  60. 2
      spec/models/validations/financial_validations_spec.rb
  61. 164
      spec/models/validations/household_validations_spec.rb
  62. 343
      spec/models/validations/sales/financial_validations_spec.rb
  63. 389
      spec/models/validations/sales/household_validations_spec.rb
  64. 75
      spec/models/validations/sales/property_validations_spec.rb
  65. 793
      spec/models/validations/sales/sale_information_validations_spec.rb
  66. 93
      spec/models/validations/sales/soft_validations_spec.rb
  67. 98
      spec/requests/collection_resources_controller_spec.rb
  68. 165
      spec/requests/duplicate_logs_controller_spec.rb
  69. 31
      spec/requests/lettings_logs_controller_spec.rb
  70. 192
      spec/services/csv/lettings_log_csv_service_spec.rb
  71. 12
      spec/services/documentation_generator_spec.rb
  72. 40
      spec/services/merge/merge_organisations_service_spec.rb
  73. 10
      spec/views/form/guidance/_financial_calculations_outright_sale_spec.rb

2
.github/workflows/review_pipeline.yml

@ -52,6 +52,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
msg: "Created review app at https://review.submit-social-housing-data.communities.gov.uk/${{ github.event.pull_request.number }}"
msg: "Created review app at https://review.submit-social-housing-data.communities.gov.uk/${{ github.event.pull_request.number }}. Note that the review app will be automatically deprovisioned after 30 days and will need the review app pipeline running again."
check_for_duplicate_msg: true
duplicate_msg_pattern: Created review app at*

120
Gemfile.lock

@ -1,29 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
actioncable (7.2.2.2)
actionpack (= 7.2.2.2)
activesupport (= 7.2.2.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
actionmailbox (7.2.2.2)
actionpack (= 7.2.2.2)
activejob (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
mail (>= 2.8.0)
actionmailer (7.2.2.1)
actionpack (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activesupport (= 7.2.2.1)
actionmailer (7.2.2.2)
actionpack (= 7.2.2.2)
actionview (= 7.2.2.2)
activejob (= 7.2.2.2)
activesupport (= 7.2.2.2)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.2.1)
actionview (= 7.2.2.1)
activesupport (= 7.2.2.1)
actionpack (7.2.2.2)
actionview (= 7.2.2.2)
activesupport (= 7.2.2.2)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.2)
@ -32,39 +32,39 @@ GEM
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.2.1)
actionpack (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
actiontext (7.2.2.2)
actionpack (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.2.1)
activesupport (= 7.2.2.1)
actionview (7.2.2.2)
activesupport (= 7.2.2.2)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (7.2.2.1)
activesupport (= 7.2.2.1)
activejob (7.2.2.2)
activesupport (= 7.2.2.2)
globalid (>= 0.3.6)
activemodel (7.2.2.1)
activesupport (= 7.2.2.1)
activemodel (7.2.2.2)
activesupport (= 7.2.2.2)
activemodel-serializers-xml (1.0.3)
activemodel (>= 5.0.0.a)
activesupport (>= 5.0.0.a)
builder (~> 3.1)
activerecord (7.2.2.1)
activemodel (= 7.2.2.1)
activesupport (= 7.2.2.1)
activerecord (7.2.2.2)
activemodel (= 7.2.2.2)
activesupport (= 7.2.2.2)
timeout (>= 0.4.0)
activestorage (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activesupport (= 7.2.2.1)
activestorage (7.2.2.2)
actionpack (= 7.2.2.2)
activejob (= 7.2.2.2)
activerecord (= 7.2.2.2)
activesupport (= 7.2.2.2)
marcel (~> 1.0)
activesupport (7.2.2.1)
activesupport (7.2.2.2)
base64
benchmark (>= 0.3)
bigdecimal
@ -108,9 +108,9 @@ GEM
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.2.0)
base64 (0.3.0)
bcrypt (3.1.20)
benchmark (0.4.0)
benchmark (0.4.1)
better_html (2.0.2)
actionview (>= 6.0)
activesupport (>= 6.0)
@ -118,7 +118,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.9)
bigdecimal (3.2.2)
bindex (0.8.1)
bootsnap (1.18.3)
msgpack (~> 1.2)
@ -149,7 +149,7 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
connection_pool (2.5.3)
crack (1.0.0)
bigdecimal
rexml
@ -178,7 +178,7 @@ GEM
dotenv-rails (3.0.2)
dotenv (= 3.0.2)
railties (>= 6.1)
drb (2.2.1)
drb (2.2.3)
dumb_delegator (1.0.0)
encryptor (3.0.0)
erb_lint (0.5.0)
@ -260,7 +260,7 @@ GEM
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.6)
logger (1.7.0)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
@ -273,7 +273,7 @@ GEM
matrix (0.4.2)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.25.4)
minitest (5.25.5)
msgpack (1.7.2)
multipart-post (2.4.1)
nested_form (0.3.2)
@ -355,20 +355,20 @@ GEM
rack (>= 1.3)
rackup (2.2.1)
rack (>= 3)
rails (7.2.2.1)
actioncable (= 7.2.2.1)
actionmailbox (= 7.2.2.1)
actionmailer (= 7.2.2.1)
actionpack (= 7.2.2.1)
actiontext (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activemodel (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
rails (7.2.2.2)
actioncable (= 7.2.2.2)
actionmailbox (= 7.2.2.2)
actionmailer (= 7.2.2.2)
actionpack (= 7.2.2.2)
actiontext (= 7.2.2.2)
actionview (= 7.2.2.2)
activejob (= 7.2.2.2)
activemodel (= 7.2.2.2)
activerecord (= 7.2.2.2)
activestorage (= 7.2.2.2)
activesupport (= 7.2.2.2)
bundler (>= 1.15.0)
railties (= 7.2.2.1)
railties (= 7.2.2.2)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
@ -383,9 +383,9 @@ GEM
nested_form (~> 0.3)
rails (>= 6.0, < 9)
turbo-rails (>= 1.0, < 3)
railties (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
railties (7.2.2.2)
actionpack (= 7.2.2.2)
activesupport (= 7.2.2.2)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)

3
app/controllers/form_controller.rb

@ -160,6 +160,9 @@ private
result[option] = 1 if question_params.include?(option)
end
elsif question.type != "date"
if question.strip_commas
question_params = question_params.delete(",")
end
result[question.id] = question_params
end

4
app/helpers/collection_time_helper.rb

@ -42,6 +42,10 @@ module CollectionTimeHelper
current_collection_start_year + 1
end
def next_collection_end_year
next_collection_start_year + 1
end
def previous_collection_start_year
current_collection_start_year - 1
end

1
app/models/form/lettings/questions/brent_4_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::Brent4Weekly < ::Form::Question
@prefix = "£"
@suffix = " every 4 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 95, 2024 => 94, 2025 => 92 }.freeze

1
app/models/form/lettings/questions/brent_bi_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::BrentBiWeekly < ::Form::Question
@prefix = "£"
@suffix = " every 2 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 95, 2024 => 94, 2025 => 92 }.freeze

1
app/models/form/lettings/questions/brent_monthly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::BrentMonthly < ::Form::Question
@prefix = "£"
@suffix = " every month"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 95, 2024 => 94, 2025 => 92 }.freeze

1
app/models/form/lettings/questions/brent_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::BrentWeekly < ::Form::Question
@prefix = "£"
@suffix = " every week"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 95, 2024 => 94, 2025 => 92 }.freeze

1
app/models/form/lettings/questions/chcharge_4_weekly.rb

@ -10,6 +10,7 @@ class Form::Lettings::Questions::Chcharge4Weekly < ::Form::Question
@prefix = "£"
@suffix = " every 4 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 94, 2024 => 93 }.freeze

1
app/models/form/lettings/questions/chcharge_bi_weekly.rb

@ -10,6 +10,7 @@ class Form::Lettings::Questions::ChchargeBiWeekly < ::Form::Question
@prefix = "£"
@suffix = " every 2 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 94, 2024 => 93 }.freeze

1
app/models/form/lettings/questions/chcharge_monthly.rb

@ -10,6 +10,7 @@ class Form::Lettings::Questions::ChchargeMonthly < ::Form::Question
@prefix = "£"
@suffix = " every month"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 94, 2024 => 93 }.freeze

1
app/models/form/lettings/questions/chcharge_weekly.rb

@ -10,6 +10,7 @@ class Form::Lettings::Questions::ChchargeWeekly < ::Form::Question
@prefix = "£"
@suffix = " every week"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 94, 2024 => 93 }.freeze

1
app/models/form/lettings/questions/earnings.rb

@ -16,6 +16,7 @@ class Form::Lettings::Questions::Earnings < ::Form::Question
{ "label" => " every year", "depends_on" => { "incfreq" => 3 } },
]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 88, 2024 => 87 }.freeze

1
app/models/form/lettings/questions/pscharge_4_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::Pscharge4Weekly < ::Form::Question
@prefix = "£"
@suffix = " every 4 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 96, 2025 => 94 }.freeze

1
app/models/form/lettings/questions/pscharge_bi_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::PschargeBiWeekly < ::Form::Question
@prefix = "£"
@suffix = " every 2 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 96, 2025 => 94 }.freeze

1
app/models/form/lettings/questions/pscharge_monthly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::PschargeMonthly < ::Form::Question
@prefix = "£"
@suffix = " every month"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 96, 2025 => 94 }.freeze

1
app/models/form/lettings/questions/pscharge_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::PschargeWeekly < ::Form::Question
@prefix = "£"
@suffix = " every week"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 96, 2025 => 94 }.freeze

1
app/models/form/lettings/questions/scharge_4_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::Scharge4Weekly < ::Form::Question
@prefix = "£"
@suffix = " every 4 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 95, 2025 => 93 }.freeze

1
app/models/form/lettings/questions/scharge_bi_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SchargeBiWeekly < ::Form::Question
@prefix = "£"
@suffix = " every 2 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 95, 2025 => 93 }.freeze

1
app/models/form/lettings/questions/scharge_monthly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SchargeMonthly < ::Form::Question
@prefix = "£"
@suffix = " every month"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 95, 2025 => 93 }.freeze

1
app/models/form/lettings/questions/scharge_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SchargeWeekly < ::Form::Question
@prefix = "£"
@suffix = " every week"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 95, 2025 => 93 }.freeze

1
app/models/form/lettings/questions/supcharg_4_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::Supcharg4Weekly < ::Form::Question
@prefix = "£"
@suffix = " every 4 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 98, 2024 => 97, 2025 => 95 }.freeze

1
app/models/form/lettings/questions/supcharg_bi_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SupchargBiWeekly < ::Form::Question
@prefix = "£"
@suffix = " every 2 weeks"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 98, 2024 => 97, 2025 => 95 }.freeze

1
app/models/form/lettings/questions/supcharg_monthly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SupchargMonthly < ::Form::Question
@prefix = "£"
@suffix = " every month"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 98, 2024 => 97, 2025 => 95 }.freeze

1
app/models/form/lettings/questions/supcharg_weekly.rb

@ -13,6 +13,7 @@ class Form::Lettings::Questions::SupchargWeekly < ::Form::Question
@prefix = "£"
@suffix = " every week"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 98, 2024 => 97, 2025 => 95 }.freeze

1
app/models/form/lettings/questions/tcharge_4_weekly.rb

@ -14,5 +14,6 @@ class Form::Lettings::Questions::Tcharge4Weekly < ::Form::Question
@requires_js = true
@fields_added = %w[brent scharge pscharge supcharg]
@hidden_in_check_answers = true
@strip_commas = true
end
end

1
app/models/form/lettings/questions/tcharge_bi_weekly.rb

@ -14,5 +14,6 @@ class Form::Lettings::Questions::TchargeBiWeekly < ::Form::Question
@requires_js = true
@fields_added = %w[brent scharge pscharge supcharg]
@hidden_in_check_answers = true
@strip_commas = true
end
end

1
app/models/form/lettings/questions/tcharge_monthly.rb

@ -14,5 +14,6 @@ class Form::Lettings::Questions::TchargeMonthly < ::Form::Question
@requires_js = true
@fields_added = %w[brent scharge pscharge supcharg]
@hidden_in_check_answers = true
@strip_commas = true
end
end

1
app/models/form/lettings/questions/tcharge_weekly.rb

@ -14,5 +14,6 @@ class Form::Lettings::Questions::TchargeWeekly < ::Form::Question
@requires_js = true
@fields_added = %w[brent scharge pscharge supcharg]
@hidden_in_check_answers = true
@strip_commas = true
end
end

1
app/models/form/lettings/questions/tshortfall.rb

@ -22,6 +22,7 @@ class Form::Lettings::Questions::Tshortfall < ::Form::Question
{ "label" => " every week for 53 weeks", "depends_on" => { "period" => 10 } },
]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 100, 2024 => 99, 2025 => 97 }.freeze

3
app/models/form/question.rb

@ -8,7 +8,7 @@ class Form::Question
:top_guidance_partial, :bottom_guidance_partial, :prefix, :suffix,
:requires_js, :fields_added, :derived, :check_answers_card_number,
:unresolved_hint_text, :question_number, :hide_question_number_on_page,
:plain_label, :error_label
:plain_label, :error_label, :strip_commas
def initialize(id, hsh, page)
@id = id
@ -45,6 +45,7 @@ class Form::Question
@plain_label = hsh["plain_label"]
@error_label = hsh["error_label"]
@disable_clearing_if_not_routed_or_dynamic_answer_options = hsh["disable_clearing_if_not_routed_or_dynamic_answer_options"]
@strip_commas = hsh["strip_commas"] || false
end
end

1
app/models/form/sales/questions/buyer1_income.rb

@ -11,6 +11,7 @@ class Form::Sales::Questions::Buyer1Income < ::Form::Question
@prefix = "£"
@check_answers_card_number = 1
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 67, 2024 => 69, 2025 => 66 }.freeze

1
app/models/form/sales/questions/buyer2_income.rb

@ -11,6 +11,7 @@ class Form::Sales::Questions::Buyer2Income < ::Form::Question
@prefix = "£"
@check_answers_card_number = 2
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 69, 2024 => 71, 2025 => 68 }.freeze

1
app/models/form/sales/questions/deposit_amount.rb

@ -13,6 +13,7 @@ class Form::Sales::Questions::DepositAmount < ::Form::Question
@optional = optional
@top_guidance_partial = top_guidance_partial
@copy_key = copy_key
@strip_commas = true
end
def derived?(log)

1
app/models/form/sales/questions/deposit_discount.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::DepositDiscount < ::Form::Question
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@top_guidance_partial = "financial_calculations_shared_ownership"
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 97, 2025 => 86 }.freeze

1
app/models/form/sales/questions/grant.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::Grant < ::Form::Question
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@top_guidance_partial = "financial_calculations_discounted_ownership"
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 101, 2024 => 102, 2025 => 104 }.freeze

1
app/models/form/sales/questions/leasehold_charges.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::LeaseholdCharges < ::Form::Question
@copy_key = "sales.sale_information.leaseholdcharges.mscharge"
@ownershipsch = ownershipsch
@question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {

1
app/models/form/sales/questions/management_fee.rb

@ -9,6 +9,7 @@ class Form::Sales::Questions::ManagementFee < ::Form::Question
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 89 }.freeze

1
app/models/form/sales/questions/monthly_rent.rb

@ -8,6 +8,7 @@ class Form::Sales::Questions::MonthlyRent < ::Form::Question
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 98, 2025 => 87 }.freeze

1
app/models/form/sales/questions/monthly_rent_after_staircasing.rb

@ -9,6 +9,7 @@ class Form::Sales::Questions::MonthlyRentAfterStaircasing < ::Form::Question
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 101 }.freeze

1
app/models/form/sales/questions/monthly_rent_before_staircasing.rb

@ -9,6 +9,7 @@ class Form::Sales::Questions::MonthlyRentBeforeStaircasing < ::Form::Question
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 100 }.freeze

1
app/models/form/sales/questions/mortgage_amount.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::MortgageAmount < ::Form::Question
@ownershipsch = ownershipsch
@question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
@top_guidance_partial = top_guidance_partial
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {

1
app/models/form/sales/questions/purchase_price.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::PurchasePrice < ::Form::Question
@ownership_sch = ownershipsch
@question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
@top_guidance_partial = top_guidance_partial
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {

1
app/models/form/sales/questions/savings.rb

@ -9,6 +9,7 @@ class Form::Sales::Questions::Savings < ::Form::Question
@step = 10
@min = 0
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 72, 2024 => 74, 2025 => 71 }.freeze

1
app/models/form/sales/questions/service_charge.rb

@ -9,6 +9,7 @@ class Form::Sales::Questions::ServiceCharge < ::Form::Question
@prefix = "£"
@copy_key = "sales.sale_information.servicecharges.servicecharge"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@strip_commas = true
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 88 }.freeze

1
app/models/form/sales/questions/value.rb

@ -10,6 +10,7 @@ class Form::Sales::Questions::Value < ::Form::Question
@prefix = "£"
@question_number = question_number_from_year[form.start_date.year] || question_number_from_year[question_number_from_year.keys.max]
@top_guidance_partial = "financial_calculations_shared_ownership"
@strip_commas = true
end
def question_number_from_year

2
app/models/validations/soft_validations.rb

@ -6,7 +6,7 @@ module Validations::SoftValidations
2 => OpenStruct.new(soft_min: 67, soft_max: 620, hard_min: 50, hard_max: 950),
3 => OpenStruct.new(soft_min: 80, soft_max: 480, hard_min: 40, hard_max: 990),
4 => OpenStruct.new(soft_min: 50, soft_max: 370, hard_min: 10, hard_max: 450),
5 => OpenStruct.new(soft_min: 50, soft_max: 380, hard_min: 10, hard_max: 690),
5 => OpenStruct.new(soft_min: 50, soft_max: 380, hard_min: 10, hard_max: 1000),
6 => OpenStruct.new(soft_min: 53, soft_max: 540, hard_min: 10, hard_max: 890),
7 => OpenStruct.new(soft_min: 47, soft_max: 460, hard_min: 10, hard_max: 1300),
8 => OpenStruct.new(soft_min: 54, soft_max: 460, hard_min: 10, hard_max: 2000),

2
app/services/merge/merge_organisations_service.rb

@ -26,7 +26,7 @@ class Merge::MergeOrganisationsService
log_success_message
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error("Organisation merge failed with: #{e.message}")
raise
raise ActiveRecord::Rollback
end
end

13
docs/infrastructure.md

@ -57,7 +57,7 @@ Where to find the Infrastructure?
The infrastructure is managed as code.
In the terraform folder of the codebase, there will be dedicated sub-folders for each of the aforementioned environments, where all the infrastructure for them is defined.
## Deployment (Pipeline — Recommended)
## Production Deployment
The application is set up so that it can be deployed via GitHub actions. We use Git tags to mark releases. The only pre-requisite is that your GitHub account is added to our team.
@ -66,12 +66,13 @@ To deploy you need to:
1. Determine [previous version](https://github.com/communitiesuk/submit-social-housing-lettings-and-sales-data/tags), such as `v0.1.1`.
2. Create a [new release](https://github.com/communitiesuk/submit-social-housing-lettings-and-sales-data/releases/new) with subsequent version (e.g., `v0.1.2`). On this page, create a new tag with that version and generate release notes. Save as draft.
3. Post release notes on Slack.
4. Publish release.
5. Monitor alerting, logging and Sentry.
6. Post success message on Slack.
7. Tag tickets as ‘Released’ and move tickets to done on JIRA.
4. Ensure that there are no other pipelines running on the repo right now. If a staging deployment is running, it must complete before you can deploy to production.
5. Publish release. This will trigger the deployment pipeline.
6. Monitor alerting, logging and Sentry.
7. Post success message on Slack.
8. Tag tickets as ‘Released’ and move tickets to done on JIRA.
## CI/CD
## Staging Deployment
When a commit is made to `main` the following GitHub action jobs are triggered:

14
spec/features/sales_log_spec.rb

@ -1,9 +1,12 @@
require "rails_helper"
RSpec.describe "Sales Log Features" do
include CollectionTimeHelper
context "when searching for specific sales logs" do
context "when I am signed in and there are sales logs in the database" do
let(:user) { FactoryBot.create(:user, last_sign_in_at: Time.zone.now, name: "Jimbo") }
let(:current_year) { current_collection_start_year }
let!(:log_to_search) { FactoryBot.create(:sales_log, owning_organisation: user.organisation) }
let!(:same_organisation_log) { FactoryBot.create(:sales_log, owning_organisation: user.organisation) }
let!(:another_organisation_log) { FactoryBot.create(:sales_log) }
@ -161,7 +164,7 @@ RSpec.describe "Sales Log Features" do
expect(page).to have_selector(".govuk-error-summary__title")
expect(page).to have_content("There is a problem")
choose("years-2023-field", allow_label_click: true)
choose("years-#{current_year}-field", allow_label_click: true)
click_button("Save changes")
expect(page).to have_current_path("/sales-logs/csv-download?codes_only=false&search=1")
@ -175,7 +178,7 @@ RSpec.describe "Sales Log Features" do
expect(page).to have_selector(".govuk-error-summary__title")
expect(page).to have_content("There is a problem")
choose("years-2023-field", allow_label_click: true)
choose("years-#{current_year}-field", allow_label_click: true)
click_button("Save changes")
expect(page).to have_current_path("/sales-logs/csv-download?codes_only=true&search=1")
@ -233,6 +236,7 @@ RSpec.describe "Sales Log Features" do
context "when I am signed in" do
let(:user) { create(:user, last_sign_in_at: Time.zone.now) }
let(:current_date) { current_collection_start_date }
before do
create(:sales_log, :in_progress, owning_organisation: user.organisation, assigned_to: user)
@ -242,7 +246,7 @@ RSpec.describe "Sales Log Features" do
end
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)) }
let(:sales_log) { FactoryBot.create(:sales_log, :shared_ownership_setup_complete, jointpur: 2, owning_organisation: user.organisation, assigned_to: user, saledate: current_date) }
context "when visiting the address page" do
before do
@ -250,7 +254,7 @@ RSpec.describe "Sales Log Features" do
end
it "displays the question number in the page header" do
expect(page).to have_content("Q16")
expect(page).to have_content("Q14")
end
end
@ -260,7 +264,7 @@ RSpec.describe "Sales Log Features" do
end
it "has the expected content" do
expect(page).to have_content(/Shared ownership scheme\s*About the staircasing transaction/)
expect(page).to have_content(/Shared ownership - staircasing transaction\s*About the staircasing transaction/)
end
end
end

8
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, saledate: Time.zone.local(2024, 5, 3)) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 2, staircase: 2) }
it "returns an empty string if question is not routed to" do
expect(question_link("mortgage", log, log.assigned_to)).to eq("")
@ -11,10 +11,10 @@ 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, saledate: Time.zone.local(2024, 5, 3)) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 1, staircase: 2) }
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>)")
it "returns a link to the question with correct question number in brackets" do
expect(question_link("mortgage", log, log.assigned_to)).to eq("(<a class=\"govuk-link\" href=\"/sales-logs/#{log.id}/mortgage-amount-shared-ownership\">Q83</a>)")
end
end
end

2
spec/helpers/merge_requests_helper_spec.rb

@ -165,7 +165,7 @@ RSpec.describe MergeRequestsHelper do
let(:organisation) { create(:organisation, name: "Org 1") }
let(:merging_organisation) { create(:organisation, name: "Org 2") }
let(:merging_organisation_2) { create(:organisation, name: "Org 3") }
let(:merge_date) { Time.zone.local(2025, 1, 1) }
let(:merge_date) { current_collection_start_date }
let(:merge_request) { create(:merge_request, absorbing_organisation: organisation, merge_date:) }
before do

11
spec/lib/tasks/recalculate_invalid_reasonpref_dontknow_spec.rb

@ -2,22 +2,29 @@ require "rails_helper"
require "rake"
RSpec.describe "recalculate_invalid_reasonpref_dontknow" do
include CollectionTimeHelper
subject(:task) { Rake::Task["recalculate_invalid_rpdontknow"] }
before do
Rake.application.rake_require("tasks/recalculate_invalid_reasonpref_dontknow")
Rake::Task.define_task(:environment)
task.reenable
Timecop.freeze(previous_collection_end_date)
end
after do
Timecop.return
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), startdate: Time.zone.local(2024, rand(4..12), rand(1..30))) }
let(:invalid_logs) { create_list(:lettings_log, 5, :completed, :ignore_validation_errors, 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), startdate: Time.zone.local(2024, rand(4..12), rand(1..30))) }
let(:valid_logs) { create_list(:lettings_log, 3, :completed, :ignore_validation_errors, 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|

7
spec/lib/tasks/update_manual_address_entry_selected_prexisting_logs_spec.rb

@ -2,10 +2,17 @@ require "rails_helper"
require "rake"
RSpec.describe "update_manual_address_entry_selected_preexisting_logs_spec", type: :task do
include CollectionTimeHelper
before do
Rake.application.rake_require("tasks/update_manual_address_entry_selected_prexisting_logs")
Rake::Task.define_task(:environment)
task.reenable
Timecop.freeze(previous_collection_end_date)
end
after do
Timecop.return
end
describe "bulk_update:update_manual_address_entry_selected" do

2
spec/models/lettings_log_derived_fields_spec.rb

@ -385,7 +385,7 @@ RSpec.describe LettingsLog, type: :model do
{
test_title: "correctly derives floats and weekly total charge",
fields_to_set: { supcharg: 100.12, pscharge: 100.13, scharge: 100.98, brent: 100.97 },
expected_values: { wsupchrg: 25.03, wpschrge: 25.03, wscharge: 25.24, wrent: 25.24, wtcharge: 100.55 },
expected_values: { wsupchrg: 25.03, wpschrge: 25.03, wscharge: 25.25, wrent: 25.24, wtcharge: 100.55 },
},
{
test_title: "correctly derives weekly care home charge when the letting is supported housing",

6
spec/models/log_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Log, type: :model do
include CollectionTimeHelper
it "has two child log classes" do
expect(SalesLog).to be < described_class
expect(LettingsLog).to be < described_class
@ -62,12 +64,12 @@ RSpec.describe Log, type: :model do
end
context "when a non setup field is invalid for a lettings log" do
subject(:model) { build_stubbed(:lettings_log, :completed, startdate: Time.zone.local(2023, 12, 12), offered: 234) }
subject(:model) { build_stubbed(:lettings_log, :completed, startdate: current_collection_start_date, age1: 234) }
it "blanks it" do
model.valid?
model.blank_invalid_non_setup_fields!
expect(model.offered).to be_nil
expect(model.age1).to be_nil
end
end

92
spec/models/sales_log_spec.rb

@ -7,6 +7,7 @@ RSpec.describe SalesLog, type: :model do
let(:owning_organisation) { create(:organisation) }
let(:assigned_to_user) { create(:user) }
let(:current_date) { current_collection_start_date }
include_examples "shared log examples", :sales_log
@ -559,67 +560,8 @@ RSpec.describe SalesLog, type: :model do
expect(record_from_db["la"]).to eq("E08000003")
end
context "with 24/25 logs" do
let(:address_sales_log_24_25) do
described_class.create({
owning_organisation:,
assigned_to: assigned_to_user,
ppcodenk: 1,
postcode_full: "CA10 1AA",
ppostcode_full: nil,
prevloc: nil,
saledate: Time.zone.local(2024, 5, 2),
manual_address_entry_selected: true,
})
end
before do
WebMock.stub_request(:get, /api\.postcodes\.io\/postcodes\/CA101AA/)
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Eden","codes":{"admin_district":"E06000064"}}}', headers: {})
end
it "sets previous postcode for discounted sale" do
address_sales_log_24_25.update!(ownershipsch: 2, ppostcode_full: nil)
record_from_db = described_class.find(address_sales_log_24_25.id)
expect(address_sales_log_24_25.ppostcode_full).to eq("CA10 1AA")
expect(record_from_db["ppostcode_full"]).to eq("CA10 1AA")
expect(record_from_db["prevloc"]).to eq("E06000064")
end
it "does not set previous postcode for non discounted sale" do
address_sales_log_24_25.update!(ownershipsch: 1, ppostcode_full: nil)
record_from_db = described_class.find(address_sales_log_24_25.id)
expect(address_sales_log_24_25.ppostcode_full).to eq(nil)
expect(record_from_db["ppostcode_full"]).to eq(nil)
expect(record_from_db["prevloc"]).to eq(nil)
end
context "when validating household members derived vars" do
let!(:household_sales_log) do
create(
:sales_log,
:completed,
managing_organisation: owning_organisation,
owning_organisation:,
assigned_to: assigned_to_user,
age6: 14,
saledate: Time.zone.local(2024, 5, 2),
)
end
it "correctly derives economic status for tenants under 16" do
record_from_db = described_class.find(household_sales_log.id)
expect(record_from_db["ecstat6"]).to eq(9)
end
end
end
context "when saving address with LAs that have changed E-codes (LA inferred from postcode)" do
context "when LA is inferred from postcode" do
let(:address_sales_log_24_25) do
create(:sales_log, :shared_ownership_setup_complete, uprn_known: 0, uprn: nil, postcode_full: "CA10 1AA", saledate: Time.zone.local(2024, 5, 2))
end
let(:address_sales_log_25_26) do
create(:sales_log, :shared_ownership_setup_complete, postcode_full: "CA10 1AA", saledate: Time.zone.local(2025, 5, 2), manual_address_entry_selected: true)
end
@ -639,12 +581,6 @@ RSpec.describe SalesLog, type: :model do
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Barnsley","codes":{"admin_district":"E08000016"}}}', headers: {})
end
context "with 2024 log" do
it "keeps 2024 E-code" do
expect(address_sales_log_24_25.la).to eq("E08000016")
end
end
context "with 2025 log" do
it "uses new 2025 E-code if" do
expect(address_sales_log_25_26.la).to eq("E08000038")
@ -658,12 +594,6 @@ RSpec.describe SalesLog, type: :model do
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Barnsley","codes":{"admin_district":"E08000038"}}}', headers: {})
end
context "with 2024 log" do
it "uses 2024 E-code" do
expect(address_sales_log_24_25.la).to eq("E08000016")
end
end
context "with 2025 log" do
it "keeps 2025 E-code if new(2025) E-code gets returned" do
expect(address_sales_log_25_26.la).to eq("E08000038")
@ -675,10 +605,6 @@ RSpec.describe SalesLog, type: :model do
context "when saving address with LAs that have changed E-codes" do
context "when address inferred from uprn - we still get LA from postcode" do
let(:address_sales_log_24_25) do
create(:sales_log, :shared_ownership_setup_complete, manual_address_entry_selected: false, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2024, 5, 2))
end
let(:address_sales_log_25_26) do
create(:sales_log, :shared_ownership_setup_complete, manual_address_entry_selected: false, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2025, 5, 2))
end
@ -698,12 +624,6 @@ RSpec.describe SalesLog, type: :model do
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Barnsley","codes":{"admin_district":"E08000016"}}}', headers: {})
end
context "with 2024 log" do
it "keeps 2024 E-code" do
expect(address_sales_log_24_25.la).to eq("E08000016")
end
end
context "with 2025 log" do
it "uses new 2025 E-code if" do
expect(address_sales_log_25_26.la).to eq("E08000038")
@ -717,12 +637,6 @@ RSpec.describe SalesLog, type: :model do
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Barnsley","codes":{"admin_district":"E08000038"}}}', headers: {})
end
context "with 2024 log" do
it "uses 2024 E-code" do # currently returns nil
expect(address_sales_log_24_25.la).to eq("E08000016")
end
end
context "with 2025 log" do
it "keeps 2025 E-code if new(2025) E-code gets returned" do
expect(address_sales_log_25_26.la).to eq("E08000038")
@ -1088,8 +1002,8 @@ RSpec.describe SalesLog, type: :model do
context "when form year changes and LA is no longer active" do
let!(:sales_log) { create(:sales_log) }
let(:end_date) { Time.zone.local(2025, 3, 30) }
let(:date_after_end_date) { Time.zone.local(2025, 3, 31) }
let(:end_date) { current_date }
let(:date_after_end_date) { current_date + 1.day }
before do
LocalAuthority.find_by(code: "E08000003").update!(end_date:)

2
spec/models/scheme_spec.rb

@ -472,7 +472,7 @@ RSpec.describe Scheme, type: :model do
context "when the most recently created deactivation is not the current one" do
before do
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.today - 300.days, reactivation_date: Time.zone.today - 200.days, scheme:)
FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.today - 5.days, reactivation_date: Time.zone.today - 4.days, scheme:)
end
it "returns reactivating_soon" do

4
spec/models/validations/date_validations_spec.rb

@ -56,7 +56,7 @@ RSpec.describe Validations::DateValidations do
context "with 2024 logs or earlier" do
it "cannot be more than 10 years before the tenancy start date" do
record.startdate = Time.zone.local(2024, 2, 1)
record.startdate = Time.zone.local(2024, 4, 1)
record.mrcdate = Time.zone.local(2014, 1, 31)
date_validator.validate_property_major_repairs(record)
expect(record.errors["mrcdate"])
@ -150,7 +150,7 @@ RSpec.describe Validations::DateValidations do
context "with 2024 logs or earlier" do
it "cannot be more than 10 years before the tenancy start date" do
record.startdate = Time.zone.local(2024, 2, 1)
record.startdate = Time.zone.local(2024, 4, 1)
record.voiddate = Time.zone.local(2014, 1, 31)
date_validator.validate_property_void_date(record)
expect(record.errors["voiddate"])

2
spec/models/validations/financial_validations_spec.rb

@ -877,7 +877,7 @@ RSpec.describe Validations::FinancialValidations do
context "when period is every 2 weeks" do
it "validates that total charge is at least 10 per week" do
record.period = 2
record.tcharge = 19.99
record.tcharge = 19.98
financial_validator.validate_rent_amount(record)
expect(record.errors["tcharge"])
.to include(match I18n.t("validations.lettings.financial.tcharge.under_10"))

164
spec/models/validations/household_validations_spec.rb

@ -50,17 +50,6 @@ RSpec.describe Validations::HouseholdValidations do
expect(record.errors["reasonother"]).to be_empty
end
context "when form year is before 2024" do
let(:startdate) { Time.zone.local(2024, 1, 1) }
it "does not validate the content of reasonother for phrases indicating homelessness" do
record.reason = 20
record.reasonother = "Temp accommodation"
household_validator.validate_reason_for_leaving_last_settled_home(record)
expect(record.errors["reason"]).to be_empty
end
end
context "when form year is >= 2024" do
let(:startdate) { Time.zone.local(2024, 4, 1) }
@ -273,53 +262,7 @@ RSpec.describe Validations::HouseholdValidations do
end
end
describe "#validate_partner_count" do
let(:startdate) { Time.zone.local(2023, 4, 1) }
it "validates that only 1 partner exists" do
record.relat2 = "P"
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat3"])
.to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat4"])
.not_to include(match I18n.t("validations.lettings.household.relat.one_partner"))
end
it "expects that a tenant can have a partner" do
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["base"]).to be_empty
end
end
describe "#validate_person_age_matches_relationship" do
context "with 2023 logs" do
let(:startdate) { Time.zone.local(2023, 4, 1) }
context "when the household contains a person under 16" do
it "validates that person must be a child of the tenant" do
record.age2 = 14
record.relat2 = "P"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.lettings.household.relat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.lettings.household.age.child_under_16_relat", person_num: 2))
end
it "expects that person is a child of the tenant" do
record.age2 = 14
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
end
end
context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) }
@ -342,41 +285,6 @@ RSpec.describe Validations::HouseholdValidations do
end
describe "#validate_person_age_matches_economic_status" do
context "with 2023 logs" do
let(:startdate) { Time.zone.local(2023, 4, 1) }
context "when the household contains a person under 16" do
it "validates that person's economic status must be Child" do
record.age2 = 14
record.ecstat2 = 1
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.lettings.household.ecstat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.lettings.household.age.child_under_16_ecstat", person_num: 2))
end
it "expects that person's economic status is Child" do
record.age2 = 14
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "validates that a person with economic status 'child' must be under 16" do
record.age2 = 21
record.relat2 = "C"
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.lettings.household.ecstat.child_over_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.lettings.household.age.child_over_16", person_num: 2))
end
end
end
context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) }
@ -393,78 +301,6 @@ RSpec.describe Validations::HouseholdValidations do
end
describe "#validate_person_age_and_relationship_matches_economic_status" do
context "with 2023 logs" do
let(:startdate) { Time.zone.local(2023, 4, 1) }
context "when the household contains a tenant’s child between the ages of 16 and 19" do
it "validates that person's economic status must be full time student or refused" do
record.age2 = 17
record.relat2 = "C"
record.ecstat2 = 1
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.lettings.household.ecstat.student_16_19.must_be_student", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.lettings.household.age.student_16_19.cannot_be_16_19.child_not_student", person_num: 2))
expect(record.errors["relat2"])
.to include(match I18n.t("validations.lettings.household.relat.student_16_19.cannot_be_child.16_19_not_student", person_num: 2))
end
it "expects that person can be a full time student" do
record.age2 = 17
record.relat2 = "C"
record.ecstat2 = 7
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
it "expects that person can refuse to share their work status" do
record.age2 = 17
record.relat2 = "C"
record.ecstat2 = 10
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
end
it "does not add an error for a person aged 16-19 who is a student but not a child of the lead tenant" do
record.age2 = 18
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add an error for a person not aged 16-19 who is a student but not a child of the lead tenant" do
record.age2 = 20
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "adds errors for a person who is a child of the lead tenant and a student but not aged 16-19" do
record.age2 = 14
record.ecstat2 = "7"
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.lettings.household.relat.student_16_19.cannot_be_child.student_not_16_19"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.lettings.household.age.student_16_19.must_be_16_19"))
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.lettings.household.ecstat.student_16_19.cannot_be_student.child_not_16_19"))
end
end
context "with 2024 logs" do
let(:startdate) { Time.zone.local(2024, 4, 1) }

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

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Validations::Sales::FinancialValidations do
include CollectionTimeHelper
subject(:financial_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } }
@ -208,47 +210,28 @@ RSpec.describe Validations::Sales::FinancialValidations do
end
describe "#validate_percentage_bought_not_equal_percentage_owned" do
let(:record) { FactoryBot.build(:sales_log) }
context "with 24/25 logs" do
before do
record.saledate = Time.zone.local(2024, 4, 3)
end
it "does not add an error if the percentage bought is less than the percentage owned" do
record.stairbought = 20
record.stairowned = 40
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors).to be_empty
end
it "adds an error if the percentage bought is equal to the percentage owned" do
record.stairbought = 30
record.stairowned = 30
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors["stairowned"]).to eq([I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
end
let(:record) { FactoryBot.build(:sales_log, :saledate_today) }
it "does not add an error to stairowned and not stairbought if the percentage bought is more than the percentage owned" do
record.stairbought = 50
record.stairowned = 40
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors).to be_empty
end
it "does not add an error if the percentage bought is less than the percentage owned" do
record.stairbought = 20
record.stairowned = 40
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors).to be_empty
end
context "with 23/24 logs" do
before do
record.saledate = Time.zone.local(2023, 4, 3)
end
it "adds an error if the percentage bought is equal to the percentage owned" do
record.stairbought = 30
record.stairowned = 30
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors["stairowned"]).to eq([I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
end
it "does not add an error if the percentage bought is equal to the percentage owned" do
record.stairbought = 30
record.stairowned = 30
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors).to be_empty
end
it "does not add an error to stairowned and not stairbought if the percentage bought is more than the percentage owned" do
record.stairbought = 50
record.stairowned = 40
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors).to be_empty
end
end
@ -348,195 +331,151 @@ RSpec.describe Validations::Sales::FinancialValidations do
describe "#validate_equity_in_range_for_year_and_type" do
let(:record) { FactoryBot.build(:sales_log, saledate:, resale: nil) }
context "with a log in the 22/23 collection year" do
let(:saledate) { Time.zone.local(2023, 1, 1) }
it "adds an error for type 2, equity below min with the correct percentage" do
record.type = 2
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
it "adds an error for type 30, equity below min with the correct percentage" do
record.type = 30
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10))
end
it "does not add an error for equity in range with the correct percentage" do
record.type = 2
record.equity = 50
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
it "adds an error for equity above max with the correct percentage" do
record.type = 2
record.equity = 90
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75))
end
let(:saledate) { current_collection_start_date }
it "does not add an error if it's a resale" do
record.type = 2
record.equity = 90
record.resale = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
it "adds an error for type 2, equity below min with the correct percentage" do
record.type = 2
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
context "with a log in 23/24 collection year" do
let(:saledate) { Time.zone.local(2024, 1, 1) }
it "adds an error for type 30, equity below min with the correct percentage" do
record.type = 30
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10))
end
it "adds an error for type 2, equity below min with the correct percentage" do
record.type = 2
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
it "adds an error for type 18, low equity below min with the correct percentage" do
record.type = 18
record.equity = 10
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
it "adds an error for type 30, equity below min with the correct percentage" do
record.type = 30
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10))
end
it "does not add an error for type 30, low equity in range with the correct percentage" do
record.type = 30
record.equity = 10
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
it "does not add an error for equity in range with the correct percentage" do
record.type = 2
record.equity = 50
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
it "does not add an error for equity in range with the correct percentage" do
record.type = 2
record.equity = 50
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
it "adds an error for equity above max with the correct percentage" do
record.type = 2
record.equity = 90
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75))
end
it "adds an error for equity above max with the correct percentage" do
record.type = 2
record.equity = 90
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75))
end
end
describe "#validate_staircase_difference" do
let(:record) { FactoryBot.build(:sales_log, saledate:) }
context "with a log in the 23/24 collection year" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
let(:saledate) { current_collection_start_date }
it "does not add an error" do
record.stairbought = 2
record.stairowned = 3
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "adds errors if equity is more than stairowned - stairbought for joint purchase" do
record.stairbought = 2.5
record.stairowned = 3
record.equity = 2
record.jointpur = 1
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))
end
context "with a log in 24/25 collection year" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
it "adds errors if equity is more than stairowned - stairbought for joint purchase" do
record.stairbought = 2.5
record.stairowned = 3
record.equity = 2
record.jointpur = 1
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))
end
it "adds errors if equity is more than stairowned - stairbought for non joint purchase" do
record.stairbought = 2
record.stairowned = 3
record.equity = 2.5
record.jointpur = 2
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 "adds errors if equity is more than stairowned - stairbought for non joint purchase" do
record.stairbought = 2
record.stairowned = 3
record.equity = 2.5
record.jointpur = 2
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 and stairnum is nil" do
record.stairbought = 2
record.stairowned = 10
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
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_staircase_difference(record)
expect(record.errors).to be_empty
end
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_staircase_difference(record)
expect(record.errors).to be_empty
end
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_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if stairbought is not given" do
record.stairbought = nil
record.stairowned = 10
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if stairbought is not given" do
record.stairbought = nil
record.stairowned = 10
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if stairowned is not given" do
record.stairbought = 2
record.stairowned = nil
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if stairowned is not given" do
record.stairbought = 2
record.stairowned = nil
record.equity = 2
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if equity is not given" do
record.stairbought = 2
record.stairowned = 10
record.equity = 0
financial_validator.validate_staircase_difference(record)
expect(record.errors).to be_empty
end
it "does not add errors if equity is not given" do
record.stairbought = 2
record.stairowned = 10
record.equity = 0
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.stairowned.less_than_stairbought_plus_equity_plus_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.stairbought.more_than_stairowned_minus_equity_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.numstair.too_high_for_stairowned_minus_stairbought_minus_equity", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
expect(record.errors["firststair"]).to include(I18n.t("validations.sales.financial.firststair.invalid_for_stairowned_minus_stairbought_minus_equity", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
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.stairowned.less_than_stairbought_plus_equity_plus_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.stairbought.more_than_stairowned_minus_equity_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.numstair.too_high_for_stairowned_minus_stairbought_minus_equity", equity: 9, bought: 10, numprevstair: 2, equity_sum: 21, stair_total: 20))
expect(record.errors["firststair"]).to include(I18n.t("validations.sales.financial.firststair.invalid_for_stairowned_minus_stairbought_minus_equity", 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 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
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
end

389
spec/models/validations/sales/household_validations_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Validations::Sales::HouseholdValidations do
include CollectionTimeHelper
subject(:household_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::Sales::HouseholdValidations } }
@ -8,272 +10,112 @@ RSpec.describe Validations::Sales::HouseholdValidations do
let(:saledate) { Time.zone.now }
describe "#validate_partner_count" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
let(:saledate) { current_collection_start_date }
it "validates that only 1 partner exists" do
it "does not validate for years >= 2024" do
record.relat2 = "P"
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.relat.one_partner"))
expect(record.errors["relat3"])
.to include(match I18n.t("validations.sales.household.relat.one_partner"))
expect(record.errors["relat4"])
.not_to include(match I18n.t("validations.sales.household.relat.one_partner"))
end
it "expects that a tenant can have a partner" do
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["base"]).to be_empty
expect(record.errors["relat2"]).to be_empty
expect(record.errors["relat3"]).to be_empty
expect(record.errors["relat4"]).to be_empty
end
end
describe "#validate_person_age_matches_relationship" do
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
context "when the household contains a person under 16" do
it "expects that person is a child of the tenant" do
record.age2 = 14
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
let(:saledate) { current_collection_start_date }
it "validates that a person under 16 must not be a partner of the buyer" do
record.age2 = 14
record.relat2 = "P"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.relat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_under_16", person_num: 2))
end
end
it "validates that a person over 20 must not be a child of the buyer" do
record.age2 = 21
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.relat.child_over_20"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_over_20"))
end
it "does not add error if person under 16 is a partner" do
record.age2 = 14
record.relat2 = "P"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
context "with 2024 logs" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
it "does not add error if person under 16 is a partner" do
record.age2 = 14
record.relat2 = "P"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add error if person over 19 is a child" do
record.age2 = 20
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
it "does not add error if person over 19 is a child" do
record.age2 = 20
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
end
describe "#validate_person_age_matches_economic_status" do
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
let(:saledate) { current_collection_start_date }
it "validates that person's economic status must be Child" do
record.age2 = 14
record.ecstat2 = 1
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.sales.household.ecstat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_under_16_ecstat", person_num: 2))
end
it "expects that person's economic status is Child" do
record.age2 = 14
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "validates that a person with economic status 'child' must be under 16" do
record.age2 = 21
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.sales.household.ecstat.child_over_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_over_16", person_num: 2))
end
end
context "with 2024 logs" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
it "does not run the validation" do
record.age2 = 14
record.ecstat2 = 1
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.not_to include(match I18n.t("validations.sales.household.ecstat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.not_to include(match I18n.t("validations.sales.household.age.child_under_16_ecstat", person_num: 2))
end
it "validates that a person with economic status 'child' must be under 16" do
record.age2 = 21
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.sales.household.ecstat.child_over_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_over_16", person_num: 2))
end
end
describe "#validate_child_12_years_younger" do
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
it "validates the child is at least 12 years younger than buyer 1" do
record.age1 = 30
record.age2 = record.age1 - 11
record.relat2 = "C"
household_validator.validate_child_12_years_younger(record)
expect(record.errors["age1"])
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
end
it "expects the child is at least 12 years younger than buyer 1" do
record.age1 = 30
record.age2 = record.age1 - 12
record.relat2 = "C"
household_validator.validate_child_12_years_younger(record)
expect(record.errors["age1"]).to be_empty
expect(record.errors["age2"]).to be_empty
expect(record.errors["relate2"]).to be_empty
end
end
context "with 2024 logs" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
let(:saledate) { current_collection_start_date }
it "does not validate that child is at least 12 year younger than buyer" do
record.age1 = 20
record.age2 = 17
record.relat2 = "C"
household_validator.validate_child_12_years_younger(record)
expect(record.errors["age1"]).to be_empty
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
it "does not validate that child is at least 12 year younger than buyer" do
record.age1 = 20
record.age2 = 17
record.relat2 = "C"
household_validator.validate_child_12_years_younger(record)
expect(record.errors["age1"]).to be_empty
expect(record.errors["age2"]).to be_empty
expect(record.errors["relat2"]).to be_empty
end
end
describe "#validate_person_age_and_relationship_matches_economic_status" do
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
let(:saledate) { current_collection_start_date }
it "does not add an error for a person aged 16-19 who is a student but not a child of the buyer" do
record.age2 = 18
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add an error for a person not aged 16-19 who is a student but not a child of the buyer" do
record.age2 = 20
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "adds errors for a person aged 16-19 who is a child of the buyer but not a student" do
context "when the household contains a tenant’s child between the ages of 16 and 19" do
it "does not add an error" do
record.age2 = 17
record.ecstat2 = "1"
record.relat2 = "C"
record.ecstat2 = 1
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.16_19_not_student"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.student_16_19.cannot_be_16_19.child_not_student"))
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.sales.household.ecstat.student_16_19.must_be_student"))
end
it "adds errors for a person who is a child of the buyer and a student but not aged 16-19" do
record.age2 = 14
record.ecstat2 = "7"
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.student_not_16_19"))
.to be_empty
expect(record.errors["age2"])
.to include(match I18n.t("validations.sales.household.age.student_16_19.must_be_16_19"))
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.sales.household.ecstat.student_16_19.cannot_be_student.child_not_16_19"))
.to be_empty
expect(record.errors["relat2"])
.to be_empty
end
end
context "with 2024 logs" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
context "when the household contains a tenant’s child between the ages of 16 and 19" do
it "does not add an error" do
record.age2 = 17
record.relat2 = "C"
record.ecstat2 = 1
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to be_empty
expect(record.errors["age2"])
.to be_empty
expect(record.errors["relat2"])
.to be_empty
end
end
it "does not add an error for a person not aged 16-19 who is a student but not a child of the buyer" do
record.age2 = 20
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add errors" do
record.age2 = 14
record.ecstat2 = "7"
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add errors for a person who is a student and aged 16-19 but not child" do
record.age2 = 17
record.ecstat2 = "7"
record.relat2 = "X"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add an error for a person not aged 16-19 who is a student but not a child of the buyer" do
record.age2 = 20
record.ecstat2 = "7"
record.relat2 = "P"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add errors" do
record.age2 = 14
record.ecstat2 = "7"
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
it "does not add errors for a person who is a student and aged 16-19 but not child" do
record.age2 = 17
record.ecstat2 = "7"
record.relat2 = "X"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
expect(record.errors["age2"]).to be_empty
end
end
@ -310,16 +152,12 @@ RSpec.describe Validations::Sales::HouseholdValidations do
expect(sales_log.errors).to be_empty
end
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
it "triggers a validation if buyer two will also not live in the property" do
sales_log.buy2livein = 2
household_validator.validate_buyers_living_in_property(sales_log)
expect(sales_log.errors[:buylivein]).to include I18n.t("validations.sales.household.buylivein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy2livein]).to include I18n.t("validations.sales.household.buy2livein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy1livein]).to include I18n.t("validations.sales.household.buy1livein.buyers_will_live_in_property_values_inconsistent")
end
it "triggers a validation if buyer two will also not live in the property" do
sales_log.buy2livein = 2
household_validator.validate_buyers_living_in_property(sales_log)
expect(sales_log.errors[:buylivein]).to include I18n.t("validations.sales.household.buylivein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy2livein]).to include I18n.t("validations.sales.household.buy2livein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy1livein]).to include I18n.t("validations.sales.household.buy1livein.buyers_will_live_in_property_values_inconsistent")
end
end
@ -383,60 +221,31 @@ RSpec.describe Validations::Sales::HouseholdValidations do
expect(record.errors).to be_empty
end
end
context "with 23/24 logs" do
let(:saledate) { Time.zone.local(2023, 4, 4) }
it "does not add an error for outright sale" do
record.ownershipsch = 2
[1, 2, 3, 4, 5, 6, 7, 9, 0].each do |prevten|
record.prevten = prevten
household_validator.validate_buyer1_previous_tenure(record)
expect(record.errors).to be_empty
end
end
end
end
describe "#validate_buyer_not_child" do
context "with 2023 logs" do
let(:saledate) { Time.zone.local(2023, 4, 1) }
it "does not add an error if either buyer is a child" do
record.jointpur = 1
record.ecstat1 = 9
record.ecstat2 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat1"]).to be_empty
expect(record.errors["ecstat2"]).to be_empty
end
end
context "with 2024 logs" do
let(:saledate) { Time.zone.local(2024, 4, 1) }
let(:saledate) { current_collection_start_date }
it "validates buyer 1 isn't a child" do
record.ecstat1 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat1"])
.to include("Buyer 1 cannot have a working situation of child under 16.")
end
it "validates buyer 1 isn't a child" do
record.ecstat1 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat1"])
.to include("Buyer 1 cannot have a working situation of child under 16.")
end
it "validates buyer 2 isn't a child" do
record.jointpur = 1
record.ecstat2 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat2"])
.to include("Buyer 2 cannot have a working situation of child under 16.")
end
it "validates buyer 2 isn't a child" do
record.jointpur = 1
record.ecstat2 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat2"])
.to include("Buyer 2 cannot have a working situation of child under 16.")
end
it "allows person 2 to be a child" do
record.jointpur = 2
record.ecstat2 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat2"]).to be_empty
end
it "allows person 2 to be a child" do
record.jointpur = 2
record.ecstat2 = 9
household_validator.validate_buyer_not_child(record)
expect(record.errors["ecstat2"]).to be_empty
end
end
end

75
spec/models/validations/sales/property_validations_spec.rb

@ -1,80 +1,21 @@
require "rails_helper"
RSpec.describe Validations::Sales::PropertyValidations do
include CollectionTimeHelper
subject(:property_validator) { property_validator_class.new }
let(:property_validator_class) { Class.new { include Validations::Sales::PropertyValidations } }
describe "#validate_postcodes_match_if_discounted_ownership" do
context "when ownership scheme is not discounted ownership" do
let(:record) { build(:sales_log, ownershipsch: 1) }
it "when postcodes match no error is added" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 1AA"
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
end
end
context "when ownership scheme is discounted ownership" do
let(:record) { build(:sales_log, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 5)) }
it "when ppostcode_full is not present no error is added" do
record.postcode_full = "SW1A 1AA"
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
expect(record.errors["ppostcode_full"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
end
let(:record) { build(:sales_log, ownershipsch: 1, saledate: current_collection_start_date) }
it "when postcode_full is not present no error is added" do
record.ppostcode_full = "SW1A 1AA"
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
expect(record.errors["ppostcode_full"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
end
it "when postcodes match no error is added" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 1AA"
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
expect(record.errors["ppostcode_full"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
end
it "when postcodes do not match an error is added for joint purchase" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 0AA"
record.jointpur = 1
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to include("Buyers’ last accommodation and discounted ownership postcodes must match.")
expect(record.errors["ppostcode_full"]).to include("Buyers’ last accommodation and discounted ownership postcodes must match.")
expect(record.errors["ownershipsch"]).to include("Buyers’ last accommodation and discounted ownership postcodes must match.")
end
it "when postcodes do not match an error is added for non joint purchase" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 0AA"
record.jointpur = 2
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to include("Buyer’s last accommodation and discounted ownership postcodes must match.")
expect(record.errors["ppostcode_full"]).to include("Buyer’s last accommodation and discounted ownership postcodes must match.")
expect(record.errors["ownershipsch"]).to include("Buyer’s last accommodation and discounted ownership postcodes must match.")
end
it "is not validated for years >= 2024" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 0AA"
it "does not add error for 2024 log" do
record.postcode_full = "SW1A 1AA"
record.ppostcode_full = "SW1A 0AA"
record.saledate = Time.zone.local(2024, 4, 5)
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
expect(record.errors["ppostcode_full"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
end
property_validator.validate_postcodes_match_if_discounted_ownership(record)
expect(record.errors["postcode_full"]).to be_empty
end
end

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

File diff suppressed because it is too large Load Diff

93
spec/models/validations/sales/soft_validations_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Validations::Sales::SoftValidations do
include CollectionTimeHelper
let(:record) { build(:sales_log) }
describe "income validations" do
@ -404,87 +406,16 @@ RSpec.describe Validations::Sales::SoftValidations do
end
context "when validating extra borrowing" do
context "when the log is for 2023" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2023, 12, 1)) }
it "returns false if extrabor not present" do
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns false if mortgage not present" do
record.extrabor = 2
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns false if deposit not present" do
record.extrabor = 2
record.mortgage = 50_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns false if value not present" do
record.extrabor = 2
record.mortgage = 50_000
record.deposit = 40_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns false if discount not present" do
record.extrabor = 2
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns false if extra borrowing expected and reported" do
record.extrabor = 1
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
it "returns true if extra borrowing expected but not reported" do
record.extrabor = 2
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.to be_extra_borrowing_expected_but_not_reported
end
end
context "when the log is for 2024" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 12, 1)) }
it "returns false for logs from 2024 onwards" do
record.extrabor = 2
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
let(:record) { build(:sales_log, saledate: previous_collection_start_date) }
it "returns false for logs from 2024 onwards" do
record.extrabor = 2
record.mortgage = 50_000
record.deposit = 40_000
record.value = 100_000
record.discount = 11
expect(record)
.not_to be_extra_borrowing_expected_but_not_reported
end
end
end

98
spec/requests/collection_resources_controller_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe CollectionResourcesController, type: :request do
include CollectionTimeHelper
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:storage_service) { instance_double(Storage::S3Service, get_file_metadata: nil, delete_file: nil) }
@ -56,10 +58,10 @@ RSpec.describe CollectionResourcesController, type: :request do
it "displays collection resources" do
get collection_resources_path
expect(page).to have_content("Lettings 2024 to 2025")
expect(page).to have_content("Lettings 2025 to 2026")
expect(page).to have_content("Sales 2024 to 2025")
expect(page).to have_content("Sales 2025 to 2026")
expect(page).to have_content("Lettings #{next_collection_start_year} to #{next_collection_end_year}")
expect(page).to have_content("Lettings #{current_collection_start_year} to #{current_collection_end_year}")
expect(page).to have_content("Sales #{next_collection_start_year} to #{next_collection_end_year}")
expect(page).to have_content("Sales #{current_collection_start_year} to #{current_collection_end_year}")
end
it "displays mandatory files" do
@ -73,10 +75,10 @@ RSpec.describe CollectionResourcesController, type: :request do
it "allows uploading new resources" do
get collection_resources_path
expect(page).to have_link("Add new sales 2024 to 2025 resource", href: new_collection_resource_path(year: 2024, log_type: "sales"))
expect(page).to have_link("Add new lettings 2024 to 2025 resource", href: new_collection_resource_path(year: 2024, log_type: "lettings"))
expect(page).to have_link("Add new sales 2025 to 2026 resource", href: new_collection_resource_path(year: 2025, log_type: "sales"))
expect(page).to have_link("Add new lettings 2025 to 2026 resource", href: new_collection_resource_path(year: 2025, log_type: "lettings"))
expect(page).to have_link("Add new sales #{next_collection_start_year} to #{next_collection_end_year} resource", href: new_collection_resource_path(year: next_collection_start_year, log_type: "sales"))
expect(page).to have_link("Add new lettings #{next_collection_start_year} to #{next_collection_end_year} resource", href: new_collection_resource_path(year: next_collection_start_year, log_type: "lettings"))
expect(page).to have_link("Add new sales #{current_collection_start_year} to #{current_collection_end_year} resource", href: new_collection_resource_path(year: current_collection_start_year, log_type: "sales"))
expect(page).to have_link("Add new lettings #{current_collection_start_year} to #{current_collection_end_year} resource", href: new_collection_resource_path(year: current_collection_start_year, log_type: "lettings"))
end
context "when files are on S3" do
@ -86,36 +88,36 @@ RSpec.describe CollectionResourcesController, type: :request do
end
it "displays file names with download links" do
expect(page).to have_link("2024_25_lettings_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("bulk-upload-lettings-template-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("bulk-upload-lettings-specification-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("2024_25_sales_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("bulk-upload-sales-template-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("bulk-upload-sales-specification-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("2025_26_lettings_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("bulk-upload-lettings-template-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("bulk-upload-lettings-specification-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("2025_26_sales_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("bulk-upload-sales-template-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("bulk-upload-sales-specification-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link(href: download_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
end
it "displays change links" do
expect(page).to have_selector(:link_or_button, "Change", count: 12)
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
end
context "when the collection year has not started yet" do
@ -157,19 +159,19 @@ RSpec.describe CollectionResourcesController, type: :request do
it "displays upload links" do
expect(page).to have_selector(:link_or_button, "Upload", count: 12)
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "lettings", resource_type: "bulk_upload_specification"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "paper_form"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template"))
expect(page).to have_link("Upload", href: edit_mandatory_collection_resource_path(year: next_collection_start_year, log_type: "sales", resource_type: "bulk_upload_specification"))
end
context "when the collection year has not started yet" do
@ -333,9 +335,9 @@ RSpec.describe CollectionResourcesController, type: :request do
end
it "displays update collection resources page content" do
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template")
get edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template")
expect(page).to have_content("Sales 2024 to 2025")
expect(page).to have_content("Sales #{current_collection_start_year} to #{current_collection_end_year}")
expect(page).to have_content("Change the bulk upload template")
expect(page).to have_content("This file will be available for all users to download.")
expect(page).to have_content("Upload file")
@ -351,9 +353,9 @@ RSpec.describe CollectionResourcesController, type: :request do
end
it "displays upload collection resources page content" do
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template")
get edit_mandatory_collection_resource_path(year: current_collection_start_year, log_type: "sales", resource_type: "bulk_upload_template")
expect(page).to have_content("Sales 2024 to 2025")
expect(page).to have_content("Sales #{current_collection_start_year} to #{current_collection_end_year}")
expect(page).to have_content("Upload the bulk upload template")
expect(page).to have_content("This file will be available for all users to download.")
expect(page).to have_content("Upload file")

165
spec/requests/duplicate_logs_controller_spec.rb

@ -4,19 +4,9 @@ RSpec.describe DuplicateLogsController, type: :request do
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { create(:user, :data_coordinator) }
let(:lettings_log) { create(:lettings_log, :duplicate, assigned_to: user) }
let(:sales_log) { create(:sales_log, :duplicate, assigned_to: user) }
let(:sales_log) { create(:sales_log, :duplicate, staircase: 2, assigned_to: user) }
describe "GET show" do
before do
Timecop.freeze(Time.zone.local(2024, 3, 1))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
context "when user is not signed in" do
it "redirects to sign in page" do
get "/lettings-logs/#{lettings_log.id}/duplicate-logs"
@ -64,11 +54,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 3)
expect(page).to have_content("Q7 - Tenant code", count: 3)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 3)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 3)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 3)
expect(page).to have_content("- Tenancy start date", count: 3)
expect(page).to have_content("- Tenant code", count: 3)
expect(page).to have_content("- Lead tenant’s age", count: 3)
expect(page).to have_content("- Lead tenant’s gender identity", count: 3)
expect(page).to have_content("- Lead tenant’s working situation", count: 3)
expect(page).to have_content("Household rent and charges", count: 3)
expect(page).to have_link("Change", count: 24)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&organisation_id=#{lettings_log.owning_organisation_id}&original_log_id=#{lettings_log.id}&referrer=duplicate_logs")
@ -81,12 +71,12 @@ RSpec.describe DuplicateLogsController, type: :request do
duplicate_logs[0].update!(uprn: "123", uprn_known: 1, uprn_confirmed: 1, manual_address_entry_selected: false)
get "/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}"
expect(page).to have_content("Q5 - Tenancy start date", count: 3)
expect(page).to have_content("Q7 - Tenant code", count: 3)
expect(page).to have_content("- Tenancy start date", count: 3)
expect(page).to have_content("- Tenant code", count: 3)
expect(page).to have_content("Postcode (from UPRN)", count: 2)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 3)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 3)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 3)
expect(page).to have_content("- Lead tenant’s age", count: 3)
expect(page).to have_content("- Lead tenant’s gender identity", count: 3)
expect(page).to have_content("- Lead tenant’s working situation", count: 3)
expect(page).to have_content("Household rent and charges", count: 3)
expect(page).to have_link("Change", count: 24)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&original_log_id=#{lettings_log.id}&referrer=duplicate_logs")
@ -110,11 +100,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 1)
expect(page).to have_content("Q7 - Tenant code", count: 1)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 1)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 1)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 1)
expect(page).to have_content("- Tenancy start date", count: 1)
expect(page).to have_content("- Tenant code", count: 1)
expect(page).to have_content("- Lead tenant’s age", count: 1)
expect(page).to have_content("- Lead tenant’s gender identity", count: 1)
expect(page).to have_content("- Lead tenant’s working situation", count: 1)
expect(page).to have_content("Household rent and charges", count: 1)
expect(page).to have_link("Change", count: 8)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?original_log_id=#{lettings_log.id}&referrer=interruption_screen")
@ -136,11 +126,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 1)
expect(page).to have_content("Q7 - Tenant code", count: 1)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 1)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 1)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 1)
expect(page).to have_content("- Tenancy start date", count: 1)
expect(page).to have_content("- Tenant code", count: 1)
expect(page).to have_content("- Lead tenant’s age", count: 1)
expect(page).to have_content("- Lead tenant’s gender identity", count: 1)
expect(page).to have_content("- Lead tenant’s working situation", count: 1)
expect(page).to have_content("Household rent and charges", count: 1)
expect(page).to have_link("Change", count: 8)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?original_log_id=#{lettings_log.id}&referrer=interruption_screen")
@ -173,12 +163,13 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 3)
expect(page).to have_content("Q2 - Purchaser code", count: 3)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 3)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 3)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 3)
expect(page).to have_content("Q15 - Postcode", count: 3)
expect(page).to have_content("- Owning organisation", count: 3)
expect(page).to have_content("- Sale completion date", count: 3)
expect(page).to have_content("- Purchaser code", count: 3)
expect(page).to have_content("- Buyer 1’s age", count: 3)
expect(page).to have_content("- Buyer 1’s gender identity", count: 3)
expect(page).to have_content("- Buyer 1’s working situation", count: 3)
expect(page).to have_content("- Postcode", count: 3)
expect(page).to have_link("Change", count: 21)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&organisation_id=#{sales_log.owning_organisation_id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[0].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&organisation_id=#{sales_log.owning_organisation_id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
@ -191,11 +182,11 @@ RSpec.describe DuplicateLogsController, type: :request do
duplicate_logs[1].update!(uprn: "123", uprn_known: 1, manual_address_entry_selected: false)
get "/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}"
expect(page).to have_content("Q1 - Sale completion date", count: 3)
expect(page).to have_content("Q2 - Purchaser code", count: 3)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 3)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 3)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 3)
expect(page).to have_content("- Sale completion date", count: 3)
expect(page).to have_content("- Purchaser code", count: 3)
expect(page).to have_content("- Buyer 1’s age", count: 3)
expect(page).to have_content("- Buyer 1’s gender identity", count: 3)
expect(page).to have_content("- Buyer 1’s working situation", count: 3)
expect(page).to have_content("Postcode (from UPRN)", count: 3)
expect(page).to have_link("Change", count: 21)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
@ -219,12 +210,12 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 1)
expect(page).to have_content("Q2 - Purchaser code", count: 1)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 1)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 1)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 1)
expect(page).to have_content("Q15 - Postcode", count: 1)
expect(page).to have_content("- Sale completion date", count: 1)
expect(page).to have_content("- Purchaser code", count: 1)
expect(page).to have_content("- Buyer 1’s age", count: 1)
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@ -245,12 +236,12 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 1)
expect(page).to have_content("Q2 - Purchaser code", count: 1)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 1)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 1)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 1)
expect(page).to have_content("Q15 - Postcode", count: 1)
expect(page).to have_content("- Sale completion date", count: 1)
expect(page).to have_content("- Purchaser code", count: 1)
expect(page).to have_content("- Buyer 1’s age", count: 1)
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@ -289,11 +280,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 3)
expect(page).to have_content("Q7 - Tenant code", count: 3)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 3)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 3)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 3)
expect(page).to have_content("- Tenancy start date", count: 3)
expect(page).to have_content("- Tenant code", count: 3)
expect(page).to have_content("- Lead tenant’s age", count: 3)
expect(page).to have_content("- Lead tenant’s gender identity", count: 3)
expect(page).to have_content("- Lead tenant’s working situation", count: 3)
expect(page).to have_content("Household rent and charges", count: 3)
expect(page).to have_link("Change", count: 21)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&original_log_id=#{lettings_log.id}&referrer=duplicate_logs")
@ -317,11 +308,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 1)
expect(page).to have_content("Q7 - Tenant code", count: 1)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 1)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 1)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 1)
expect(page).to have_content("- Tenancy start date", count: 1)
expect(page).to have_content("- Tenant code", count: 1)
expect(page).to have_content("- Lead tenant’s age", count: 1)
expect(page).to have_content("- Lead tenant’s gender identity", count: 1)
expect(page).to have_content("- Lead tenant’s working situation", count: 1)
expect(page).to have_content("Household rent and charges", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?original_log_id=#{lettings_log.id}&referrer=interruption_screen")
@ -343,11 +334,11 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q5 - Tenancy start date", count: 1)
expect(page).to have_content("Q7 - Tenant code", count: 1)
expect(page).to have_content("Q32 - Lead tenant’s age", count: 1)
expect(page).to have_content("Q33 - Lead tenant’s gender identity", count: 1)
expect(page).to have_content("Q37 - Lead tenant’s working situation", count: 1)
expect(page).to have_content("- Tenancy start date", count: 1)
expect(page).to have_content("- Tenant code", count: 1)
expect(page).to have_content("- Lead tenant’s age", count: 1)
expect(page).to have_content("- Lead tenant’s gender identity", count: 1)
expect(page).to have_content("- Lead tenant’s working situation", count: 1)
expect(page).to have_content("Household rent and charges", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/tenant-code?original_log_id=#{lettings_log.id}&referrer=interruption_screen")
@ -380,12 +371,12 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 3)
expect(page).to have_content("Q2 - Purchaser code", count: 3)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 3)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 3)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 3)
expect(page).to have_content("Q15 - Postcode", count: 3)
expect(page).to have_content("- Sale completion date", count: 3)
expect(page).to have_content("- Purchaser code", count: 3)
expect(page).to have_content("- Buyer 1’s age", count: 3)
expect(page).to have_content("- Buyer 1’s gender identity", count: 3)
expect(page).to have_content("- Buyer 1’s working situation", count: 3)
expect(page).to have_content("- Postcode", count: 3)
expect(page).to have_link("Change", count: 18)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[0].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
@ -408,12 +399,12 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 1)
expect(page).to have_content("Q2 - Purchaser code", count: 1)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 1)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 1)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 1)
expect(page).to have_content("Q15 - Postcode", count: 1)
expect(page).to have_content("- Sale completion date", count: 1)
expect(page).to have_content("- Purchaser code", count: 1)
expect(page).to have_content("- Buyer 1’s age", count: 1)
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
expect(page).to have_link("Change", count: 6)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@ -434,12 +425,12 @@ RSpec.describe DuplicateLogsController, type: :request do
end
it "displays check your answers for each log with correct questions" do
expect(page).to have_content("Q1 - Sale completion date", count: 1)
expect(page).to have_content("Q2 - Purchaser code", count: 1)
expect(page).to have_content("Q20 - Buyer 1’s age", count: 1)
expect(page).to have_content("Q21 - Buyer 1’s gender identity", count: 1)
expect(page).to have_content("Q25 - Buyer 1’s working situation", count: 1)
expect(page).to have_content("Q15 - Postcode", count: 1)
expect(page).to have_content("- Sale completion date", count: 1)
expect(page).to have_content("- Purchaser code", count: 1)
expect(page).to have_content("- Buyer 1’s age", count: 1)
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
expect(page).to have_link("Change", count: 6)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end

31
spec/requests/lettings_logs_controller_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe LettingsLogsController, type: :request do
include CollectionTimeHelper
let(:user) { FactoryBot.create(:user, organisation: create(:organisation, rent_periods: [2])) }
let(:owning_organisation) { user.organisation }
let(:managing_organisation) { owning_organisation }
@ -10,6 +12,7 @@ RSpec.describe LettingsLogsController, type: :request do
ActionController::HttpAuthentication::Basic
.encode_credentials(api_username, api_password)
end
let(:current_date) { current_collection_start_date }
let(:headers) do
{
@ -1218,32 +1221,6 @@ RSpec.describe LettingsLogsController, type: :request do
end
end
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)
expect(page).to have_content "Tenancy information"
expect(page).not_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 "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) }
@ -1588,7 +1565,7 @@ RSpec.describe LettingsLogsController, type: :request do
end
context "when viewing a specific log affected by deactivated location" do
let!(:affected_lettings_log) { FactoryBot.create(:lettings_log, unresolved: true, assigned_to: user, needstype: 2, startdate: Time.zone.local(2024, 4, 1)) }
let!(:affected_lettings_log) { FactoryBot.create(:lettings_log, unresolved: true, assigned_to: user, needstype: 2, startdate: current_date) }
let(:headers) { { "Accept" => "text/html" } }
before do

192
spec/services/csv/lettings_log_csv_service_spec.rb

@ -117,12 +117,12 @@ 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, startdate: Time.zone.local(2024, 11, 1)) }
let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) }
it "gives answer to radio questions as labels" do
relat2_column_index = attribute_line.index("relat2")
relat2_value = content_line[relat2_column_index]
expect(relat2_value).to eq "Partner"
expect(relat2_value).to eq "Yes"
end
it "gives answers to free input questions as the user input" do
@ -579,194 +579,6 @@ RSpec.describe Csv::LettingsLogCsvService do
end
end
end
context "when the requested log year is 2023" do
let(:year) { 2023 }
let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") }
let(:log) do
create(
:lettings_log,
:ignore_validation_errors,
created_by: user,
assigned_to: user,
created_at: Time.zone.local(2023, 11, 26),
updated_at: Time.zone.local(2023, 11, 26),
owning_organisation: organisation,
managing_organisation: organisation,
needstype: 1,
renewal: 0,
startdate: Time.zone.local(2023, 11, 26),
rent_type: 1,
tenancycode: "HIJKLMN",
propcode: "ABCDEFG",
declaration: 1,
address_line1: "Address line 1",
town_or_city: "London",
postcode_full: "NW9 5LL",
la: "E09000003",
is_la_inferred: false,
first_time_property_let_as_social_housing: 0,
unitletas: 2,
rsnvac: 6,
offered: 2,
unittype_gn: 7,
builtype: 1,
wchair: 1,
beds: 3,
voiddate: Time.zone.local(2023, 11, 24),
majorrepairs: 1,
mrcdate: Time.zone.local(2023, 11, 25),
joint: 3,
startertenancy: 1,
tenancy: 4,
tenancylength: 2,
hhmemb: 4,
age1_known: 0,
age1: 35,
sex1: "F",
ethnic_group: 0,
ethnic: 2,
national: 13,
ecstat1: 0,
details_known_2: 0,
relat2: "P",
age2_known: 0,
age2: 32,
sex2: "M",
ecstat2: 6,
details_known_3: 1,
details_known_4: 0,
relat4: "R",
age4_known: 1,
sex4: "R",
ecstat4: 10,
armedforces: 1,
leftreg: 4,
reservist: 1,
preg_occ: 2,
housingneeds: 1,
housingneeds_type: 0,
housingneeds_a: 1,
housingneeds_b: 0,
housingneeds_c: 0,
housingneeds_f: 0,
housingneeds_g: 0,
housingneeds_h: 0,
housingneeds_other: 0,
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,
layear: 2,
waityear: 7,
reason: 4,
prevten: 6,
homeless: 1,
ppcodenk: 1,
ppostcode_full: "TN23 6LZ",
previous_la_known: 1,
prevloc: "E07000105",
reasonpref: 1,
rp_homeless: 0,
rp_insan_unsat: 1,
rp_medwel: 0,
rp_hardship: 0,
rp_dontknow: 0,
cbl: 0,
chr: 1,
cap: 0,
accessible_register: 0,
referral: 2,
net_income_known: 0,
incref: 0,
incfreq: 1,
earnings: 268,
hb: 6,
has_benefits: 1,
benefits: 1,
period: 2,
brent: 200,
scharge: 50,
pscharge: 40,
supcharg: 35,
tcharge: 325,
hbrentshortfall: 1,
tshortfall_known: 1,
tshortfall: 12,
)
end
context "when exporting with human readable labels" do
let(:export_type) { "labels" }
context "when the current user is a support user" do
let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_23.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
context "when the current user is not a support user" do
let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
end
context "when exporting values as codes" do
let(:export_type) { "codes" }
context "when the current user is a support user" do
let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_23.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
context "when the current user is not a support user" do
let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_23.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
end
end
end
end
end

12
spec/services/documentation_generator_spec.rb

@ -155,8 +155,8 @@ describe DocumentationGenerator do
context "when the service is run for lettings" do
let(:log_type) { "lettings" }
let(:form) { FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2023, "lettings")] }
let(:row_parser_class) { BulkUpload::Lettings::Year2023::RowParser }
let(:form) { FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2025, "lettings")] }
let(:row_parser_class) { BulkUpload::Lettings::Year2025::RowParser }
it "creates new validation documentation records" do
expect(Rails.logger).to receive(:info).with(/described/).at_least(:once)
@ -167,7 +167,7 @@ describe DocumentationGenerator do
expect(any_validation.field).to eq("ppostcode_full")
expect(any_validation.error_message).to eq("Enter a valid postcode")
expect(any_validation.case).to eq("Previous postcode is known and current postcode is blank")
expect(any_validation.collection_year).to eq("2023/2024")
expect(any_validation.collection_year).to eq("2025/2026")
expect(any_validation.validation_type).to eq("format")
expect(any_validation.hard_soft).to eq("hard")
expect(any_validation.other_validated_models).to eq("User")
@ -207,8 +207,8 @@ describe DocumentationGenerator do
context "when the service is run for sales" do
let(:log_type) { "sales" }
let(:form) { FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2023, "sales")] }
let(:row_parser_class) { BulkUpload::Sales::Year2023::RowParser }
let(:form) { FormHandler.instance.forms[FormHandler.instance.form_name_from_start_year(2025, "sales")] }
let(:row_parser_class) { BulkUpload::Sales::Year2025::RowParser }
it "creates new validation documentation records" do
expect(Rails.logger).to receive(:info).with(/described/).at_least(:once)
@ -219,7 +219,7 @@ describe DocumentationGenerator do
expect(any_validation.field).to eq("ppostcode_full")
expect(any_validation.error_message).to eq("Enter a valid postcode")
expect(any_validation.case).to eq("Previous postcode is known and current postcode is blank")
expect(any_validation.collection_year).to eq("2023/2024")
expect(any_validation.collection_year).to eq("2025/2026")
expect(any_validation.validation_type).to eq("format")
expect(any_validation.hard_soft).to eq("hard")
expect(any_validation.other_validated_models).to eq("User")

40
spec/services/merge/merge_organisations_service_spec.rb

@ -59,7 +59,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -103,7 +103,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -140,7 +140,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.child_organisations.count).to eq(3)
@ -557,7 +557,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -590,7 +590,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.sales_logs.count).to eq(0)
@ -652,7 +652,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.sales_logs.count).to eq(0)
@ -688,7 +688,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
expect(absorbing_organisation.lettings_logs.count).to eq(0)
@ -852,7 +852,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -971,7 +971,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -1096,7 +1096,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
absorbing_organisation.reload
merging_organisation.reload
@ -1166,7 +1166,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload
@ -1210,7 +1210,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload
@ -1247,7 +1247,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
expect(new_absorbing_organisation.child_organisations.count).to eq(3)
@ -1352,7 +1352,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload
@ -1384,7 +1384,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
expect(new_absorbing_organisation.sales_logs.count).to eq(0)
@ -1423,7 +1423,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
expect(new_absorbing_organisation.sales_logs.count).to eq(0)
@ -1459,7 +1459,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
expect(new_absorbing_organisation.lettings_logs.count).to eq(0)
@ -1565,7 +1565,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload
@ -1655,7 +1655,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload
@ -1697,7 +1697,7 @@ RSpec.describe Merge::MergeOrganisationsService do
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
expect { merge_organisations_service.call }.to raise_error(ActiveRecord::RecordInvalid)
merge_organisations_service.call
new_absorbing_organisation.reload
merging_organisation.reload

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

@ -1,12 +1,14 @@
require "rails_helper"
RSpec.describe "form/guidance/_financial_calculations_outright_sale.html.erb" do
let(:log) { create(:sales_log) }
include CollectionTimeHelper
let(:log) { create(:sales_log) }
let(:current_date) { current_collection_start_date }
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, saledate: Time.zone.local(2024, 11, 1)) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: nil, saledate: current_date) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }
@ -18,7 +20,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, saledate: Time.zone.local(2024, 11, 1)) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 2, saledate: current_date) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }
@ -32,7 +34,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, saledate: Time.zone.local(2024, 11, 1)) }
let(:log) { create(:sales_log, :shared_ownership_setup_complete, mortgageused: 1, saledate: current_date) }
it "renders correct content" do
render partial: "form/guidance/financial_calculations_outright_sale", locals: { log:, current_user: log.assigned_to }

Loading…
Cancel
Save