Browse Source

CLDC-2069 Find UPRNs by address (#2278)

* feat: mvp commit with address selector from address line 1 and postcode using OS places find endpoint

* feat: build out alternative routes through the address lookup flow

* refactor: lint

* refactor: remove commented lines

* feat: make nil safe

* feat: test address client

* feat: store address input separately

* feat: add migration

* feat: display inputs in answer label

* feat: update data presenter and test

* feat: revert precicions schema update

* feat: revert precision schema update

* feat: migrate new fields to sales logs

* feat: update shared log examples tests

* feat: use -1 for not listed address for extensibility

* feat: add service error to address_selection

* feat: handle case when no addresses are found

* feat: allow re-entering different uprns

* feat: improve error handling and don't accept "no match" precisions

* feat: add page tests

* feat: confirm uprn on address update

* feat: add question tests

* feat: don't set minimum match for initial search

* feat: mvp commit with address selector from address line 1 and postcode using OS places find endpoint

* feat: build out alternative routes through the address lookup flow

* refactor: lint

* refactor: remove commented lines

* feat: make nil safe

* feat: test address client

* feat: store address input separately

* feat: add migration

* feat: display inputs in answer label

* feat: update data presenter and test

* feat: revert precision schema update

* feat: migrate new fields to sales logs

* feat: update shared log examples tests

* feat: use -1 for not listed address for extensibility

* feat: add service error to address_selection

* feat: handle case when no addresses are found

* feat: allow re-entering different uprns

* feat: improve error handling and don't accept "no match" precisions

* feat: add page tests

* feat: confirm uprn on address update

* feat: add question tests

* feat: don't set minimum match for initial search

* feat: add no address found page

* feat: allow uprn known to be skipped, and set 0.4 min precision

* feat: accept best "good" match in bulk upload

* feat: update validations and test

* refactor: avoid stubbing using any_instance_of

* refactor: use change_table in migrations

* feat: add lettings behaviour to sales logs

* feat: update sales tests

* feat: xit test that is xited in lettings

* feat: stub os api in sales row parser

* feat: stub os api in sales row parser

* feat: add address line 1 to required attributes

* feat: update matching details and fix row parser validation

* refactor: improve readability

* feat: set uprns as option IDs to avoid multiple lookups

* feat: add sales uprn_selection

* feat: update schema

* feat: update tests

* feat: remove redundant methods

* feat: update error message and fix tests

* feat: update tests

* feat: update tests and error behaviour

* feat: update tests
pull/2314/head
natdeanlewissoftwire 10 months ago committed by GitHub
parent
commit
fedbc6acad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 25
      app/models/form/lettings/pages/address_fallback.rb
  2. 19
      app/models/form/lettings/pages/address_matcher.rb
  3. 26
      app/models/form/lettings/pages/no_address_found.rb
  4. 12
      app/models/form/lettings/pages/uprn.rb
  5. 28
      app/models/form/lettings/pages/uprn_selection.rb
  6. 20
      app/models/form/lettings/questions/address_line1_for_address_matcher.rb
  7. 9
      app/models/form/lettings/questions/no_address_found.rb
  8. 13
      app/models/form/lettings/questions/postcode_for_address_matcher.rb
  9. 18
      app/models/form/lettings/questions/uprn_confirmation.rb
  10. 34
      app/models/form/lettings/questions/uprn_selection.rb
  11. 11
      app/models/form/lettings/subsections/property_information.rb
  12. 25
      app/models/form/sales/pages/address_fallback.rb
  13. 19
      app/models/form/sales/pages/address_matcher.rb
  14. 26
      app/models/form/sales/pages/no_address_found.rb
  15. 12
      app/models/form/sales/pages/uprn.rb
  16. 28
      app/models/form/sales/pages/uprn_selection.rb
  17. 20
      app/models/form/sales/questions/address_line1_for_address_matcher.rb
  18. 9
      app/models/form/sales/questions/no_address_found.rb
  19. 13
      app/models/form/sales/questions/postcode_for_address_matcher.rb
  20. 18
      app/models/form/sales/questions/uprn_confirmation.rb
  21. 34
      app/models/form/sales/questions/uprn_selection.rb
  22. 36
      app/models/form/sales/subsections/property_information.rb
  23. 19
      app/models/lettings_log.rb
  24. 67
      app/models/log.rb
  25. 19
      app/models/sales_log.rb
  26. 52
      app/services/address_client.rb
  27. 21
      app/services/address_data_presenter.rb
  28. 17
      app/services/bulk_upload/lettings/year2024/row_parser.rb
  29. 17
      app/services/bulk_upload/sales/year2024/row_parser.rb
  30. 2
      app/services/csv/lettings_log_csv_service.rb
  31. 5
      config/locales/en.yml
  32. 8
      db/migrate/20240304103216_add_address_input_fields_to_lettings_log.rb
  33. 8
      db/migrate/20240304115940_add_address_lookup_fields_to_sales_logs.rb
  34. 5
      db/migrate/20240306091659_add_no_address_found_check_to_lettings_logs.rb
  35. 5
      db/migrate/20240307161802_add_address_search_value_check_to_sales_logs.rb
  36. 5
      db/migrate/20240311094307_add_uprn_selection_to_lettings_log.rb
  37. 5
      db/migrate/20240311102706_add_uprn_selection_to_sales_log.rb
  38. 10
      db/schema.rb
  39. 4
      spec/fixtures/files/lettings_log_csv_export_codes_23.csv
  40. 4
      spec/fixtures/files/lettings_log_csv_export_codes_24.csv
  41. 4
      spec/fixtures/files/lettings_log_csv_export_labels_23.csv
  42. 4
      spec/fixtures/files/lettings_log_csv_export_labels_24.csv
  43. 4
      spec/fixtures/files/sales_logs_csv_export_codes_23.csv
  44. 4
      spec/fixtures/files/sales_logs_csv_export_codes_24.csv
  45. 4
      spec/fixtures/files/sales_logs_csv_export_labels_23.csv
  46. 4
      spec/fixtures/files/sales_logs_csv_export_labels_24.csv
  47. 40
      spec/models/form/lettings/pages/address_fallback_spec.rb
  48. 33
      spec/models/form/lettings/pages/address_matcher_spec.rb
  49. 46
      spec/models/form/lettings/pages/no_address_found_spec.rb
  50. 44
      spec/models/form/lettings/pages/uprn_selection_spec.rb
  51. 42
      spec/models/form/lettings/pages/uprn_spec.rb
  52. 62
      spec/models/form/lettings/questions/address_line1_for_address_matcher_spec.rb
  53. 44
      spec/models/form/lettings/questions/no_address_found_spec.rb
  54. 62
      spec/models/form/lettings/questions/postcode_for_address_matcher_spec.rb
  55. 102
      spec/models/form/lettings/questions/uprn_selection_spec.rb
  56. 5
      spec/models/form/lettings/subsections/property_information_spec.rb
  57. 40
      spec/models/form/sales/pages/address_fallback_spec.rb
  58. 33
      spec/models/form/sales/pages/address_matcher_spec.rb
  59. 46
      spec/models/form/sales/pages/no_address_found_spec.rb
  60. 44
      spec/models/form/sales/pages/uprn_selection_spec.rb
  61. 42
      spec/models/form/sales/pages/uprn_spec.rb
  62. 62
      spec/models/form/sales/questions/address_line1_for_address_matcher_spec.rb
  63. 44
      spec/models/form/sales/questions/no_address_found_spec.rb
  64. 62
      spec/models/form/sales/questions/postcode_for_address_matcher_spec.rb
  65. 102
      spec/models/form/sales/questions/uprn_selection_spec.rb
  66. 18
      spec/models/form/sales/subsections/property_information_spec.rb
  67. 68
      spec/services/address_client_spec.rb
  68. 51
      spec/services/address_data_presenter_spec.rb
  69. 25
      spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb
  70. 4
      spec/services/bulk_upload/sales/year2024/row_parser_spec.rb
  71. 78
      spec/shared/shared_log_examples.rb

25
app/models/form/lettings/pages/address_fallback.rb

@ -0,0 +1,25 @@
class Form::Lettings::Pages::AddressFallback < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address"
@header = "Q12 - What is the property's address?"
@depends_on = [
{ "is_supported_housing?" => false, "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => nil, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_known" => 0, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "address_options_present?" => false },
]
end
def questions
@questions ||= [
Form::Lettings::Questions::AddressLine1.new(nil, nil, self),
Form::Lettings::Questions::AddressLine2.new(nil, nil, self),
Form::Lettings::Questions::TownOrCity.new(nil, nil, self),
Form::Lettings::Questions::County.new(nil, nil, self),
Form::Lettings::Questions::PostcodeForFullAddress.new(nil, nil, self),
]
end
end

19
app/models/form/lettings/pages/address_matcher.rb

@ -0,0 +1,19 @@
class Form::Lettings::Pages::AddressMatcher < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address_matcher"
@header = "Find an address"
@depends_on = [
{ "is_supported_housing?" => false, "uprn_known" => nil },
{ "is_supported_housing?" => false, "uprn_known" => 0 },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0 },
]
end
def questions
@questions ||= [
Form::Lettings::Questions::AddressLine1ForAddressMatcher.new(nil, nil, self),
Form::Lettings::Questions::PostcodeForAddressMatcher.new(nil, nil, self),
]
end
end

26
app/models/form/lettings/pages/no_address_found.rb

@ -0,0 +1,26 @@
class Form::Lettings::Pages::NoAddressFound < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "no_address_found"
@type = "interruption_screen"
@title_text = {
"translation" => "soft_validations.no_address_found.title_text",
"arguments" => [],
}
@informative_text = {
"translation" => "soft_validations.no_address_found.informative_text",
"arguments" => [],
}
@depends_on = [{ "address_options_present?" => false }]
end
def questions
@questions ||= [
Form::Lettings::Questions::NoAddressFound.new(nil, nil, self),
]
end
def interruption_screen_question_ids
%w[address_line1_input]
end
end

12
app/models/form/lettings/pages/uprn.rb

@ -13,12 +13,20 @@ class Form::Lettings::Pages::Uprn < ::Form::Page
end
def skip_text
"Enter address instead"
if form.start_year_after_2024?
"Search for address instead"
else
"Enter address instead"
end
end
def skip_href(log = nil)
return unless log
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
if form.start_year_after_2024?
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address-matcher"
else
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
end
end
end

28
app/models/form/lettings/pages/uprn_selection.rb

@ -0,0 +1,28 @@
class Form::Lettings::Pages::UprnSelection < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_selection"
@header = "We found some addresses that might be this property"
@depends_on = [{ "address_options_present?" => true }]
end
def questions
@questions ||= [
Form::Lettings::Questions::UprnSelection.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
(log.uprn_known.nil? || log.uprn_known.zero?) && log.address_line1_input.present? && log.postcode_full_input.present? && (1..10).cover?(log.address_options&.count)
end
def skip_text
"Search for address again"
end
def skip_href(log = nil)
return unless log
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address-matcher"
end
end

20
app/models/form/lettings/questions/address_line1_for_address_matcher.rb

@ -0,0 +1,20 @@
class Form::Lettings::Questions::AddressLine1ForAddressMatcher < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_line1_input"
@header = "Address line 1"
@error_label = "Address line 1"
@type = "text"
@plain_label = true
@check_answer_label = "Find address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
@hide_question_number_on_page = true
end
def answer_label(log, _current_user = nil)
[
log.address_line1_input,
log.postcode_full_input,
].select(&:present?).join("\n")
end
end

9
app/models/form/lettings/questions/no_address_found.rb

@ -0,0 +1,9 @@
class Form::Lettings::Questions::NoAddressFound < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_search_value_check"
@header = "No address found"
@type = "interruption_screen"
@hidden_in_check_answers = true
end
end

13
app/models/form/lettings/questions/postcode_for_address_matcher.rb

@ -0,0 +1,13 @@
class Form::Lettings::Questions::PostcodeForAddressMatcher < ::Form::Question
def initialize(id, hsh, page)
super
@id = "postcode_full_input"
@header = "Postcode"
@type = "text"
@width = 5
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
@hide_question_number_on_page = true
@hidden_in_check_answers = true
end
end

18
app/models/form/lettings/questions/uprn_confirmation.rb

@ -4,14 +4,22 @@ class Form::Lettings::Questions::UprnConfirmation < ::Form::Question
@id = "uprn_confirmed"
@header = "Is this the property address?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answer_label = "Is this the right address?"
end
ANSWER_OPTIONS = {
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to enter the address manually" },
}.freeze
def answer_options
if form.start_year_after_2024?
{
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to search for the address instead" },
}.freeze
else
{
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to enter the address manually" },
}.freeze
end
end
def notification_banner(log = nil)
return unless log&.uprn

34
app/models/form/lettings/questions/uprn_selection.rb

@ -0,0 +1,34 @@
class Form::Lettings::Questions::UprnSelection < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn_selection"
@header = "Select the correct address"
@type = "radio"
@check_answer_label = "Select the correct address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options(log = nil, _user = nil)
answer_opts = { "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" } }
return answer_opts unless ActiveRecord::Base.connected?
return answer_opts unless log&.address_options
answer_opts = {}
(0...[log.address_options.count, 10].min).each do |i|
answer_opts[log.address_options[i][:uprn]] = { "value" => log.address_options[i][:address] }
end
answer_opts["divider"] = { "value" => true }
answer_opts["uprn_not_listed"] = { "value" => "The address is not listed, I want to enter the address manually" }
answer_opts
end
def displayed_answer_options(log, user = nil)
answer_options(log, user)
end
def hidden_in_check_answers?(log, _current_user = nil)
(log.uprn_known == 1 || log.uprn_confirmed == 1) || !(1..10).cover?(log.address_options&.count)
end
end

11
app/models/form/lettings/subsections/property_information.rb

@ -31,7 +31,16 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
end
def uprn_questions
if form.start_date.year >= 2023
if form.start_year_after_2024?
[
Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),
Form::Lettings::Pages::AddressMatcher.new(nil, nil, self),
Form::Lettings::Pages::NoAddressFound.new(nil, nil, self),
Form::Lettings::Pages::UprnSelection.new(nil, nil, self),
Form::Lettings::Pages::AddressFallback.new(nil, nil, self),
]
elsif form.start_date.year == 2023
[
Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),

25
app/models/form/sales/pages/address_fallback.rb

@ -0,0 +1,25 @@
class Form::Sales::Pages::AddressFallback < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address"
@header = "Q12 - What is the property's address?"
@depends_on = [
{ "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => nil, "address_options_present?" => false },
{ "uprn_known" => 0, "address_options_present?" => false },
{ "uprn_confirmed" => 0, "address_options_present?" => false },
]
end
def questions
@questions ||= [
Form::Sales::Questions::AddressLine1.new(nil, nil, self),
Form::Sales::Questions::AddressLine2.new(nil, nil, self),
Form::Sales::Questions::TownOrCity.new(nil, nil, self),
Form::Sales::Questions::County.new(nil, nil, self),
Form::Sales::Questions::PostcodeForFullAddress.new(nil, nil, self),
]
end
end

19
app/models/form/sales/pages/address_matcher.rb

@ -0,0 +1,19 @@
class Form::Sales::Pages::AddressMatcher < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address_matcher"
@header = "Find an address"
@depends_on = [
{ "uprn_known" => nil },
{ "uprn_known" => 0 },
{ "uprn_confirmed" => 0 },
]
end
def questions
@questions ||= [
Form::Sales::Questions::AddressLine1ForAddressMatcher.new(nil, nil, self),
Form::Sales::Questions::PostcodeForAddressMatcher.new(nil, nil, self),
]
end
end

26
app/models/form/sales/pages/no_address_found.rb

@ -0,0 +1,26 @@
class Form::Sales::Pages::NoAddressFound < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "no_address_found"
@type = "interruption_screen"
@title_text = {
"translation" => "soft_validations.no_address_found.title_text",
"arguments" => [],
}
@informative_text = {
"translation" => "soft_validations.no_address_found.informative_text",
"arguments" => [],
}
@depends_on = [{ "address_options_present?" => false }]
end
def questions
@questions ||= [
Form::Sales::Questions::NoAddressFound.new(nil, nil, self),
]
end
def interruption_screen_question_ids
%w[address_line1_input]
end
end

12
app/models/form/sales/pages/uprn.rb

@ -12,12 +12,20 @@ class Form::Sales::Pages::Uprn < ::Form::Page
end
def skip_text
"Enter address instead"
if form.start_year_after_2024?
"Search for address instead"
else
"Enter address instead"
end
end
def skip_href(log = nil)
return unless log
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
if form.start_year_after_2024?
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address-matcher"
else
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
end
end
end

28
app/models/form/sales/pages/uprn_selection.rb

@ -0,0 +1,28 @@
class Form::Sales::Pages::UprnSelection < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_selection"
@header = "We found some addresses that might be this property"
@depends_on = [{ "address_options_present?" => true }]
end
def questions
@questions ||= [
Form::Sales::Questions::UprnSelection.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
(log.uprn_known.nil? || log.uprn_known.zero?) && log.address_line1_input.present? && log.postcode_full_input.present? && (1..10).cover?(log.address_options&.count)
end
def skip_text
"Search for address again"
end
def skip_href(log = nil)
return unless log
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address-matcher"
end
end

20
app/models/form/sales/questions/address_line1_for_address_matcher.rb

@ -0,0 +1,20 @@
class Form::Sales::Questions::AddressLine1ForAddressMatcher < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_line1_input"
@header = "Address line 1"
@error_label = "Address line 1"
@type = "text"
@plain_label = true
@check_answer_label = "Find address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
@hide_question_number_on_page = true
end
def answer_label(log, _current_user = nil)
[
log.address_line1_input,
log.postcode_full_input,
].select(&:present?).join("\n")
end
end

9
app/models/form/sales/questions/no_address_found.rb

@ -0,0 +1,9 @@
class Form::Sales::Questions::NoAddressFound < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_search_value_check"
@header = "No address found"
@type = "interruption_screen"
@hidden_in_check_answers = true
end
end

13
app/models/form/sales/questions/postcode_for_address_matcher.rb

@ -0,0 +1,13 @@
class Form::Sales::Questions::PostcodeForAddressMatcher < ::Form::Question
def initialize(id, hsh, page)
super
@id = "postcode_full_input"
@header = "Postcode"
@type = "text"
@width = 5
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
@hide_question_number_on_page = true
@hidden_in_check_answers = true
end
end

18
app/models/form/sales/questions/uprn_confirmation.rb

@ -4,14 +4,22 @@ class Form::Sales::Questions::UprnConfirmation < ::Form::Question
@id = "uprn_confirmed"
@header = "Is this the property address?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answer_label = "Is this the right address?"
end
ANSWER_OPTIONS = {
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to enter the address manually" },
}.freeze
def answer_options
if form.start_year_after_2024?
{
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to search for the address instead" },
}.freeze
else
{
"1" => { "value" => "Yes" },
"0" => { "value" => "No, I want to enter the address manually" },
}.freeze
end
end
def notification_banner(log = nil)
return unless log&.uprn

34
app/models/form/sales/questions/uprn_selection.rb

@ -0,0 +1,34 @@
class Form::Sales::Questions::UprnSelection < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn_selection"
@header = "Select the correct address"
@type = "radio"
@check_answer_label = "Select the correct address"
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
def answer_options(log = nil, _user = nil)
answer_opts = { "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" } }
return answer_opts unless ActiveRecord::Base.connected?
return answer_opts unless log&.address_options
answer_opts = {}
(0...[log.address_options.count, 10].min).each do |i|
answer_opts[log.address_options[i][:uprn]] = { "value" => log.address_options[i][:address] }
end
answer_opts["divider"] = { "value" => true }
answer_opts["uprn_not_listed"] = { "value" => "The address is not listed, I want to enter the address manually" }
answer_opts
end
def displayed_answer_options(log, user = nil)
answer_options(log, user)
end
def hidden_in_check_answers?(log, _current_user = nil)
(log.uprn_known == 1 || log.uprn_confirmed == 1) || !(1..10).cover?(log.address_options&.count)
end
end

36
app/models/form/sales/subsections/property_information.rb

@ -22,16 +22,32 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
end
def uprn_questions
[
Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::Address.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("local_authority_combined_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
]
if form.start_year_after_2024?
[
Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::AddressMatcher.new(nil, nil, self),
Form::Sales::Pages::NoAddressFound.new(nil, nil, self),
Form::Sales::Pages::UprnSelection.new(nil, nil, self),
Form::Sales::Pages::AddressFallback.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("local_authority_combined_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
]
else
[
Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::Address.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("local_authority_combined_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
]
end
end
def postcode_and_la_questions

19
app/models/lettings_log.rb

@ -34,6 +34,7 @@ class LettingsLog < Log
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
before_validation :set_derived_fields!
before_validation :process_uprn_change!, if: :should_process_uprn_change?
before_validation :process_address_change!, if: :should_process_address_change?
belongs_to :scheme, optional: true
belongs_to :location, optional: true
@ -845,6 +846,22 @@ private
end
def should_process_uprn_change?
uprn && startdate && (uprn_changed? || startdate_changed?) && collection_start_year_for_date(startdate) >= 2023
return unless uprn
return unless startdate
return unless collection_start_year_for_date(startdate) >= 2023
uprn_changed? || startdate_changed?
end
def should_process_address_change?
return unless uprn_selection || select_best_address_match
return unless startdate
return unless form.start_year_after_2024?
if select_best_address_match
address_line1_input.present? && postcode_full_input.present?
else
uprn_selection_changed? || startdate_changed?
end
end
end

67
app/models/log.rb

@ -53,19 +53,26 @@ class Log < ApplicationRecord
scope :filter_by_owning_organisation, ->(owning_organisation, _user = nil) { where(owning_organisation:) }
scope :filter_by_managing_organisation, ->(managing_organisation, _user = nil) { where(managing_organisation:) }
attr_accessor :skip_update_status, :skip_update_uprn_confirmed, :skip_dpo_validation
attr_accessor :skip_update_status, :skip_update_uprn_confirmed, :select_best_address_match, :skip_dpo_validation
delegate :present?, to: :address_options, prefix: true
def process_uprn_change!
if uprn.present?
service = UprnClient.new(uprn)
service.call
return errors.add(:uprn, :uprn_error, message: service.error) if service.error.present?
if service.error.present?
errors.add(:uprn, :uprn_error, message: service.error)
errors.add(:uprn_selection, :uprn_error, message: service.error)
return
end
presenter = UprnDataPresenter.new(service.result)
self.uprn_known = 1
self.uprn_confirmed = nil unless skip_update_uprn_confirmed
self.uprn_selection = nil
self.address_line1 = presenter.address_line1
self.address_line2 = presenter.address_line2
self.town_or_city = presenter.town_or_city
@ -75,6 +82,62 @@ class Log < ApplicationRecord
end
end
def process_address_change!
if uprn_selection.present? || select_best_address_match.present?
if select_best_address_match
service = AddressClient.new(address_string)
service.call
return nil if service.result.blank? || service.error.present?
presenter = AddressDataPresenter.new(service.result.first)
os_match_threshold_for_bulk_upload = 0.7
if presenter.match >= os_match_threshold_for_bulk_upload
self.uprn_selection = presenter.uprn
else
return nil
end
end
if uprn_selection == "uprn_not_listed"
self.uprn_known = 0
self.uprn_confirmed = nil
self.uprn = nil
self.address_line1 = address_line1_input
self.address_line2 = nil
self.town_or_city = nil
self.county = nil
self.postcode_full = postcode_full_input
else
self.uprn = uprn_selection
self.uprn_confirmed = 1
self.skip_update_uprn_confirmed = true
process_uprn_change!
end
end
end
def address_string
"#{address_line1_input}, #{postcode_full_input}"
end
def address_options
return @address_options if @address_options
if [address_line1_input, postcode_full_input].all?(&:present?)
service = AddressClient.new(address_string)
service.call
return nil if service.result.blank? || service.error.present?
address_opts = []
service.result.first(10).each do |result|
presenter = AddressDataPresenter.new(result)
address_opts.append({ address: presenter.address, uprn: presenter.uprn })
end
@address_options = address_opts
end
end
def collection_start_year
return @start_year if @start_year

19
app/models/sales_log.rb

@ -32,6 +32,7 @@ class SalesLog < Log
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
before_validation :set_derived_fields!
before_validation :process_uprn_change!, if: :should_process_uprn_change?
before_validation :process_address_change!, if: :should_process_address_change?
belongs_to :managing_organisation, class_name: "Organisation", optional: true
@ -429,7 +430,23 @@ class SalesLog < Log
end
def should_process_uprn_change?
uprn && saledate && (uprn_changed? || saledate_changed?) && collection_start_year_for_date(saledate) >= 2023
return unless uprn
return unless saledate
return unless collection_start_year_for_date(saledate) >= 2023
uprn_changed? || saledate_changed?
end
def should_process_address_change?
return unless uprn_selection || select_best_address_match
return unless saledate
return unless form.start_year_after_2024?
if select_best_address_match
address_line1_input.present? && postcode_full_input.present?
else
uprn_selection_changed? || saledate_changed?
end
end
def value_with_discount

52
app/services/address_client.rb

@ -0,0 +1,52 @@
require "net/http"
class AddressClient
attr_reader :address
attr_accessor :error
ADDRESS = "api.os.uk".freeze
PATH = "/search/places/v1/find".freeze
def initialize(address)
@address = address
end
def call
unless response.is_a?(Net::HTTPSuccess) && result.present?
@error = "Address is not recognised. Check the address, or enter the UPRN"
end
rescue JSON::ParserError
@error = "Address is not recognised. Check the address, or enter the UPRN"
end
def result
@result ||= JSON.parse(response.body)["results"]&.map { |address| address["DPA"] }
end
private
def http_client
client = Net::HTTP.new(ADDRESS, 443)
client.use_ssl = true
client.verify_mode = OpenSSL::SSL::VERIFY_PEER
client.max_retries = 3
client.read_timeout = 10 # seconds
client
end
def endpoint_uri
uri = URI(PATH)
params = {
query: address,
key: ENV["OS_DATA_KEY"],
maxresults: 10,
minmatch: 0.4,
}
uri.query = URI.encode_www_form(params)
uri.to_s
end
def response
@response ||= http_client.request_get(endpoint_uri)
end
end

21
app/services/address_data_presenter.rb

@ -0,0 +1,21 @@
require "net/http"
class AddressDataPresenter
attr_reader :data
def initialize(data)
@data = data
end
def uprn
data["UPRN"]
end
def address
data["ADDRESS"]
end
def match
data["MATCH"]
end
end

17
app/services/bulk_upload/lettings/year2024/row_parser.rb

@ -409,6 +409,7 @@ class BulkUpload::Lettings::Year2024::RowParser
validate :validate_created_by_exists, on: :after_log
validate :validate_created_by_related, on: :after_log
validate :validate_all_charges_given, on: :after_log, if: proc { is_carehome.zero? }
validate :validate_address_option_found, on: :after_log
validate :validate_nulls, on: :after_log
@ -572,6 +573,14 @@ private
end
end
def validate_address_option_found
if !log.address_options_present? && field_16.blank? && (field_17.present? || field_19.present?)
%i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field|
errors.add(field, I18n.t("validations.no_address_found"))
end
end
end
def validate_incomplete_soft_validations
routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }.compact
routed_to_soft_validation_questions.each do |question|
@ -1065,6 +1074,7 @@ private
address_line2: [:field_18],
town_or_city: [:field_19],
county: [:field_20],
uprn_selection: [:field_17],
}.compact
end
@ -1261,10 +1271,17 @@ private
attributes["address_line2"] = field_18
attributes["town_or_city"] = field_19
attributes["county"] = field_20
attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_16.blank?
attributes
end
def address_line1_input
[field_17, field_18, field_19].compact.join(", ")
end
def postcode_known
if postcode_full.present?
1

17
app/services/bulk_upload/sales/year2024/row_parser.rb

@ -450,6 +450,7 @@ class BulkUpload::Sales::Year2024::RowParser
on: :after_log
validate :validate_buyer1_economic_status, on: :before_log
validate :validate_address_option_found, on: :after_log
validate :validate_nulls, on: :after_log
validate :validate_valid_radio_option, on: :before_log
@ -597,6 +598,14 @@ private
end
end
def validate_address_option_found
if !log.address_options_present? && field_22.blank? && (field_23.present? || field_25.present?)
%i[field_23 field_24 field_25 field_26 field_27 field_28].each do |field|
errors.add(field, I18n.t("validations.no_address_found"))
end
end
end
def validate_address_fields
if field_22.blank? || log.errors.attribute_names.include?(:uprn)
if field_23.blank?
@ -758,6 +767,7 @@ private
address_line2: %i[field_24],
town_or_city: %i[field_25],
county: %i[field_26],
uprn_selection: [:field_23],
ethnic_group2: %i[field_40],
ethnicbuy2: %i[field_40],
@ -932,6 +942,9 @@ private
attributes["address_line2"] = field_24
attributes["town_or_city"] = field_25
attributes["county"] = field_26
attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_22.blank?
attributes["ethnic_group2"] = infer_buyer2_ethnic_group_from_ethnic
attributes["ethnicbuy2"] = field_40
@ -948,6 +961,10 @@ private
attributes
end
def address_line1_input
[field_23, field_24, field_25].compact.join(", ")
end
def saledate
Date.new(field_6 + 2000, field_5, field_4) if field_6.present? && field_5.present? && field_4.present?
rescue Date::Error

2
app/services/csv/lettings_log_csv_service.rb

@ -296,7 +296,7 @@ module Csv
"letting_allocation_unknown" => %w[letting_allocation_none],
}.freeze
SUPPORT_ONLY_ATTRIBUTES = %w[net_income_value_check first_time_property_let_as_social_housing postcode_known is_la_inferred totchild totelder totadult net_income_known previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 wrent wscharge wpschrge wsupchrg wtcharge wtshortfall rent_value_check old_form_id old_id retirement_value_check tshortfall_known pregnancy_value_check hhtype new_old la prevloc updated_by_id bulk_upload_id uprn_confirmed reasonother_value_check].freeze
SUPPORT_ONLY_ATTRIBUTES = %w[net_income_value_check first_time_property_let_as_social_housing postcode_known is_la_inferred totchild totelder totadult net_income_known previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 wrent wscharge wpschrge wsupchrg wtcharge wtshortfall rent_value_check old_form_id old_id retirement_value_check tshortfall_known pregnancy_value_check hhtype new_old la prevloc updated_by_id bulk_upload_id uprn_confirmed address_line1_input postcode_full_input address_search_value_check uprn_selection reasonother_value_check].freeze
def lettings_log_attributes
ordered_questions = FormHandler.instance.ordered_lettings_questions_for_all_years

5
config/locales/en.yml

@ -213,6 +213,7 @@ en:
not_answered: "You must answer %{question}"
invalid_option: "Enter a valid value for %{question}"
invalid_number: "Enter a number for %{question}"
no_address_found: "We could not find this address. Edit the address data or fix this error on the CORE site."
other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided"
other_field_not_required: "%{other_field_label} must not be provided if %{main_field_label} was not other"
@ -759,7 +760,9 @@ Make sure these answers are correct."
must_be_less_than_3_years_from_saledate: "You told us practical completion or handover date is more than 3 years before sale completion date"
saledate:
must_be_less_than_3_years_from_hodate: "You told us sale completion date is more than 3 years after practical completion or handover date"
no_address_found:
title_text: "No address found"
informative_text: "We could not find an address that matches your search. You can search again or continue to enter the address manually."
devise:
email:

8
db/migrate/20240304103216_add_address_input_fields_to_lettings_log.rb

@ -0,0 +1,8 @@
class AddAddressInputFieldsToLettingsLog < ActiveRecord::Migration[7.0]
def change
change_table :lettings_logs, bulk: true do |t|
t.string :address_line1_input
t.string :postcode_full_input
end
end
end

8
db/migrate/20240304115940_add_address_lookup_fields_to_sales_logs.rb

@ -0,0 +1,8 @@
class AddAddressLookupFieldsToSalesLogs < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.string :address_line1_input
t.string :postcode_full_input
end
end
end

5
db/migrate/20240306091659_add_no_address_found_check_to_lettings_logs.rb

@ -0,0 +1,5 @@
class AddNoAddressFoundCheckToLettingsLogs < ActiveRecord::Migration[7.0]
def change
add_column :lettings_logs, :address_search_value_check, :integer
end
end

5
db/migrate/20240307161802_add_address_search_value_check_to_sales_logs.rb

@ -0,0 +1,5 @@
class AddAddressSearchValueCheckToSalesLogs < ActiveRecord::Migration[7.0]
def change
add_column :sales_logs, :address_search_value_check, :integer
end
end

5
db/migrate/20240311094307_add_uprn_selection_to_lettings_log.rb

@ -0,0 +1,5 @@
class AddUprnSelectionToLettingsLog < ActiveRecord::Migration[7.0]
def change
add_column :lettings_logs, :uprn_selection, :string
end
end

5
db/migrate/20240311102706_add_uprn_selection_to_sales_log.rb

@ -0,0 +1,5 @@
class AddUprnSelectionToSalesLog < ActiveRecord::Migration[7.0]
def change
add_column :sales_logs, :uprn_selection, :string
end
end

10
db/schema.rb

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2024_02_16_163519) do
ActiveRecord::Schema[7.0].define(version: 2024_03_11_102706) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -308,6 +308,10 @@ ActiveRecord::Schema[7.0].define(version: 2024_02_16_163519) do
t.integer "nationality_all"
t.integer "nationality_all_group"
t.integer "reasonother_value_check"
t.string "address_line1_input"
t.string "postcode_full_input"
t.integer "address_search_value_check"
t.string "uprn_selection"
t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id"
t.index ["location_id"], name: "index_lettings_logs_on_location_id"
@ -661,6 +665,10 @@ ActiveRecord::Schema[7.0].define(version: 2024_02_16_163519) do
t.integer "nationality_all_group"
t.integer "nationality_all_buyer2"
t.integer "nationality_all_buyer2_group"
t.string "address_line1_input"
t.string "postcode_full_input"
t.integer "address_search_value_check"
t.string "uprn_selection"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id"

4
spec/fixtures/files/lettings_log_csv_export_codes_23.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,1,,,2023,DLUHC,DLUHC,1,7,0,2023-11-26,2,2,1,,2,HIJKLMN,ABCDEFG,1,0,,,fake address,,London,,NW9 5LL,false,Barnet,E09000003,0,2,6,2,2,7,1,1,3,2023-11-24,,,1,2023-11-25,,3,1,4,,2,,1,4,,1,4,0,0,2,35,,F,0,2,,13,0,0,P,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,2,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,,2,,0,0,1,268,,6,1,1,,0,2,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,,
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1_input,postcode_full_input,address_search_value_check,uprn_selection,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,1,,,2023,DLUHC,DLUHC,1,7,0,2023-11-26,2,2,1,,2,HIJKLMN,ABCDEFG,1,0,,,,,,,fake address,,London,,NW9 5LL,false,Barnet,E09000003,0,2,6,2,2,7,1,1,3,2023-11-24,,,1,2023-11-25,,3,1,4,,2,,1,4,,1,4,0,0,2,35,,F,0,2,,13,0,0,P,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,2,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,,2,,0,0,1,268,,6,1,1,,0,2,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,,

1 id status duplicate_set_id created_by is_dpo created_at updated_by updated_at creation_method old_id old_form_id collection_start_year owning_organisation_name managing_organisation_name needstype lettype renewal startdate renttype renttype_detail irproduct irproduct_other lar tenancycode propcode postcode_known uprn_known uprn uprn_confirmed address_line1_input postcode_full_input address_search_value_check uprn_selection address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la first_time_property_let_as_social_housing unitletas rsnvac newprop offered unittype_gn builtype wchair beds voiddate vacdays void_date_value_check majorrepairs mrcdate major_repairs_date_value_check joint startertenancy tenancy tenancyother tenancylength sheltered declaration hhmemb pregnancy_value_check refused hhtype totchild totelder totadult age1 retirement_value_check sex1 ethnic_group ethnic nationality_all national ecstat1 details_known_2 relat2 age2 sex2 ecstat2 details_known_3 relat3 age3 sex3 ecstat3 details_known_4 relat4 age4 sex4 ecstat4 details_known_5 relat5 age5 sex5 ecstat5 details_known_6 relat6 age6 sex6 ecstat6 details_known_7 relat7 age7 sex7 ecstat7 details_known_8 relat8 age8 sex8 ecstat8 armedforces leftreg reservist preg_occ housingneeds housingneeds_type housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h housingneeds_other illness illness_type_4 illness_type_5 illness_type_2 illness_type_6 illness_type_7 illness_type_3 illness_type_9 illness_type_8 illness_type_1 illness_type_10 layear waityear reason reasonother reasonother_value_check prevten new_old homeless ppcodenk ppostcode_full previous_la_known is_previous_la_inferred prevloc_label prevloc reasonpref rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow cbl cap chr letting_allocation_none referral referral_value_check net_income_known incref incfreq earnings net_income_value_check hb has_benefits benefits household_charge nocharge period is_carehome chcharge wchchrg carehome_charges_value_check brent wrent rent_value_check scharge wscharge pscharge wpschrge supcharg wsupchrg tcharge wtcharge scharge_value_check pscharge_value_check supcharg_value_check hbrentshortfall tshortfall_known tshortfall wtshortfall scheme_code scheme_service_name scheme_sensitive SCHTYPE scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_local_authority location_startdate
2 completed s.port@jeemayle.com false 2023-11-26T00:00:00+00:00 2023-11-26T00:00:00+00:00 1 2023 DLUHC DLUHC 1 7 0 2023-11-26 2 2 1 2 HIJKLMN ABCDEFG 1 0 fake address London NW9 5LL false Barnet E09000003 0 2 6 2 2 7 1 1 3 2023-11-24 1 2023-11-25 3 1 4 2 1 4 1 4 0 0 2 35 F 0 2 13 0 0 P 32 M 6 1 R -9 R 10 0 R -9 R 10 1 4 1 2 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 2 7 4 6 2 1 0 TN23 6LZ 1 false Ashford E07000105 1 0 1 0 0 0 0 0 1 2 0 0 1 268 6 1 1 0 2 200.0 100.0 50.0 25.0 40.0 20.0 35.0 17.5 325.0 162.5 1 0 12.0 6.0

4
spec/fixtures/files/lettings_log_csv_export_codes_24.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2024-04-01T00:00:00+01:00,1,,,2023,DLUHC,DLUHC,1,7,0,2023-11-26,2,2,1,,2,HIJKLMN,ABCDEFG,1,1,0,,,fake address,,London,,NW9 5LL,false,Barnet,E09000003,0,2,6,2,2,7,1,1,3,2023-11-24,,,1,2023-11-25,,3,1,4,,2,,4,,1,4,0,0,2,35,,F,0,2,13,,0,0,P,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,2,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,0,,2,,0,0,1,268,,6,1,1,,0,2,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,,
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1_input,postcode_full_input,address_search_value_check,uprn_selection,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2024-04-01T00:00:00+01:00,1,,,2023,DLUHC,DLUHC,1,7,0,2023-11-26,2,2,1,,2,HIJKLMN,ABCDEFG,1,1,0,,,,,,,fake address,,London,,NW9 5LL,false,Barnet,E09000003,0,2,6,2,2,7,1,1,3,2023-11-24,,,1,2023-11-25,,3,1,4,,2,,4,,1,4,0,0,2,35,,F,0,2,13,,0,0,P,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,2,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,0,,2,,0,0,1,268,,6,1,1,,0,2,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,,

1 id status duplicate_set_id created_by is_dpo created_at updated_by updated_at creation_method old_id old_form_id collection_start_year owning_organisation_name managing_organisation_name needstype lettype renewal startdate renttype renttype_detail irproduct irproduct_other lar tenancycode propcode declaration postcode_known uprn_known uprn uprn_confirmed address_line1_input postcode_full_input address_search_value_check uprn_selection address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la first_time_property_let_as_social_housing unitletas rsnvac newprop offered unittype_gn builtype wchair beds voiddate vacdays void_date_value_check majorrepairs mrcdate major_repairs_date_value_check joint startertenancy tenancy tenancyother tenancylength sheltered hhmemb pregnancy_value_check refused hhtype totchild totelder totadult age1 retirement_value_check sex1 ethnic_group ethnic national nationality_all ecstat1 details_known_2 relat2 age2 sex2 ecstat2 details_known_3 relat3 age3 sex3 ecstat3 details_known_4 relat4 age4 sex4 ecstat4 details_known_5 relat5 age5 sex5 ecstat5 details_known_6 relat6 age6 sex6 ecstat6 details_known_7 relat7 age7 sex7 ecstat7 details_known_8 relat8 age8 sex8 ecstat8 armedforces leftreg reservist preg_occ housingneeds housingneeds_type housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h housingneeds_other illness illness_type_4 illness_type_5 illness_type_2 illness_type_6 illness_type_7 illness_type_3 illness_type_9 illness_type_8 illness_type_1 illness_type_10 layear waityear reason reasonother reasonother_value_check prevten new_old homeless ppcodenk ppostcode_full previous_la_known is_previous_la_inferred prevloc_label prevloc reasonpref rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow cbl cap chr accessible_register letting_allocation_none referral referral_value_check net_income_known incref incfreq earnings net_income_value_check hb has_benefits benefits household_charge nocharge period is_carehome chcharge wchchrg carehome_charges_value_check brent wrent rent_value_check scharge wscharge pscharge wpschrge supcharg wsupchrg tcharge wtcharge scharge_value_check pscharge_value_check supcharg_value_check hbrentshortfall tshortfall_known tshortfall wtshortfall scheme_code scheme_service_name scheme_sensitive SCHTYPE scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_local_authority location_startdate
2 completed s.port@jeemayle.com false 2023-11-26T00:00:00+00:00 2024-04-01T00:00:00+01:00 1 2023 DLUHC DLUHC 1 7 0 2023-11-26 2 2 1 2 HIJKLMN ABCDEFG 1 1 0 fake address London NW9 5LL false Barnet E09000003 0 2 6 2 2 7 1 1 3 2023-11-24 1 2023-11-25 3 1 4 2 4 1 4 0 0 2 35 F 0 2 13 0 0 P 32 M 6 1 R -9 R 10 0 R -9 R 10 1 4 1 2 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 2 7 4 6 2 1 0 TN23 6LZ 1 false Ashford E07000105 1 0 1 0 0 0 0 0 1 0 2 0 0 1 268 6 1 1 0 2 200.0 100.0 50.0 25.0 40.0 20.0 35.0 17.5 325.0 162.5 1 0 12.0 6.0

4
spec/fixtures/files/lettings_log_csv_export_labels_23.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,,,2023,DLUHC,DLUHC,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,Rent to Buy,,No,HIJKLMN,ABCDEFG,Yes,No,,,fake address,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,,Yes,4,0,0,2,35,,Female,White,Irish,,Tenant prefers not to say,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,2,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,,Tenant applied directly (no referral or nomination),,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,No,Every 2 weeks,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,,
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1_input,postcode_full_input,address_search_value_check,uprn_selection,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,,,2023,DLUHC,DLUHC,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,Rent to Buy,,No,HIJKLMN,ABCDEFG,Yes,No,,,,,,,fake address,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,,Yes,4,0,0,2,35,,Female,White,Irish,,Tenant prefers not to say,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,2,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,,Tenant applied directly (no referral or nomination),,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,No,Every 2 weeks,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,,

1 id status duplicate_set_id created_by is_dpo created_at updated_by updated_at creation_method old_id old_form_id collection_start_year owning_organisation_name managing_organisation_name needstype lettype renewal startdate renttype renttype_detail irproduct irproduct_other lar tenancycode propcode postcode_known uprn_known uprn uprn_confirmed address_line1_input postcode_full_input address_search_value_check uprn_selection address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la first_time_property_let_as_social_housing unitletas rsnvac newprop offered unittype_gn builtype wchair beds voiddate vacdays void_date_value_check majorrepairs mrcdate major_repairs_date_value_check joint startertenancy tenancy tenancyother tenancylength sheltered declaration hhmemb pregnancy_value_check refused hhtype totchild totelder totadult age1 retirement_value_check sex1 ethnic_group ethnic nationality_all national ecstat1 details_known_2 relat2 age2 sex2 ecstat2 details_known_3 relat3 age3 sex3 ecstat3 details_known_4 relat4 age4 sex4 ecstat4 details_known_5 relat5 age5 sex5 ecstat5 details_known_6 relat6 age6 sex6 ecstat6 details_known_7 relat7 age7 sex7 ecstat7 details_known_8 relat8 age8 sex8 ecstat8 armedforces leftreg reservist preg_occ housingneeds housingneeds_type housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h housingneeds_other illness illness_type_4 illness_type_5 illness_type_2 illness_type_6 illness_type_7 illness_type_3 illness_type_9 illness_type_8 illness_type_1 illness_type_10 layear waityear reason reasonother reasonother_value_check prevten new_old homeless ppcodenk ppostcode_full previous_la_known is_previous_la_inferred prevloc_label prevloc reasonpref rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow cbl cap chr letting_allocation_none referral referral_value_check net_income_known incref incfreq earnings net_income_value_check hb has_benefits benefits household_charge nocharge period is_carehome chcharge wchchrg carehome_charges_value_check brent wrent rent_value_check scharge wscharge pscharge wpschrge supcharg wsupchrg tcharge wtcharge scharge_value_check pscharge_value_check supcharg_value_check hbrentshortfall tshortfall_known tshortfall wtshortfall scheme_code scheme_service_name scheme_sensitive SCHTYPE scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_local_authority location_startdate
2 completed s.port@jeemayle.com false 2023-11-26T00:00:00+00:00 2023-11-26T00:00:00+00:00 single log 2023 DLUHC DLUHC General needs Affordable rent general needs local authority No 2023-11-26 Affordable Rent Affordable Rent Rent to Buy No HIJKLMN ABCDEFG Yes No fake address London NW9 5LL No Barnet E09000003 No Affordable rent basis Tenant abandoned property No 2 House Purpose built Yes 3 2023-11-24 Yes 2023-11-25 Don’t know Yes Assured Shorthold Tenancy (AST) – Fixed term 2 Yes 4 Yes 4 0 0 2 35 Female White Irish Tenant prefers not to say Other Yes Partner 32 Male Not seeking work No Prefers not to say Not known Prefers not to say Prefers not to say Yes Person prefers not to say Not known Person prefers not to say Person prefers not to say Yes – the person is a current or former regular No – they left up to and including 5 years ago Yes No Yes Fully wheelchair accessible housing Yes No No No No No No Yes No No Yes No No No No No No No Less than 1 year 1 year but under 2 years Loss of tied accommodation Other supported housing 2 No Yes TN23 6LZ Yes No Ashford E07000105 Yes Yes No No Yes Tenant applied directly (no referral or nomination) Yes No Weekly 268 Universal Credit housing element Yes All No Every 2 weeks 200.0 100.0 50.0 25.0 40.0 20.0 35.0 17.5 325.0 162.5 Yes Yes 12.0 6.0

4
spec/fixtures/files/lettings_log_csv_export_labels_24.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2024-04-01T00:00:00+01:00,single log,,,2023,DLUHC,DLUHC,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,Rent to Buy,,No,HIJKLMN,ABCDEFG,Yes,Yes,No,,,fake address,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,4,,Yes,4,0,0,2,35,,Female,White,Irish,Tenant prefers not to say,,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,2,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,,Tenant applied directly (no referral or nomination),,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,No,Every 2 weeks,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,,
id,status,duplicate_set_id,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,postcode_known,uprn_known,uprn,uprn_confirmed,address_line1_input,postcode_full_input,address_search_value_check,uprn_selection,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,details_known_2,relat2,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate
,completed,,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2024-04-01T00:00:00+01:00,single log,,,2023,DLUHC,DLUHC,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,Rent to Buy,,No,HIJKLMN,ABCDEFG,Yes,Yes,No,,,,,,,fake address,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,4,,Yes,4,0,0,2,35,,Female,White,Irish,Tenant prefers not to say,,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,2,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,,Tenant applied directly (no referral or nomination),,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,No,Every 2 weeks,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,,

1 id status duplicate_set_id created_by is_dpo created_at updated_by updated_at creation_method old_id old_form_id collection_start_year owning_organisation_name managing_organisation_name needstype lettype renewal startdate renttype renttype_detail irproduct irproduct_other lar tenancycode propcode declaration postcode_known uprn_known uprn uprn_confirmed address_line1_input postcode_full_input address_search_value_check uprn_selection address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la first_time_property_let_as_social_housing unitletas rsnvac newprop offered unittype_gn builtype wchair beds voiddate vacdays void_date_value_check majorrepairs mrcdate major_repairs_date_value_check joint startertenancy tenancy tenancyother tenancylength sheltered hhmemb pregnancy_value_check refused hhtype totchild totelder totadult age1 retirement_value_check sex1 ethnic_group ethnic national nationality_all ecstat1 details_known_2 relat2 age2 sex2 ecstat2 details_known_3 relat3 age3 sex3 ecstat3 details_known_4 relat4 age4 sex4 ecstat4 details_known_5 relat5 age5 sex5 ecstat5 details_known_6 relat6 age6 sex6 ecstat6 details_known_7 relat7 age7 sex7 ecstat7 details_known_8 relat8 age8 sex8 ecstat8 armedforces leftreg reservist preg_occ housingneeds housingneeds_type housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h housingneeds_other illness illness_type_4 illness_type_5 illness_type_2 illness_type_6 illness_type_7 illness_type_3 illness_type_9 illness_type_8 illness_type_1 illness_type_10 layear waityear reason reasonother reasonother_value_check prevten new_old homeless ppcodenk ppostcode_full previous_la_known is_previous_la_inferred prevloc_label prevloc reasonpref rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow cbl cap chr accessible_register letting_allocation_none referral referral_value_check net_income_known incref incfreq earnings net_income_value_check hb has_benefits benefits household_charge nocharge period is_carehome chcharge wchchrg carehome_charges_value_check brent wrent rent_value_check scharge wscharge pscharge wpschrge supcharg wsupchrg tcharge wtcharge scharge_value_check pscharge_value_check supcharg_value_check hbrentshortfall tshortfall_known tshortfall wtshortfall scheme_code scheme_service_name scheme_sensitive SCHTYPE scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_local_authority location_startdate
2 completed s.port@jeemayle.com false 2023-11-26T00:00:00+00:00 2024-04-01T00:00:00+01:00 single log 2023 DLUHC DLUHC General needs Affordable rent general needs local authority No 2023-11-26 Affordable Rent Affordable Rent Rent to Buy No HIJKLMN ABCDEFG Yes Yes No fake address London NW9 5LL No Barnet E09000003 No Affordable rent basis Tenant abandoned property No 2 House Purpose built Yes 3 2023-11-24 Yes 2023-11-25 Don’t know Yes Assured Shorthold Tenancy (AST) – Fixed term 2 4 Yes 4 0 0 2 35 Female White Irish Tenant prefers not to say Other Yes Partner 32 Male Not seeking work No Prefers not to say Not known Prefers not to say Prefers not to say Yes Person prefers not to say Not known Person prefers not to say Person prefers not to say Yes – the person is a current or former regular No – they left up to and including 5 years ago Yes No Yes Fully wheelchair accessible housing Yes No No No No No No Yes No No Yes No No No No No No No Less than 1 year 1 year but under 2 years Loss of tied accommodation Other supported housing 2 No Yes TN23 6LZ Yes No Ashford E07000105 Yes Yes No No Yes No Tenant applied directly (no referral or nomination) Yes No Weekly 268 Universal Credit housing element Yes All No Every 2 weeks 200.0 100.0 50.0 25.0 40.0 20.0 35.0 17.5 325.0 162.5 Yes Yes 12.0 6.0

4
spec/fixtures/files/sales_logs_csv_export_codes_23.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-01-01T00:00:00+00:00,,2023,1,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,2,8,,,,1,1,2,1,1,0,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,1,2,1,30,X,17,17,,18,1,1,P,35,X,17,,,13,1,1,3,C,14,X,9,X,-9,X,3,R,-9,R,10,,,,,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-01-01T00:00:00+00:00,,2023,1,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,2,8,,,,1,1,2,1,1,0,,,,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,1,2,1,30,X,17,17,,18,1,1,P,35,X,17,,,13,1,1,3,C,14,X,9,X,-9,X,3,R,-9,R,10,,,,,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0

1 id status duplicate_set_id created_at updated_at old_form_id collection_start_year creation_method is_dpo owning_organisation_name managing_organisation_name created_by day month year purchid ownershipsch type othtype companybuy buylivein jointpur jointmore beds proptype builtype pcodenk uprn uprn_confirmed address_line1_input postcode_full_input uprn_selection address_line1 address_line2 town_or_city county pcode1 pcode2 la_known la la_label wchair noint privacynotice age1 sex1 ethnic_group ethnic nationality_all national ecstat1 buy1livein relat2 age2 sex2 ethnic_group2 ethnicbuy2 nationality_all_buyer2 nationalbuy2 ecstat2 buy2livein hholdcount relat3 age3 sex3 ecstat3 relat4 age4 sex4 ecstat4 relat5 age5 sex5 ecstat5 relat6 age6 sex6 ecstat6 prevten ppcodenk ppostc1 ppostc2 previous_la_known prevloc prevloc_label pregyrha pregother pregla pregghb pregblank buy2living prevtenbuy2 hhregres hhregresstill armedforcesspouse disabled wheel income1nk income1 inc1mort income2nk income2 inc2mort hb savingsnk savings prevown prevshared proplen staircase stairbought stairowned staircasesale resale exday exmonth exyear hoday homonth hoyear lanomagr soctenant frombeds fromprop socprevten value equity mortgageused mortgage mortgagelender mortgagelenderother mortlen extrabor deposit cashdis mrent has_mscharge mscharge discount grant
2 completed 2023-12-08T00:00:00+00:00 2024-01-01T00:00:00+00:00 2023 1 false DLUHC DLUHC billyboy@eyeklaud.com 8 12 2023 2 8 1 1 2 1 1 0 Address line 1 Town or city SW1A 1AA 1 E09000003 Barnet 1 2 1 30 X 17 17 18 1 1 P 35 X 17 13 1 1 3 C 14 X 9 X -9 X 3 R -9 R 10 1 1 0 1 1 1 1 3 1 4 5 1 1 0 10000 1 0 10000 1 4 1 1 2 10 110000.0 1 20000.0 5 10 1 80000.0 1 100.0 10000.0

4
spec/fixtures/files/sales_logs_csv_export_codes_24.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,beds,proptype,builtype,pcodenk,wchair,age1,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-05-01T00:00:00+01:00,,2023,1,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,2,8,,,,1,1,2,1,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,2,1,1,0,1,30,X,17,17,18,,1,1,P,35,X,17,,13,,1,1,3,C,14,X,9,X,-9,X,3,R,-9,R,10,,,,,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,beds,proptype,builtype,pcodenk,wchair,age1,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-05-01T00:00:00+01:00,,2023,1,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,2,8,,,,1,1,2,1,,,,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,2,1,1,0,1,30,X,17,17,18,,1,1,P,35,X,17,,13,,1,1,3,C,14,X,9,X,-9,X,3,R,-9,R,10,,,,,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0

1 id status duplicate_set_id created_at updated_at old_form_id collection_start_year creation_method is_dpo owning_organisation_name managing_organisation_name created_by day month year purchid ownershipsch type othtype companybuy buylivein jointpur jointmore noint privacynotice uprn uprn_confirmed address_line1_input postcode_full_input uprn_selection address_line1 address_line2 town_or_city county pcode1 pcode2 la_known la la_label beds proptype builtype pcodenk wchair age1 sex1 ethnic_group ethnic national nationality_all ecstat1 buy1livein relat2 age2 sex2 ethnic_group2 ethnicbuy2 nationalbuy2 nationality_all_buyer2 ecstat2 buy2livein hholdcount relat3 age3 sex3 ecstat3 relat4 age4 sex4 ecstat4 relat5 age5 sex5 ecstat5 relat6 age6 sex6 ecstat6 prevten ppcodenk ppostc1 ppostc2 previous_la_known prevloc prevloc_label pregyrha pregother pregla pregghb pregblank buy2living prevtenbuy2 hhregres hhregresstill armedforcesspouse disabled wheel income1nk income1 inc1mort income2nk income2 inc2mort hb savingsnk savings prevown prevshared proplen staircase stairbought stairowned staircasesale resale exday exmonth exyear hoday homonth hoyear lanomagr soctenant frombeds fromprop socprevten value equity mortgageused mortgage mortgagelender mortgagelenderother mortlen extrabor deposit cashdis mrent has_mscharge mscharge discount grant
2 completed 2023-12-08T00:00:00+00:00 2024-05-01T00:00:00+01:00 2023 1 false DLUHC DLUHC billyboy@eyeklaud.com 8 12 2023 2 8 1 1 2 1 Address line 1 Town or city SW1A 1AA 1 E09000003 Barnet 2 1 1 0 1 30 X 17 17 18 1 1 P 35 X 17 13 1 1 3 C 14 X 9 X -9 X 3 R -9 R 10 1 1 0 1 1 1 1 3 1 4 5 1 1 0 10000 1 0 10000 1 4 1 1 2 10 110000.0 1 20000.0 5 10 1 80000.0 1 100.0 10000.0

4
spec/fixtures/files/sales_logs_csv_export_labels_23.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-01-01T00:00:00+00:00,,2023,single log,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,2,Flat or maisonette,Purpose built,0,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,Yes,Yes,1,30,Non-binary,Buyer prefers not to say,17,,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,,Buyer prefers not to say,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,"In government training into work, such as New Deal",Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,No,,,No,,,1,1,1,1,,Don't know,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,"Don’t know ",No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,nationality_all,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-01-01T00:00:00+00:00,,2023,single log,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,2,Flat or maisonette,Purpose built,0,,,,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,Yes,Yes,1,30,Non-binary,Buyer prefers not to say,17,,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,,Buyer prefers not to say,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,"In government training into work, such as New Deal",Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,No,,,No,,,1,1,1,1,,Don't know,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,"Don’t know ",No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0

1 id status duplicate_set_id created_at updated_at old_form_id collection_start_year creation_method is_dpo owning_organisation_name managing_organisation_name created_by day month year purchid ownershipsch type othtype companybuy buylivein jointpur jointmore beds proptype builtype pcodenk uprn uprn_confirmed address_line1_input postcode_full_input uprn_selection address_line1 address_line2 town_or_city county pcode1 pcode2 la_known la la_label wchair noint privacynotice age1 sex1 ethnic_group ethnic nationality_all national ecstat1 buy1livein relat2 age2 sex2 ethnic_group2 ethnicbuy2 nationality_all_buyer2 nationalbuy2 ecstat2 buy2livein hholdcount relat3 age3 sex3 ecstat3 relat4 age4 sex4 ecstat4 relat5 age5 sex5 ecstat5 relat6 age6 sex6 ecstat6 prevten ppcodenk ppostc1 ppostc2 previous_la_known prevloc prevloc_label pregyrha pregother pregla pregghb pregblank buy2living prevtenbuy2 hhregres hhregresstill armedforcesspouse disabled wheel income1nk income1 inc1mort income2nk income2 inc2mort hb savingsnk savings prevown prevshared proplen staircase stairbought stairowned staircasesale resale exday exmonth exyear hoday homonth hoyear lanomagr soctenant frombeds fromprop socprevten value equity mortgageused mortgage mortgagelender mortgagelenderother mortlen extrabor deposit cashdis mrent has_mscharge mscharge discount grant
2 completed 2023-12-08T00:00:00+00:00 2024-01-01T00:00:00+00:00 2023 single log false DLUHC DLUHC billyboy@eyeklaud.com 8 12 2023 Yes - a discounted ownership scheme Right to Acquire (RTA) Yes Yes 2 Flat or maisonette Purpose built 0 Address line 1 Town or city SW1A 1AA 1 E09000003 Barnet Yes Yes 1 30 Non-binary Buyer prefers not to say 17 United Kingdom Full-time - 30 hours or more Yes Partner 35 Non-binary Buyer prefers not to say Buyer prefers not to say Full-time - 30 hours or more Yes 3 Child 14 Non-binary Child under 16 Other Not known Non-binary In government training into work, such as New Deal Prefers not to say Not known Prefers not to say Prefers not to say Local authority tenant No No 1 1 1 1 Don't know Yes Yes No Yes Yes Yes 10000 Yes Yes 10000 Yes Don’t know No Yes No 10 110000.0 Yes 20000.0 Cambridge Building Society 10 Yes 80000.0 Yes 100.0 10000.0

4
spec/fixtures/files/sales_logs_csv_export_labels_24.csv vendored

@ -1,2 +1,2 @@
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,beds,proptype,builtype,pcodenk,wchair,age1,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-05-01T00:00:00+01:00,,2023,single log,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,2,Flat or maisonette,Purpose built,0,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,Buyer prefers not to say,,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,"In government training into work, such as New Deal",Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,No,,,No,,,1,1,1,1,,Don't know,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,"Don’t know ",No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0
id,status,duplicate_set_id,created_at,updated_at,old_form_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,managing_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,beds,proptype,builtype,pcodenk,wchair,age1,sex1,ethnic_group,ethnic,national,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
,completed,,2023-12-08T00:00:00+00:00,2024-05-01T00:00:00+01:00,,2023,single log,false,DLUHC,DLUHC,billyboy@eyeklaud.com,8,12,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,,,,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,2,Flat or maisonette,Purpose built,0,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,Buyer prefers not to say,,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,"In government training into work, such as New Deal",Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,No,,,No,,,1,1,1,1,,Don't know,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,"Don’t know ",No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0

1 id status duplicate_set_id created_at updated_at old_form_id collection_start_year creation_method is_dpo owning_organisation_name managing_organisation_name created_by day month year purchid ownershipsch type othtype companybuy buylivein jointpur jointmore noint privacynotice uprn uprn_confirmed address_line1_input postcode_full_input uprn_selection address_line1 address_line2 town_or_city county pcode1 pcode2 la_known la la_label beds proptype builtype pcodenk wchair age1 sex1 ethnic_group ethnic national nationality_all ecstat1 buy1livein relat2 age2 sex2 ethnic_group2 ethnicbuy2 nationalbuy2 nationality_all_buyer2 ecstat2 buy2livein hholdcount relat3 age3 sex3 ecstat3 relat4 age4 sex4 ecstat4 relat5 age5 sex5 ecstat5 relat6 age6 sex6 ecstat6 prevten ppcodenk ppostc1 ppostc2 previous_la_known prevloc prevloc_label pregyrha pregother pregla pregghb pregblank buy2living prevtenbuy2 hhregres hhregresstill armedforcesspouse disabled wheel income1nk income1 inc1mort income2nk income2 inc2mort hb savingsnk savings prevown prevshared proplen staircase stairbought stairowned staircasesale resale exday exmonth exyear hoday homonth hoyear lanomagr soctenant frombeds fromprop socprevten value equity mortgageused mortgage mortgagelender mortgagelenderother mortlen extrabor deposit cashdis mrent has_mscharge mscharge discount grant
2 completed 2023-12-08T00:00:00+00:00 2024-05-01T00:00:00+01:00 2023 single log false DLUHC DLUHC billyboy@eyeklaud.com 8 12 2023 Yes - a discounted ownership scheme Right to Acquire (RTA) Yes Yes Yes 1 Address line 1 Town or city SW1A 1AA 1 E09000003 Barnet 2 Flat or maisonette Purpose built 0 Yes 30 Non-binary Buyer prefers not to say 17 United Kingdom Full-time - 30 hours or more Yes Partner 35 Non-binary Buyer prefers not to say Buyer prefers not to say Full-time - 30 hours or more Yes 3 Child 14 Non-binary Child under 16 Other Not known Non-binary In government training into work, such as New Deal Prefers not to say Not known Prefers not to say Prefers not to say Local authority tenant No No 1 1 1 1 Don't know Yes Yes No Yes Yes Yes 10000 Yes Yes 10000 Yes Don’t know No Yes No 10 110000.0 Yes 20000.0 Cambridge Building Society 10 Yes 80000.0 Yes 100.0 10000.0

40
spec/models/form/lettings/pages/address_fallback_spec.rb

@ -0,0 +1,40 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::AddressFallback, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2024, 4, 1))) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_line1 address_line2 town_or_city county postcode_full])
end
it "has the correct id" do
expect(page.id).to eq("address")
end
it "has the correct header" do
expect(page.header).to eq("Q12 - What is the property's address?")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "is_supported_housing?" => false, "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => nil, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_known" => 0, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "address_options_present?" => false },
])
end
end

33
spec/models/form/lettings/pages/address_matcher_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::AddressMatcher, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_line1_input postcode_full_input])
end
it "has the correct id" do
expect(page.id).to eq("address_matcher")
end
it "has the correct header" do
expect(page.header).to eq("Find an address")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "is_supported_housing?" => false, "uprn_known" => nil }, { "is_supported_housing?" => false, "uprn_known" => 0 }, { "is_supported_housing?" => false, "uprn_confirmed" => 0 }])
end
end

46
spec/models/form/lettings/pages/no_address_found_spec.rb

@ -0,0 +1,46 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::NoAddressFound, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:log) { create(:lettings_log) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_search_value_check])
end
it "has the correct id" do
expect(page.id).to eq("no_address_found")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "address_options_present?" => false }])
end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
it "has the correct title_text" do
expect(page.title_text).to eq({ "arguments" => [], "translation" => "soft_validations.no_address_found.title_text" })
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({ "arguments" => [], "translation" => "soft_validations.no_address_found.informative_text" })
end
it "has the correct interruption_screen_question_ids" do
expect(page.interruption_screen_question_ids).to eq(%w[address_line1_input])
end
end

44
spec/models/form/lettings/pages/uprn_selection_spec.rb

@ -0,0 +1,44 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::UprnSelection, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:log) { create(:lettings_log) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[uprn_selection])
end
it "has the correct id" do
expect(page.id).to eq("uprn_selection")
end
it "has the correct header" do
expect(page.header).to eq("We found some addresses that might be this property")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct skip text" do
"Search for address again"
end
it "has the correct skip_href" do
expect(page.skip_href(log)).to eq(
"/lettings-logs/#{log.id}/address-matcher",
)
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "address_options_present?" => true }])
end
end

42
spec/models/form/lettings/pages/uprn_spec.rb

@ -5,7 +5,13 @@ RSpec.describe Form::Lettings::Pages::Uprn, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2024, 4, 1))) }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }
before do
allow(form).to receive(:start_year_after_2024?).and_return(false)
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@ -31,10 +37,6 @@ RSpec.describe Form::Lettings::Pages::Uprn, type: :model do
expect(page.depends_on).to eq([{ "is_supported_housing?" => false }])
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Enter address instead")
end
describe "has correct skip_href" do
context "when log is nil" do
it "is nil" do
@ -45,10 +47,32 @@ RSpec.describe Form::Lettings::Pages::Uprn, type: :model do
context "when log is present" do
let(:log) { create(:lettings_log) }
it "points to address page" do
expect(page.skip_href(log)).to eq(
"/lettings-logs/#{log.id}/address",
)
context "with 2023/24 form" do
it "points to address page" do
expect(page.skip_href(log)).to eq(
"/lettings-logs/#{log.id}/address",
)
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Enter address instead")
end
end
context "with 2024/25 form" do
before do
allow(form).to receive(:start_year_after_2024?).and_return(true)
end
it "points to address search page" do
expect(page.skip_href(log)).to eq(
"/lettings-logs/#{log.id}/address-matcher",
)
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Search for address instead")
end
end
end
end

62
spec/models/form/lettings/questions/address_line1_for_address_matcher_spec.rb

@ -0,0 +1,62 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::AddressLine1ForAddressMatcher, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("address_line1_input")
end
it "has the correct header" do
expect(question.header).to eq("Address line 1")
end
it "has the correct error label" do
expect(question.error_label).to eq("Address line 1")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Find address")
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("text")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer label" do
expect(question.answer_label(log)).to eq("Address line 1\nAA1 1AA")
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
it "has the correct disable_clearing_if_not_routed_or_dynamic_answer_options value" do
expect(question.disable_clearing_if_not_routed_or_dynamic_answer_options).to eq(true)
end
end

44
spec/models/form/lettings/questions/no_address_found_spec.rb

@ -0,0 +1,44 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::NoAddressFound, type: :model do
subject(:question) { described_class.new(nil, question_definition, page) }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("address_search_value_check")
end
it "has the correct header" do
expect(question.header).to eq("No address found")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to be_nil
end
it "has the correct type" do
expect(question.type).to eq("interruption_screen")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer_options" do
expect(question.answer_options).to be_nil
end
it "has the correct hidden_in_check_answers" do
expect(question.hidden_in_check_answers).to eq(true)
end
end

62
spec/models/form/lettings/questions/postcode_for_address_matcher_spec.rb

@ -0,0 +1,62 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::PostcodeForAddressMatcher, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("postcode_full_input")
end
it "has the correct header" do
expect(question.header).to eq("Postcode")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq(nil)
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("text")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer label" do
expect(question.answer_label(log)).to eq("AA1 1AA")
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct inferred_answers value" do
expect(question.inferred_answers).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
it "has the correct disable_clearing_if_not_routed_or_dynamic_answer_options value" do
expect(question.disable_clearing_if_not_routed_or_dynamic_answer_options).to eq(true)
end
end

102
spec/models/form/lettings/questions/uprn_selection_spec.rb

@ -0,0 +1,102 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::UprnSelection, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:lettings_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:address_client_instance) { AddressClient.new(log.address_string) }
before do
allow(AddressClient).to receive(:new).and_return(address_client_instance)
allow(address_client_instance).to receive(:call)
allow(address_client_instance).to receive(:result).and_return([{
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
}])
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("uprn_selection")
end
it "has the correct header" do
expect(question.header).to eq("Select the correct address")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Select the correct address")
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer options" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.answer_options(log)).to eq({ "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" }, "UPRN" => { "value" => "full address" }, "divider" => { "value" => true } })
end
it "has the correct displayed answer options" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.displayed_answer_options(log)).to eq({ "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" }, "UPRN" => { "value" => "full address" }, "divider" => { "value" => true } })
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
context "when the log has address options" do
it "has the correct hidden_in_check_answers?" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: '{"results": {"0": "address_0", "1": "address_1", "2": "address_2"}}', headers: {})
expect(question.hidden_in_check_answers?(log)).to eq(false)
end
end
context "when the log does not have address options" do
before do
allow(address_client_instance).to receive(:result).and_return(nil)
end
it "has the correct hidden_in_check_answers?" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.hidden_in_check_answers?(log)).to eq(true)
end
end
end

5
spec/models/form/lettings/subsections/property_information_spec.rb

@ -10,7 +10,7 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do
end
describe "pages" do
let(:section) { instance_double(Form::Sales::Sections::Household, form:) }
let(:section) { instance_double(Form::Lettings::Sections::Household, form:) }
let(:form) { instance_double(Form, start_date:) }
before do
@ -91,6 +91,9 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do
%w[
uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address
property_local_authority
local_authority_min_rent_value_check

40
spec/models/form/sales/pages/address_fallback_spec.rb

@ -0,0 +1,40 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::AddressFallback, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2024, 4, 1))) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_line1 address_line2 town_or_city county postcode_full])
end
it "has the correct id" do
expect(page.id).to eq("address")
end
it "has the correct header" do
expect(page.header).to eq("Q12 - What is the property's address?")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => nil, "address_options_present?" => false },
{ "uprn_known" => 0, "address_options_present?" => false },
{ "uprn_confirmed" => 0, "address_options_present?" => false },
])
end
end

33
spec/models/form/sales/pages/address_matcher_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::AddressMatcher, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_line1_input postcode_full_input])
end
it "has the correct id" do
expect(page.id).to eq("address_matcher")
end
it "has the correct header" do
expect(page.header).to eq("Find an address")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "uprn_known" => nil }, { "uprn_known" => 0 }, { "uprn_confirmed" => 0 }])
end
end

46
spec/models/form/sales/pages/no_address_found_spec.rb

@ -0,0 +1,46 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::NoAddressFound, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:log) { create(:sales_log) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[address_search_value_check])
end
it "has the correct id" do
expect(page.id).to eq("no_address_found")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "address_options_present?" => false }])
end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
it "has the correct title_text" do
expect(page.title_text).to eq({ "arguments" => [], "translation" => "soft_validations.no_address_found.title_text" })
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({ "arguments" => [], "translation" => "soft_validations.no_address_found.informative_text" })
end
it "has the correct interruption_screen_question_ids" do
expect(page.interruption_screen_question_ids).to eq(%w[address_line1_input])
end
end

44
spec/models/form/sales/pages/uprn_selection_spec.rb

@ -0,0 +1,44 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::UprnSelection, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:log) { create(:sales_log) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[uprn_selection])
end
it "has the correct id" do
expect(page.id).to eq("uprn_selection")
end
it "has the correct header" do
expect(page.header).to eq("We found some addresses that might be this property")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct skip text" do
"Search for address again"
end
it "has the correct skip_href" do
expect(page.skip_href(log)).to eq(
"/sales-logs/#{log.id}/address-matcher",
)
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "address_options_present?" => true }])
end
end

42
spec/models/form/sales/pages/uprn_spec.rb

@ -5,7 +5,13 @@ RSpec.describe Form::Sales::Pages::Uprn, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }
before do
allow(form).to receive(:start_year_after_2024?).and_return(false)
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@ -31,10 +37,6 @@ RSpec.describe Form::Sales::Pages::Uprn, type: :model do
expect(page.depends_on).to be_nil
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Enter address instead")
end
describe "has correct skip_href" do
context "when log is nil" do
it "is nil" do
@ -45,10 +47,32 @@ RSpec.describe Form::Sales::Pages::Uprn, type: :model do
context "when log is present" do
let(:log) { create(:sales_log) }
it "points to address page" do
expect(page.skip_href(log)).to eq(
"/sales-logs/#{log.id}/address",
)
context "with 2023/24 form" do
it "points to address page" do
expect(page.skip_href(log)).to eq(
"/sales-logs/#{log.id}/address",
)
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Enter address instead")
end
end
context "with 2024/25 form" do
before do
allow(form).to receive(:start_year_after_2024?).and_return(true)
end
it "points to address search page" do
expect(page.skip_href(log)).to eq(
"/sales-logs/#{log.id}/address-matcher",
)
end
it "has correct skip_text" do
expect(page.skip_text).to eq("Search for address instead")
end
end
end
end

62
spec/models/form/sales/questions/address_line1_for_address_matcher_spec.rb

@ -0,0 +1,62 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::AddressLine1ForAddressMatcher, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("address_line1_input")
end
it "has the correct header" do
expect(question.header).to eq("Address line 1")
end
it "has the correct error label" do
expect(question.error_label).to eq("Address line 1")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Find address")
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("text")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer label" do
expect(question.answer_label(log)).to eq("Address line 1\nAA1 1AA")
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
it "has the correct disable_clearing_if_not_routed_or_dynamic_answer_options value" do
expect(question.disable_clearing_if_not_routed_or_dynamic_answer_options).to eq(true)
end
end

44
spec/models/form/sales/questions/no_address_found_spec.rb

@ -0,0 +1,44 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::NoAddressFound, type: :model do
subject(:question) { described_class.new(nil, question_definition, page) }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("address_search_value_check")
end
it "has the correct header" do
expect(question.header).to eq("No address found")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to be_nil
end
it "has the correct type" do
expect(question.type).to eq("interruption_screen")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer_options" do
expect(question.answer_options).to be_nil
end
it "has the correct hidden_in_check_answers" do
expect(question.hidden_in_check_answers).to eq(true)
end
end

62
spec/models/form/sales/questions/postcode_for_address_matcher_spec.rb

@ -0,0 +1,62 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::PostcodeForAddressMatcher, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("postcode_full_input")
end
it "has the correct header" do
expect(question.header).to eq("Postcode")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq(nil)
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("text")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer label" do
expect(question.answer_label(log)).to eq("AA1 1AA")
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct inferred_answers value" do
expect(question.inferred_answers).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
it "has the correct disable_clearing_if_not_routed_or_dynamic_answer_options value" do
expect(question.disable_clearing_if_not_routed_or_dynamic_answer_options).to eq(true)
end
end

102
spec/models/form/sales/questions/uprn_selection_spec.rb

@ -0,0 +1,102 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::UprnSelection, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log, :in_progress, address_line1_input: "Address line 1", postcode_full_input: "AA1 1AA") }
let(:address_client_instance) { AddressClient.new(log.address_string) }
before do
allow(AddressClient).to receive(:new).and_return(address_client_instance)
allow(address_client_instance).to receive(:call)
allow(address_client_instance).to receive(:result).and_return([{
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
}])
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("uprn_selection")
end
it "has the correct header" do
expect(question.header).to eq("Select the correct address")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Select the correct address")
end
it "has the correct question_number" do
expect(question.question_number).to eq(nil)
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct answer options" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.answer_options(log)).to eq({ "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" }, "UPRN" => { "value" => "full address" }, "divider" => { "value" => true } })
end
it "has the correct displayed answer options" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.displayed_answer_options(log)).to eq({ "uprn_not_listed" => { "value" => "The address is not listed, I want to enter the address manually" }, "UPRN" => { "value" => "full address" }, "divider" => { "value" => true } })
end
it "has the correct inferred check answers value" do
expect(question.inferred_check_answers_value).to be_nil
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to be_nil
end
context "when the log has address options" do
it "has the correct hidden_in_check_answers?" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: '{"results": {"0": "address_0", "1": "address_1", "2": "address_2"}}', headers: {})
expect(question.hidden_in_check_answers?(log)).to eq(false)
end
end
context "when the log does not have address options" do
before do
allow(address_client_instance).to receive(:result).and_return(nil)
end
it "has the correct hidden_in_check_answers?" do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: "", headers: {})
expect(question.hidden_in_check_answers?(log)).to eq(true)
end
end
end

18
spec/models/form/sales/subsections/property_information_spec.rb

@ -1,10 +1,8 @@
require "rails_helper"
RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
subject(:property_information) { described_class.new(subsection_id, subsection_definition, section) }
subject(:property_information) { described_class.new(nil, nil, section) }
let(:subsection_id) { nil }
let(:subsection_definition) { nil }
let(:section) { instance_double(Form::Sales::Sections::PropertyInformation) }
it "has correct section" do
@ -12,7 +10,12 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
end
describe "pages" do
let(:section) { instance_double(Form::Sales::Sections::Household, form: instance_double(Form, start_date:)) }
let(:section) { instance_double(Form::Sales::Sections::Household, form:) }
let(:form) { instance_double(Form, start_date:) }
before do
allow(form).to receive(:start_year_after_2024?).and_return(false)
end
context "when 2022" do
let(:start_date) { Time.utc(2022, 2, 8) }
@ -67,11 +70,18 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
context "when 2024" do
let(:start_date) { Time.utc(2024, 2, 8) }
before do
allow(form).to receive(:start_year_after_2024?).and_return(true)
end
it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq(
%w[
uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address
property_local_authority
local_authority_buyer_1_income_max_value_check

68
spec/services/address_client_spec.rb

@ -0,0 +1,68 @@
require "rails_helper"
describe AddressClient do
let(:client) { described_class.new("123") }
let(:valid_response) do
{ results: [{ DPA: { UPRN: "12345" } }] }.to_json
end
def stub_api_request(body:, status: 200)
stub_request(:get, "https://api.os.uk/search/places/v1/find?key=OS_DATA_KEY&maxresults=10&minmatch=0.4&query=123")
.to_return(status:, body:, headers: {})
end
describe "call" do
context "when json parse error" do
before do
stub_api_request(body: "{", status: 200)
client.call
end
it "returns error" do
expect(client.error).to eq("Address is not recognised. Check the address, or enter the UPRN")
end
end
context "when http error" do
before do
stub_api_request(body: valid_response, status: 500)
client.call
end
it "returns error" do
expect(client.error).to eq("Address is not recognised. Check the address, or enter the UPRN")
end
end
context "when results empty" do
before do
stub_api_request(body: {}.to_json)
client.call
end
it "returns error" do
expect(client.error).to eq("Address is not recognised. Check the address, or enter the UPRN")
end
end
context "with results" do
before do
stub_api_request(body: valid_response)
client.call
end
it "returns result" do
expect(client.result).to eq([{ "UPRN" => "12345" }])
end
it "returns no error" do
expect(client.error).to be_nil
end
end
end
end

51
spec/services/address_data_presenter_spec.rb

@ -0,0 +1,51 @@
require "rails_helper"
describe AddressDataPresenter do
let(:data) do
JSON.parse(
'{
"UPRN": "UPRN",
"UDPRN": "UDPRN",
"ADDRESS": "full address",
"SUB_BUILDING_NAME": "0",
"BUILDING_NAME": "building name",
"THOROUGHFARE_NAME": "thoroughfare",
"POST_TOWN": "posttown",
"POSTCODE": "postcode",
"STATUS": "APPROVED",
"DOUBLE_DEPENDENT_LOCALITY": "double dependent locality",
"DEPENDENT_LOCALITY": "dependent locality",
"CLASSIFICATION_CODE": "classification code",
"LOCAL_CUSTODIAN_CODE_DESCRIPTION": "LONDON BOROUGH OF HARINGEY",
"BLPU_STATE_CODE": "2",
"BLPU_STATE_CODE_DESCRIPTION": "In use",
"LAST_UPDATE_DATE": "31/07/2020",
"ENTRY_DATE": "30/01/2015",
"BLPU_STATE_DATE": "30/01/2015",
"LANGUAGE": "EN",
"MATCH_DESCRIPTION": "EXACT",
"MATCH": "1.0"
}',
)
end
let(:presenter) { described_class.new(data) }
describe "#uprn" do
it "returns uprn" do
expect(presenter.uprn).to eq("UPRN")
end
end
describe "#match" do
it "returns match" do
expect(presenter.match).to eq("1.0")
end
end
describe "#address" do
it "returns address" do
expect(presenter.address).to eq("full address")
end
end
end

25
spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

@ -87,6 +87,24 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
stub_request(:get, /api\.postcodes\.io/)
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
stub_request(:get, /api\.os\.uk\/search\/places\/v1\/find/)
.to_return(status: 200, body: { results: [{ DPA: { MATCH: 0.9, BUILDING_NAME: "result address line 1", POST_TOWN: "result town or city", POSTCODE: "AA1 1AA", UPRN: "12345" } }] }.to_json, headers: {})
stub_request(:get, /api\.os\.uk\/search\/places\/v1\/uprn/)
.to_return(status: 200, body: '{"status":200,"results":[{"DPA":{
"PO_BOX_NUMBER": "fake",
"ORGANISATION_NAME": "org",
"DEPARTMENT_NAME": "name",
"SUB_BUILDING_NAME": "building",
"BUILDING_NAME": "name",
"BUILDING_NUMBER": "number",
"DEPENDENT_THOROUGHFARE_NAME": "data",
"THOROUGHFARE_NAME": "thing",
"POST_TOWN": "London",
"POSTCODE": "SE2 6RT"
}}]}', headers: {})
parser.valid?
end
@ -773,12 +791,11 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
describe "#validate_nulls" do
context "when non-setup questions are null" do
let(:attributes) { setup_section_params.merge({ field_16: "", field_17: "", field_19: "" }) }
let(:attributes) { setup_section_params.merge({ field_43: "" }) }
it "fetches the question's check_answer_label if it exists, otherwise it gets the question's header" do
parser.valid?
expect(parser.errors[:field_17]).to eql(["You must answer address line 1"])
expect(parser.errors[:field_19]).to eql(["You must answer town or city"])
expect(parser.errors[:field_43]).to eql(["You must answer lead tenant’s gender identity"])
end
end
end
@ -1444,7 +1461,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
let(:attributes) { setup_section_params.merge({ field_16: "1234567890123" }) }
it "adds an appropriate error" do
expect(parser.errors[:field_16]).to eql(["UPRN is not recognised. Check the number, or enter the address"])
expect(parser.errors[:field_16]).to eql(["UPRN must be 12 digits or less"])
end
end

4
spec/services/bulk_upload/sales/year2024/row_parser_spec.rb

@ -50,6 +50,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
field_20: "1",
field_21: "1",
field_22: "12",
field_23: "Address line 1",
field_27: "CR0",
field_28: "4BB",
field_29: "E09000008",
@ -242,6 +243,9 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
stub_request(:get, /api\.postcodes\.io/)
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: { results: [{ DPA: { MATCH: 0.9, BUILDING_NAME: "result address line 1", POST_TOWN: "result town or city", POSTCODE: "AA1 1AA", UPRN: "12345" } }] }.to_json, headers: {})
parser.valid?
end

78
spec/shared/shared_log_examples.rb

@ -103,6 +103,84 @@ RSpec.shared_examples "shared log examples" do |log_type|
allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message)
expect { log.process_uprn_change! }.to change { log.errors[:uprn] }.from([]).to([error_message])
.and change { log.errors[:uprn_selection] }.from([]).to([error_message])
end
end
end
describe "#process_address_change!" do
context "when address_line1_input and postcode_full_input set to a value" do
let(:log) do
log = build(
log_type,
uprn_selection: "UPRN",
address_line1: "Address line 1",
postcode_full: "AA1 1AA",
county: "county",
)
log.save!(validate: false)
log
end
it "updates log fields" do
log.address_line1_input = "New address line 1"
log.postcode_full_input = "BB2 2BB"
allow_any_instance_of(AddressClient).to receive(:call)
allow_any_instance_of(AddressClient).to receive(:result).and_return([{
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
}])
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:result).and_return({
"UPRN" => "UPRN",
"UDPRN" => "UDPRN",
"ADDRESS" => "full address",
"SUB_BUILDING_NAME" => "0",
"BUILDING_NAME" => "building name",
"THOROUGHFARE_NAME" => "thoroughfare",
"POST_TOWN" => "posttown",
"POSTCODE" => "postcode",
})
expect { log.process_address_change! }.to change(log, :address_line1).from("Address line 1").to("0, Building Name, Thoroughfare")
.and change(log, :town_or_city).from(nil).to("Posttown")
.and change(log, :postcode_full).from("AA1 1AA").to("POSTCODE")
.and change(log, :uprn_confirmed).from(nil).to(1)
.and change(log, :uprn).from(nil).to("UPRN")
.and change(log, :uprn_known).from(nil).to(1)
.and change(log, :uprn_selection).from("UPRN").to(nil)
.and change(log, :county).from("county").to(nil)
end
end
context "when address inputs are nil" do
let(:log) { create(log_type, uprn_selection: nil, address_line1_input: nil, postcode_full_input: nil) }
it "does not update log" do
expect { log.process_address_change! }.not_to change(log, :attributes)
end
end
context "when service errors" do
let(:log) { build(log_type, :in_progress, uprn_selection: "UPRN", address_line1_input: "123", postcode_full_input: "AA1 1AA") }
let(:error_message) { "error" }
it "adds error to log" do
allow_any_instance_of(AddressClient).to receive(:call)
allow_any_instance_of(AddressClient).to receive(:error).and_return(error_message)
allow_any_instance_of(UprnClient).to receive(:call)
allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message)
expect { log.process_address_change! }.to change { log.errors[:uprn_selection] }.from([]).to([error_message])
.and change { log.errors[:uprn_selection] }.from([]).to([error_message])
end
end
end

Loading…
Cancel
Save