Browse Source

Merge branch 'main' into CLDC-1825-prepare-bulk-upload-guidance

# Conflicts:
#	db/schema.rb
pull/1342/head
natdeanlewissoftwire 3 years ago
parent
commit
b57e1f6b88
  1. 12
      app/components/bulk_upload_error_summary_table_component.rb
  2. 16
      app/components/check_answers_summary_list_card_component.html.erb
  3. 13
      app/mailers/bulk_upload_mailer.rb
  4. 8
      app/models/bulk_upload.rb
  5. 21
      app/models/derived_variables/lettings_log_variables.rb
  6. 8
      app/models/form.rb
  7. 24
      app/models/form/lettings/pages/address.rb
  8. 15
      app/models/form/lettings/pages/care_home_charges_value_check.rb
  9. 2
      app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb
  10. 6
      app/models/form/lettings/pages/new_build_handover_date.rb
  11. 2
      app/models/form/lettings/pages/property_building_type.rb
  12. 2
      app/models/form/lettings/pages/property_let_type.rb
  13. 10
      app/models/form/lettings/pages/property_local_authority.rb
  14. 13
      app/models/form/lettings/pages/property_major_repairs.rb
  15. 2
      app/models/form/lettings/pages/property_number_of_bedrooms.rb
  16. 2
      app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb
  17. 2
      app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb
  18. 2
      app/models/form/lettings/pages/property_postcode.rb
  19. 2
      app/models/form/lettings/pages/property_unit_type.rb
  20. 2
      app/models/form/lettings/pages/property_vacancy_reason_first_let.rb
  21. 2
      app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb
  22. 2
      app/models/form/lettings/pages/property_wheelchair_accessible.rb
  23. 28
      app/models/form/lettings/pages/uprn.rb
  24. 17
      app/models/form/lettings/pages/uprn_confirmation.rb
  25. 16
      app/models/form/lettings/pages/uprn_known.rb
  26. 13
      app/models/form/lettings/pages/void_or_renewal_date.rb
  27. 38
      app/models/form/lettings/questions/address_line1.rb
  28. 13
      app/models/form/lettings/questions/address_line2.rb
  29. 14
      app/models/form/lettings/questions/care_home_charges_value_check.rb
  30. 13
      app/models/form/lettings/questions/county.rb
  31. 2
      app/models/form/lettings/questions/ethnic_black.rb
  32. 4
      app/models/form/lettings/questions/la.rb
  33. 25
      app/models/form/lettings/questions/postcode_for_full_address.rb
  34. 9
      app/models/form/lettings/questions/rsnvac_first_let.rb
  35. 13
      app/models/form/lettings/questions/town_or_city.rb
  36. 35
      app/models/form/lettings/questions/uprn.rb
  37. 34
      app/models/form/lettings/questions/uprn_confirmation.rb
  38. 21
      app/models/form/lettings/questions/uprn_known.rb
  39. 1
      app/models/form/lettings/subsections/income_and_benefits.rb
  40. 23
      app/models/form/lettings/subsections/property_information.rb
  41. 2
      app/models/form/sales/pages/address.rb
  42. 26
      app/models/form/sales/pages/discounted_sale_value_check.rb
  43. 4
      app/models/form/sales/pages/mortgage_amount.rb
  44. 6
      app/models/form/sales/pages/number_of_others_in_property.rb
  45. 1
      app/models/form/sales/questions/address_line1.rb
  46. 2
      app/models/form/sales/questions/buyer1_ethnic_background_black.rb
  47. 2
      app/models/form/sales/questions/buyer2_ethnic_background_black.rb
  48. 23
      app/models/form/sales/questions/discounted_sale_value_check.rb
  49. 2
      app/models/form/sales/questions/mortgage_amount.rb
  50. 47
      app/models/form/sales/questions/mortgage_lender.rb
  51. 4
      app/models/form/sales/questions/number_of_others_in_property.rb
  52. 1
      app/models/form/sales/questions/uprn.rb
  53. 2
      app/models/form/sales/questions/uprn_known.rb
  54. 4
      app/models/form/sales/subsections/discounted_ownership_scheme.rb
  55. 1
      app/models/form/sales/subsections/setup.rb
  56. 11
      app/models/form/subsection.rb
  57. 2
      app/models/form_handler.rb
  58. 15
      app/models/lettings_log.rb
  59. 1
      app/models/location.rb
  60. 1
      app/models/log.rb
  61. 21
      app/models/sales_log.rb
  62. 2
      app/models/scheme.rb
  63. 9
      app/models/validations/date_validations.rb
  64. 20
      app/models/validations/financial_validations.rb
  65. 8
      app/models/validations/household_validations.rb
  66. 2
      app/models/validations/property_validations.rb
  67. 8
      app/models/validations/sales/financial_validations.rb
  68. 11
      app/models/validations/sales/sale_information_validations.rb
  69. 10
      app/models/validations/sales/setup_validations.rb
  70. 9
      app/models/validations/sales/soft_validations.rb
  71. 2
      app/models/validations/shared_validations.rb
  72. 10
      app/models/validations/soft_validations.rb
  73. 2
      app/models/validations/tenancy_validations.rb
  74. 135
      app/services/bulk_upload/lettings/year2022/row_parser.rb
  75. 143
      app/services/bulk_upload/lettings/year2023/row_parser.rb
  76. 24
      app/services/imports/lettings_logs_import_service.rb
  77. 30
      app/services/imports/sales_logs_import_service.rb
  78. 24
      app/services/imports/scheme_location_import_service.rb
  79. 2
      app/views/form/_check_answers_summary_list.html.erb
  80. 6
      app/views/form/check_answers.html.erb
  81. 22
      app/views/form/review.html.erb
  82. 38
      config/forms/2021_2022.json
  83. 50
      config/forms/2022_2023.json
  84. 6
      config/initializers/feature_toggle.rb
  85. 37
      config/locales/en.yml
  86. 5
      db/migrate/20230313124749_add_carehome_charges_value_check.rb
  87. 5
      db/migrate/20230316162737_add_discounted_sale_value_check.rb
  88. 3
      db/schema.rb
  89. 147
      spec/components/bulk_upload_error_summary_table_component_spec.rb
  90. 6
      spec/factories/lettings_log.rb
  91. 1
      spec/features/form/page_routing_spec.rb
  92. 26
      spec/features/lettings_log_spec.rb
  93. 46
      spec/features/sales_log_spec.rb
  94. 2
      spec/fixtures/exports/general_needs_log.csv
  95. 4
      spec/fixtures/exports/general_needs_log.xml
  96. 4
      spec/fixtures/exports/supported_housing_logs.xml
  97. 4
      spec/fixtures/files/lettings_logs_download.csv
  98. 4
      spec/fixtures/files/lettings_logs_download_codes_only.csv
  99. 4
      spec/fixtures/files/lettings_logs_download_non_support.csv
  100. 1
      spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml
  101. Some files were not shown because too many files have changed in this diff Show More

12
app/components/bulk_upload_error_summary_table_component.rb

@ -12,7 +12,7 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
end
def sorted_errors
@sorted_errors ||= bulk_upload
@sorted_errors ||= setup_errors.presence || bulk_upload
.bulk_upload_errors
.group(:col, :field, :error)
.having("count(*) > ?", display_threshold)
@ -26,6 +26,16 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
private
def setup_errors
@setup_errors ||= bulk_upload
.bulk_upload_errors
.where(category: "setup")
.group(:col, :field, :error)
.having("count(*) > ?", display_threshold)
.count
.sort_by { |el| el[0][0].rjust(3, "0") }
end
def display_threshold
DISPLAY_THRESHOLD
end

16
app/components/check_answers_summary_list_card_component.html.erb

@ -12,16 +12,22 @@
<% summary_list.row do |row| %>
<% row.key { get_question_label(question) } %>
<% row.value do %>
<span class="govuk-!-margin-right-4"><%= get_answer_label(question) %></span>
<%= simple_format(
get_answer_label(question),
wrapper_tag: "span",
class: "govuk-!-margin-right-4",
) %>
<% extra_value = question.get_extra_check_answer_value(log) %>
<% if extra_value %>
<span class="govuk-!-font-weight-regular app-!-colour-muted"><%= extra_value %></span>
<% if extra_value && question.answer_label(log).present? %>
<%= simple_format(
extra_value,
wrapper_tag: "span",
class: "govuk-!-font-weight-regular app-!-colour-muted",
) %>
<% end %>
<br>
<% question.get_inferred_answers(log).each do |inferred_answer| %>
<span class="govuk-!-font-weight-regular app-!-colour-muted"><%= inferred_answer %></span>
<% end %>

13
app/mailers/bulk_upload_mailer.rb

@ -33,19 +33,7 @@ class BulkUploadMailer < NotifyMailer
)
end
def columns_with_errors(bulk_upload:)
array = bulk_upload.columns_with_errors
if array.size > 3
"#{array.take(3).join(', ')} and more"
else
array.join(", ")
end
end
def send_correct_and_upload_again_mail(bulk_upload:)
error_description = "We noticed that you have a lot of similar errors in column #{columns_with_errors(bulk_upload:)}. Please correct your data export and upload again."
summary_report_link = if BulkUploadErrorSummaryTableComponent.new(bulk_upload:).errors?
summary_bulk_upload_lettings_result_url(bulk_upload)
else
@ -60,7 +48,6 @@ class BulkUploadMailer < NotifyMailer
upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time),
year_combo: bulk_upload.year_combo,
lettings_or_sales: bulk_upload.log_type,
error_description:,
summary_report_link:,
},
)

8
app/models/bulk_upload.rb

@ -30,14 +30,6 @@ class BulkUpload < ApplicationRecord
end
end
def columns_with_errors
bulk_upload_errors
.select(:col)
.distinct(:col)
.pluck(:col)
.sort_by { |col| col.rjust(2, "0") }
end
def general_needs?
needstype == 1
end

21
app/models/derived_variables/lettings_log_variables.rb

@ -94,6 +94,17 @@ module DerivedVariables::LettingsLogVariables
self.vacdays = property_vacant_days
set_housingneeds_fields if housingneeds?
if uprn_known&.zero?
self.uprn = nil
end
if uprn_confirmed&.zero?
self.uprn = nil
self.uprn_known = 0
end
reset_address_fields! if is_supported_housing?
end
private
@ -229,4 +240,14 @@ private
self.housingneeds_g = 0
self.housingneeds_h = 0
end
def reset_address_fields!
self.uprn = nil
self.uprn_known = nil
self.uprn_confirmed = nil
self.address_line1 = nil
self.address_line2 = nil
self.town_or_city = nil
self.county = nil
end
end

8
app/models/form.rb

@ -7,9 +7,9 @@ class Form
if sales_or_start_year_after_2022?(type, start_year)
@start_date = Time.zone.local(start_year, 4, 1)
@end_date = if start_year && start_year.to_i > 2022
Time.zone.local(start_year + 1, 7, 9)
Time.zone.local(start_year + 1, 6, 9)
else
Time.zone.local(start_year + 1, 7, 7)
Time.zone.local(start_year + 1, 6, 7)
end
@setup_sections = type == "sales" ? [Form::Sales::Sections::Setup.new(nil, nil, self)] : [Form::Lettings::Sections::Setup.new(nil, nil, self)]
@form_sections = sections_in_form.map { |sec| sec.new(nil, nil, self) }
@ -111,8 +111,8 @@ class Form
when :in_progress
"#{next_subsection.id}/check_answers".dasherize
when :not_started
first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(log, nil) }.id
first_question_in_subsection.to_s.dasherize
first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(log, nil) }
first_question_in_subsection ? first_question_in_subsection.id.to_s.dasherize : next_incomplete_section_redirect_path(next_subsection, log)
else
"error"
end

24
app/models/form/lettings/pages/address.rb

@ -0,0 +1,24 @@
class Form::Lettings::Pages::Address < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address"
@header = "Q12 - What is the property's address?"
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
def routed_to?(log, _current_user = nil)
return false if log.uprn_known.nil?
return false if log.is_supported_housing?
log.uprn_confirmed != 1 || log.uprn_known.zero?
end
end

15
app/models/form/lettings/pages/care_home_charges_value_check.rb

@ -0,0 +1,15 @@
class Form::Lettings::Pages::CareHomeChargesValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "care_home_charges_value_check"
@depends_on = [{ "care_home_charge_expected_not_provided?" => true }]
@title_text = {
"translation" => "soft_validations.care_home_charges.title_text",
}
@informative_text = ""
end
def questions
@questions ||= [Form::Lettings::Questions::CareHomeChargesValueCheck.new(nil, nil, self)]
end
end

2
app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::FirstTimePropertyLetAsSocialHousing < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "first_time_property_let_as_social_housing"
@depends_on = [{ "renewal" => 0 }]
@depends_on = [{ "is_renewal?" => false }]
end
def questions

6
app/models/form/lettings/pages/new_build_handover_date.rb

@ -2,11 +2,7 @@ class Form::Lettings::Pages::NewBuildHandoverDate < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "new_build_handover_date"
@depends_on = [
{ "renewal" => 0, "rsnvac" => 15 },
{ "renewal" => 0, "rsnvac" => 16 },
{ "renewal" => 0, "rsnvac" => 17 },
]
@depends_on = [{ "is_renewal?" => false, "has_first_let_vacancy_reason?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_building_type.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyBuildingType < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_building_type"
@depends_on = [{ "needstype" => 1 }]
@depends_on = [{ "is_general_needs?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_let_type.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyLetType < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_let_type"
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0, "needstype" => 1 }]
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }]
end
def questions

10
app/models/form/lettings/pages/property_local_authority.rb

@ -2,10 +2,18 @@ class Form::Lettings::Pages::PropertyLocalAuthority < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_local_authority"
@depends_on = [{ "is_la_inferred" => false, "needstype" => 1 }]
@depends_on = [{ "is_la_inferred" => false, "is_general_needs?" => true }]
end
def questions
@questions ||= [Form::Lettings::Questions::La.new(nil, nil, self)]
end
def routed_to?(log, _current_user = nil)
return false if log.uprn_known.nil? && form.start_date.year >= 2023
return false if log.is_la_inferred?
return false if log.is_supported_housing?
true
end
end

13
app/models/form/lettings/pages/property_major_repairs.rb

@ -2,18 +2,7 @@ class Form::Lettings::Pages::PropertyMajorRepairs < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_major_repairs"
@depends_on = [
{ "renewal" => 0, "rsnvac" => 5 },
{ "renewal" => 0, "rsnvac" => 6 },
{ "renewal" => 0, "rsnvac" => 8 },
{ "renewal" => 0, "rsnvac" => 9 },
{ "renewal" => 0, "rsnvac" => 10 },
{ "renewal" => 0, "rsnvac" => 11 },
{ "renewal" => 0, "rsnvac" => 12 },
{ "renewal" => 0, "rsnvac" => 13 },
{ "renewal" => 0, "rsnvac" => 18 },
{ "renewal" => 0, "rsnvac" => 19 },
]
@depends_on = [{ "is_renewal?" => false, "vacancy_reason_not_renewal_or_first_let?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_number_of_bedrooms.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfBedrooms < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_number_of_bedrooms"
@depends_on = [{ "needstype" => 1 }]
@depends_on = [{ "is_general_needs?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfTimesReletNotSocialLet < ::Form::Pa
def initialize(id, hsh, subsection)
super
@id = "property_number_of_times_relet_not_social_let"
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0 }]
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }]
end
def questions

2
app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfTimesReletSocialLet < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_number_of_times_relet_social_let"
@depends_on = [{ "first_time_property_let_as_social_housing" => 1, "renewal" => 0 }]
@depends_on = [{ "first_time_property_let_as_social_housing" => 1, "is_renewal?" => false }]
end
def questions

2
app/models/form/lettings/pages/property_postcode.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyPostcode < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_postcode"
@depends_on = [{ "needstype" => 1 }]
@depends_on = [{ "is_general_needs?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_unit_type.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyUnitType < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_unit_type"
@depends_on = [{ "needstype" => 1 }]
@depends_on = [{ "is_general_needs?" => true }]
end
def questions

2
app/models/form/lettings/pages/property_vacancy_reason_first_let.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyVacancyReasonFirstLet < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_vacancy_reason_first_let"
@depends_on = [{ "first_time_property_let_as_social_housing" => 1, "renewal" => 0 }]
@depends_on = [{ "first_time_property_let_as_social_housing" => 1, "is_renewal?" => false }]
end
def questions

2
app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyVacancyReasonNotFirstLet < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_vacancy_reason_not_first_let"
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0 }]
@depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }]
end
def questions

2
app/models/form/lettings/pages/property_wheelchair_accessible.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyWheelchairAccessible < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "property_wheelchair_accessible"
@depends_on = [{ "is_supported_housing?" => false }]
@depends_on = [{ "is_general_needs?" => true }]
end
def questions

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

@ -0,0 +1,28 @@
class Form::Lettings::Pages::Uprn < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn"
end
def questions
@questions ||= [
Form::Lettings::Questions::Uprn.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
return false if log.is_supported_housing?
log.uprn_known == 1
end
def skip_text
"Enter address instead"
end
def skip_href(log = nil)
return unless log
"/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
end
end

17
app/models/form/lettings/pages/uprn_confirmation.rb

@ -0,0 +1,17 @@
class Form::Lettings::Pages::UprnConfirmation < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_confirmation"
@header = "We found an address that might be this property"
end
def questions
@questions ||= [
Form::Lettings::Questions::UprnConfirmation.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
log.uprn.present? && log.uprn_known == 1
end
end

16
app/models/form/lettings/pages/uprn_known.rb

@ -0,0 +1,16 @@
class Form::Lettings::Pages::UprnKnown < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_known"
end
def questions
@questions ||= [
Form::Lettings::Questions::UprnKnown.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
!log.is_supported_housing?
end
end

13
app/models/form/lettings/pages/void_or_renewal_date.rb

@ -2,18 +2,7 @@ class Form::Lettings::Pages::VoidOrRenewalDate < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "void_or_renewal_date"
@depends_on = [
{ "renewal" => 0, "rsnvac" => 5 },
{ "renewal" => 0, "rsnvac" => 6 },
{ "renewal" => 0, "rsnvac" => 8 },
{ "renewal" => 0, "rsnvac" => 9 },
{ "renewal" => 0, "rsnvac" => 10 },
{ "renewal" => 0, "rsnvac" => 11 },
{ "renewal" => 0, "rsnvac" => 12 },
{ "renewal" => 0, "rsnvac" => 13 },
{ "renewal" => 0, "rsnvac" => 18 },
{ "renewal" => 0, "rsnvac" => 19 },
]
@depends_on = [{ "is_renewal?" => false, "vacancy_reason_not_renewal_or_first_let?" => true }]
end
def questions

38
app/models/form/lettings/questions/address_line1.rb

@ -0,0 +1,38 @@
class Form::Lettings::Questions::AddressLine1 < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_line1"
@check_answer_label = "Address"
@header = "Address line 1"
@type = "text"
@plain_label = true
@check_answer_label = "Q12 - Address"
end
def hidden_in_check_answers?(log, _current_user = nil)
return true if log.uprn_known.nil?
return false if log.uprn_known&.zero?
return true if log.uprn_confirmed.nil? && log.uprn.present?
return true if log.uprn_known == 1 && log.uprn.blank?
log.uprn_confirmed == 1
end
def answer_label(log, _current_user = nil)
[
log.address_line1,
log.address_line2,
log.postcode_full,
log.town_or_city,
log.county,
].select(&:present?).join("\n")
end
def get_extra_check_answer_value(log)
return unless log.is_la_inferred?
la = LocalAuthority.find_by(code: log.la)&.name
la.presence
end
end

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

@ -0,0 +1,13 @@
class Form::Lettings::Questions::AddressLine2 < ::Form::Question
def initialize(id, hsh, page)
super
@id = "address_line2"
@header = "Address line 2 (optional)"
@type = "text"
@plain_label = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)
true
end
end

14
app/models/form/lettings/questions/care_home_charges_value_check.rb

@ -0,0 +1,14 @@
class Form::Lettings::Questions::CareHomeChargesValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "carehome_charges_value_check"
@check_answer_label = "Care home charges confirmation"
@header = "Are you sure there are no care home charges?"
@type = "interruption_screen"
@check_answers_card_number = 0
@answer_options = ANSWER_OPTIONS
@hidden_in_check_answers = { "depends_on" => [{ "carehome_charges_value_check" => 0 }, { "carehome_charges_value_check" => 1 }] }
end
ANSWER_OPTIONS = { "0" => { "value" => "Yes" }, "1" => { "value" => "No" } }.freeze
end

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

@ -0,0 +1,13 @@
class Form::Lettings::Questions::County < ::Form::Question
def initialize(id, hsh, page)
super
@id = "county"
@header = "County (optional)"
@type = "text"
@plain_label = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)
true
end
end

2
app/models/form/lettings/questions/ethnic_black.rb

@ -19,7 +19,7 @@ class Form::Lettings::Questions::EthnicBlack < ::Form::Question
"value" => "Caribbean",
},
"14" => {
"value" => "Any other Black, African or Caribbean background",
"value" => "Any other Black, African, Caribbean or Black British background",
},
}.freeze
end

4
app/models/form/lettings/questions/la.rb

@ -13,4 +13,8 @@ class Form::Lettings::Questions::La < ::Form::Question
def answer_options
{ "" => "Select an option" }.merge(LocalAuthority.active(form.start_date).england.map { |la| [la.code, la.name] }.to_h)
end
def hidden_in_check_answers?(log, _current_user = nil)
log.startdate && log.startdate.year >= 2023 && log.is_la_inferred?
end
end

25
app/models/form/lettings/questions/postcode_for_full_address.rb

@ -0,0 +1,25 @@
class Form::Lettings::Questions::PostcodeForFullAddress < ::Form::Question
def initialize(id, hsh, page)
super
@id = "postcode_full"
@header = "Postcode"
@type = "text"
@width = 5
@inferred_check_answers_value = [{
"condition" => {
"pcodenk" => 1,
},
"value" => "Not known",
}]
@inferred_answers = {
"la" => {
"is_la_inferred" => true,
},
}
@plain_label = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)
true
end
end

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

@ -12,11 +12,8 @@ class Form::Lettings::Questions::RsnvacFirstLet < ::Form::Question
end
ANSWER_OPTIONS = {
"16" =>
{ "value" => "First let of conversion, rehabilitation or acquired property" },
"17" =>
{ "value" => "First let of leased property" },
"15" =>
{ "value" => "First let of new-build property" },
"16" => { "value" => "First let of conversion, rehabilitation or acquired property" },
"17" => { "value" => "First let of leased property" },
"15" => { "value" => "First let of new-build property" },
}.freeze
end

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

@ -0,0 +1,13 @@
class Form::Lettings::Questions::TownOrCity < ::Form::Question
def initialize(id, hsh, page)
super
@id = "town_or_city"
@header = "Town or city"
@type = "text"
@plain_label = true
end
def hidden_in_check_answers?(_log = nil, _current_user = nil)
true
end
end

35
app/models/form/lettings/questions/uprn.rb

@ -0,0 +1,35 @@
class Form::Lettings::Questions::Uprn < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn"
@check_answer_label = "UPRN"
@header = "What is the property's UPRN"
@type = "text"
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
@width = 10
@question_number = 11
end
def unanswered_error_message
I18n.t("validations.property.uprn.invalid")
end
def get_extra_check_answer_value(log)
value = [
log.address_line1,
log.address_line2,
log.town_or_city,
log.county,
log.postcode_full,
(LocalAuthority.find_by(code: log.la)&.name if log.la.present?),
].select(&:present?)
return unless value.any?
"\n\n#{value.join("\n")}"
end
def hidden_in_check_answers?(log, _current_user = nil)
log.uprn_known != 1
end
end

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

@ -0,0 +1,34 @@
class Form::Lettings::Questions::UprnConfirmation < ::Form::Question
def initialize(id, hsh, page)
super
@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 notification_banner(log = nil)
return unless log&.uprn
{
title: "UPRN: #{log.uprn}",
heading: [
log.address_line1,
log.address_line2,
log.postcode_full,
log.town_or_city,
log.county,
].select(&:present?).join("\n"),
}
end
def hidden_in_check_answers?(log, _current_user = nil)
log.uprn_known != 1 || log.uprn_confirmed.present?
end
end

21
app/models/form/lettings/questions/uprn_known.rb

@ -0,0 +1,21 @@
class Form::Lettings::Questions::UprnKnown < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn_known"
@check_answer_label = "UPRN known?"
@header = "Do you know the property's UPRN?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.<br><br>
You can continue without the UPRN, but it means we will need you to enter the address of the property."
end
ANSWER_OPTIONS = {
"1" => { "value" => "Yes" },
"0" => { "value" => "No" },
}.freeze
def unanswered_error_message
I18n.t("validations.property.uprn_known.invalid")
end
end

1
app/models/form/lettings/subsections/income_and_benefits.rb

@ -19,6 +19,7 @@ class Form::Lettings::Subsections::IncomeAndBenefits < ::Form::Subsection
Form::Lettings::Pages::CareHomeBiWeekly.new(nil, nil, self),
Form::Lettings::Pages::CareHome4Weekly.new(nil, nil, self),
Form::Lettings::Pages::CareHomeMonthly.new(nil, nil, self),
Form::Lettings::Pages::CareHomeChargesValueCheck.new(nil, nil, self),
Form::Lettings::Pages::RentWeekly.new(nil, nil, self),
Form::Lettings::Pages::RentBiWeekly.new(nil, nil, self),
Form::Lettings::Pages::Rent4Weekly.new(nil, nil, self),

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

@ -8,7 +8,7 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
def pages
@pages ||= [
Form::Lettings::Pages::PropertyPostcode.new(nil, nil, self),
uprn_questions,
Form::Lettings::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Lettings::Pages::FirstTimePropertyLetAsSocialHousing.new(nil, nil, self),
Form::Lettings::Pages::PropertyLetType.new(nil, nil, self),
@ -25,6 +25,25 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
Form::Lettings::Pages::NewBuildHandoverDate.new(nil, nil, self),
Form::Lettings::Pages::PropertyMajorRepairs.new(nil, nil, self),
Form::Lettings::Pages::PropertyMajorRepairsValueCheck.new(nil, nil, self),
].compact
].flatten.compact
end
def uprn_questions
if form.start_date.year >= 2023
[
Form::Lettings::Pages::UprnKnown.new(nil, nil, self),
Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),
Form::Lettings::Pages::Address.new(nil, nil, self),
]
else
[
Form::Lettings::Pages::PropertyPostcode.new(nil, nil, self),
]
end
end
def displayed_in_tasklist?(log)
!(log.is_supported_housing? && log.is_renewal?)
end
end

2
app/models/form/sales/pages/address.rb

@ -2,7 +2,7 @@ class Form::Sales::Pages::Address < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address"
@header = "What is the property's address?"
@header = "Q15 - What is the property's address?"
end
def questions

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

@ -0,0 +1,26 @@
class Form::Sales::Pages::DiscountedSaleValueCheck < ::Form::Page
def initialize(id, hsh, subsection, person_index = nil)
super(id, hsh, subsection)
@depends_on = depends_on
@title_text = {
"translation" => "soft_validations.discounted_sale_value.title_text",
"arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }],
}
@informative_text = {
"translation" => "soft_validations.discounted_sale_value.informative_text",
"arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }],
}
@person_index = person_index
@depends_on = [
{
"discounted_ownership_value_invalid?" => true,
},
]
end
def questions
@questions ||= [
Form::Sales::Questions::DiscountedSaleValueCheck.new(nil, nil, self),
]
end
end

4
app/models/form/sales/pages/mortgage_amount.rb

@ -3,9 +3,7 @@ class Form::Sales::Pages::MortgageAmount < ::Form::Page
super(id, hsh, subsection)
@ownershipsch = ownershipsch
@header = "Mortgage Amount"
@depends_on = [{
"mortgageused" => 1,
}]
@depends_on = [{ "mortgage_used?" => true }]
end
def questions

6
app/models/form/sales/pages/number_of_others_in_property.rb

@ -4,11 +4,11 @@ class Form::Sales::Pages::NumberOfOthersInProperty < ::Form::Page
@depends_on = [
{
"privacynotice" => 1,
"jointpur" => joint_purchase ? 1 : 2,
"joint_purchase?" => joint_purchase,
},
{
"noint" => 1,
"jointpur" => joint_purchase ? 1 : 2,
"buyer_not_interviewed?" => true,
"joint_purchase?" => joint_purchase,
},
]
@joint_purchase = joint_purchase

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

@ -6,6 +6,7 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question
@header = "Address line 1"
@type = "text"
@plain_label = true
@check_answer_label = "Q15 - Address"
end
def hidden_in_check_answers?(log, _current_user = nil)

2
app/models/form/sales/questions/buyer1_ethnic_background_black.rb

@ -14,6 +14,6 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundBlack < ::Form::Question
ANSWER_OPTIONS = {
"13" => { "value" => "African" },
"12" => { "value" => "Caribbean" },
"14" => { "value" => "Any other Black, African or Caribbean background" },
"14" => { "value" => "Any other Black, African, Caribbean or Black British background" },
}.freeze
end

2
app/models/form/sales/questions/buyer2_ethnic_background_black.rb

@ -13,6 +13,6 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundBlack < ::Form::Question
ANSWER_OPTIONS = {
"13" => { "value" => "African" },
"12" => { "value" => "Caribbean" },
"14" => { "value" => "Any other Black, African or Caribbean background" },
"14" => { "value" => "Any other Black, African, Caribbean or Black British background" },
}.freeze
end

23
app/models/form/sales/questions/discounted_sale_value_check.rb

@ -0,0 +1,23 @@
class Form::Sales::Questions::DiscountedSaleValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "discounted_sale_value_check"
@check_answer_label = "Discounted sale value confirmation"
@header = "Are you sure this is correct?"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
}
@hidden_in_check_answers = {
"depends_on" => [
{
"discounted_sale_value_check" => 0,
},
{
"discounted_sale_value_check" => 1,
},
],
}
end
end

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

@ -5,7 +5,7 @@ class Form::Sales::Questions::MortgageAmount < ::Form::Question
@check_answer_label = "Mortgage amount"
@header = "What is the mortgage amount?"
@type = "numeric"
@min = 0
@min = 1
@width = 5
@prefix = "£"
@hint_text = "Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments. Numeric in pounds. Rounded to the nearest pound."

47
app/models/form/sales/questions/mortgage_lender.rb

@ -56,8 +56,55 @@ class Form::Sales::Questions::MortgageLender < ::Form::Question
"38" => "West Bromwich Building Society",
"39" => "Yorkshire Building Society",
"40" => "Other",
"0" => "Don’t know",
}.freeze
def displayed_answer_options(_log, _user = nil)
{
"" => "Select an option",
"1" => "Atom Bank",
"2" => "Barclays Bank PLC",
"3" => "Bath Building Society",
"4" => "Buckinghamshire Building Society",
"5" => "Cambridge Building Society",
"6" => "Coventry Building Society",
"7" => "Cumberland Building Society",
"8" => "Darlington Building Society",
"9" => "Dudley Building Society",
"10" => "Ecology Building Society",
"11" => "Halifax",
"12" => "Hanley Economic Building Society",
"13" => "Hinckley and Rugby Building Society",
"14" => "Holmesdale Building Society",
"15" => "Ipswich Building Society",
"16" => "Leeds Building Society",
"17" => "Lloyds Bank",
"18" => "Mansfield Building Society",
"19" => "Market Harborough Building Society",
"20" => "Melton Mowbray Building Society",
"21" => "Nationwide Building Society",
"22" => "Natwest",
"23" => "Nedbank Private Wealth",
"24" => "Newbury Building Society",
"25" => "OneSavings Bank",
"26" => "Parity Trust",
"27" => "Penrith Building Society",
"28" => "Pepper Homeloans",
"29" => "Royal Bank of Scotland",
"30" => "Santander",
"31" => "Skipton Building Society",
"32" => "Teachers Building Society",
"33" => "The Co-operative Bank",
"34" => "Tipton & Coseley Building Society",
"35" => "TSB",
"36" => "Ulster Bank",
"37" => "Virgin Money",
"38" => "West Bromwich Building Society",
"39" => "Yorkshire Building Society",
"40" => "Other",
}
end
def question_number
case @ownershipsch
when 1

4
app/models/form/sales/questions/number_of_others_in_property.rb

@ -3,12 +3,12 @@ class Form::Sales::Questions::NumberOfOthersInProperty < ::Form::Question
super(id, hsh, page)
@id = "hholdcount"
@check_answer_label = "Number of other people living in the property"
@header = "Besides the buyer(s), how many other people live or will live in the property?"
@header = "Besides the #{'buyer'.pluralize(joint_purchase ? 2 : 1)}, how many other people live or will live in the property?"
@type = "numeric"
@hint_text = hint(joint_purchase)
@width = 2
@min = 0
@max = joint_purchase ? 4 : 5
@max = 15
@question_number = 35
end

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

@ -7,6 +7,7 @@ class Form::Sales::Questions::Uprn < ::Form::Question
@type = "text"
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
@width = 10
@question_number = 14
end
def unanswered_error_message

2
app/models/form/sales/questions/uprn_known.rb

@ -3,7 +3,7 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question
super
@id = "uprn_known"
@check_answer_label = "UPRN known?"
@header = "Do you know the property UPRN?"
@header = "Do you know the property's UPRN?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.<br><br>

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

@ -14,12 +14,15 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self),
Form::Sales::Pages::GrantValueCheck.new(nil, nil, self),
Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_grant_value_check", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_discounted_ownership_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_used_mortgage_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_used_value_check", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_amount_mortgage_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_value_check", nil, self),
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_mortgage_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_mortgage", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_discounted_ownership", nil, self, ownershipsch: 2),
@ -31,6 +34,7 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_deposit_value_check", nil, self),
Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_deposit", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_deposit_value_check", nil, self),
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_discounted_ownership_value_check", nil, self),
]

1
app/models/form/sales/subsections/setup.rb

@ -18,6 +18,7 @@ class Form::Sales::Subsections::Setup < ::Form::Subsection
Form::Sales::Pages::OutrightOwnershipType.new(nil, nil, self),
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_type_value_check", nil, self),
Form::Sales::Pages::BuyerCompany.new(nil, nil, self),
Form::Sales::Pages::BuyerLive.new(nil, nil, self),
Form::Sales::Pages::JointPurchase.new(nil, nil, self),

11
app/models/form/subsection.rb

@ -7,6 +7,7 @@ class Form::Subsection
if hsh
@label = hsh["label"]
@depends_on = hsh["depends_on"]
@displayed_in_tasklist_from_json = hsh["displayed_in_tasklist"]
@pages = hsh["pages"].map { |s_id, p| Form::Page.new(s_id, p, self) }
end
end
@ -48,7 +49,13 @@ class Form::Subsection
end
end
def displayed_in_tasklist?(_log)
true
def displayed_in_tasklist?(log)
return true unless @displayed_in_tasklist_from_json
@displayed_in_tasklist_from_json.any? do |conditions|
conditions.all? do |method, expected_return_value|
log.send(method) == expected_return_value
end
end
end
end

2
app/models/form_handler.rb

@ -47,7 +47,7 @@ class FormHandler
form = Form.new(form_path)
form_to_set = form_name_from_start_year(form.start_date.year, "lettings")
forms[form_to_set] = form if forms[form_to_set].blank?
forms[form_to_set] = form if form_to_set && forms[form_to_set].blank?
end
end

15
app/models/lettings_log.rb

@ -32,6 +32,7 @@ class LettingsLog < Log
before_validation :reset_location_fields!, unless: :postcode_known?
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
before_validation :set_derived_fields!
after_validation :process_uprn_change!, if: :should_process_uprn_change?
belongs_to :scheme, optional: true
belongs_to :location, optional: true
@ -53,7 +54,7 @@ class LettingsLog < Log
scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org).or(where(managing_organisation: org)) }
AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze
OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenancycode propcode].freeze
OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenancycode propcode chcharge].freeze
RENT_TYPE_MAPPING_LABELS = { 1 => "Social Rent", 2 => "Affordable Rent", 3 => "Intermediate Rent" }.freeze
HAS_BENEFITS_OPTIONS = [1, 6, 8, 7].freeze
NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52 }.freeze
@ -287,6 +288,10 @@ class LettingsLog < Log
[15, 16, 17].include?(rsnvac)
end
def vacancy_reason_not_renewal_or_first_let?
[5, 6, 8, 9, 10, 11, 12, 13, 18, 19].include? rsnvac
end
def previous_tenancy_was_temporary?
# 4: Tied housing or renting with job
# 6: Supported housing
@ -501,6 +506,10 @@ class LettingsLog < Log
update!(created_by: nil)
end
def care_home_charge_expected_not_provided?
is_carehome == 1 && chcharge.blank?
end
private
def reset_derived_questions
@ -671,4 +680,8 @@ private
def unknown_housingneeds?
housingneeds == 3
end
def should_process_uprn_change?
uprn_changed? && startdate && startdate.year >= 2023
end
end

1
app/models/location.rb

@ -23,6 +23,7 @@ class Location < ApplicationRecord
scope :search_by, ->(param) { search_by_name(param).or(search_by_postcode(param)) }
scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) }
scope :active, -> { where(confirmed: true).and(started) }
scope :confirmed, -> { where(confirmed: true) }
LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h

1
app/models/log.rb

@ -45,6 +45,7 @@ class Log < ApplicationRecord
self.address_line2 = presenter.address_line2
self.town_or_city = presenter.town_or_city
self.postcode_full = presenter.postcode
self.county = nil
process_postcode_changes!
end
end

21
app/models/sales_log.rb

@ -42,7 +42,7 @@ class SalesLog < Log
}
scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) }
OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check mortgagelender othtype].freeze
OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check].freeze
RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze
def lettings?
@ -243,6 +243,10 @@ class SalesLog < Log
ownershipsch == 2
end
def mortgage_used?
mortgageused == 1
end
def mortgage_not_used?
mortgageused == 2
end
@ -330,4 +334,19 @@ class SalesLog < Log
def should_process_uprn_change?
uprn_changed? && saledate && saledate.year >= 2023
end
def value_with_discount
return if value.blank?
discount_amount = discount ? value * discount / 100 : 0
value - discount_amount
end
def mortgage_deposit_and_grant_total
return if deposit.blank?
grant_amount = grant || 0
mortgage_amount = mortgage || 0
mortgage_amount + deposit + grant_amount
end
end

2
app/models/scheme.rb

@ -235,7 +235,7 @@ class Scheme < ApplicationRecord
end
def status_at(date)
return :incomplete unless confirmed
return :incomplete unless confirmed && locations.confirmed.any?
return :deactivated if open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date
return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date
return :reactivating_soon if recent_deactivation&.reactivation_date.present? && date < recent_deactivation.reactivation_date

9
app/models/validations/date_validations.rb

@ -33,17 +33,10 @@ module Validations::DateValidations
def validate_startdate(record)
return unless record.startdate && date_valid?("startdate", record)
if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14
if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14.days
record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after")
end
if record.scheme_id.present?
scheme_end_date = record.scheme.end_date
if scheme_end_date.present? && record.startdate > scheme_end_date
record.errors.add :startdate, I18n.t("validations.setup.startdate.before_scheme_end_date")
end
end
if record["voiddate"].present? && record.startdate < record["voiddate"]
record.errors.add :startdate, I18n.t("validations.setup.startdate.after_void_date")
end

20
app/models/validations/financial_validations.rb

@ -25,6 +25,7 @@ module Validations::FinancialValidations
if record.ecstat1 && record.weekly_net_income
if record.weekly_net_income > record.applicable_income_range.hard_max
record.errors.add :earnings, :over_hard_max, message: I18n.t("validations.financial.earnings.over_hard_max", hard_max: record.applicable_income_range.hard_max)
record.errors.add :ecstat1, :over_hard_max, message: I18n.t("validations.financial.ecstat.over_hard_max", hard_max: record.applicable_income_range.hard_max)
end
if record.weekly_net_income < record.applicable_income_range.hard_min
@ -132,12 +133,12 @@ private
CHARGE_MAXIMUMS = {
scharge: {
private_registered_provider: {
general_needs: 55,
supported_housing: 280,
general_needs: 155,
supported_housing: 480,
},
local_authority: {
general_needs: 45,
supported_housing: 165,
general_needs: 155,
supported_housing: 365,
},
},
pscharge: {
@ -187,7 +188,12 @@ private
collection_year = record.collection_start_year
rent_range = LaRentRange.find_by(start_year: collection_year, la: record.la, beds: record.beds_for_la_rent_range, lettype: record.lettype)
rent_range = LaRentRange.find_by(
start_year: collection_year,
la: record.la,
beds: record.beds_for_la_rent_range,
lettype: record.lettype,
)
if rent_range.present? && !weekly_value_in_range(record, "brent", rent_range.hard_min, rent_range.hard_max) && record.brent.present? && record.period.present?
if record.weekly_value(record["brent"]) < rent_range.hard_min
@ -200,7 +206,9 @@ private
record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.below_hard_min")
record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.below_hard_min")
record.errors.add :period, I18n.t("validations.financial.brent.period.below_hard_min")
elsif record.beds.blank? || record.beds < LaRentRange::MAX_BEDS
end
if record.weekly_value(record["brent"]) > rent_range.hard_max
record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max")
record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max")
record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max")

8
app/models/validations/household_validations.rb

@ -35,12 +35,6 @@ module Validations::HouseholdValidations
end
end
def validate_pregnancy(record)
if (record.has_pregnancy? || record.pregnancy_refused?) && women_in_household(record) && !women_of_child_bearing_age_in_household(record)
record.errors.add :preg_occ, I18n.t("validations.household.preg_occ.no_female")
end
end
def validate_household_number_of_other_members(record)
(2..8).each do |n|
validate_person_age_matches_economic_status(record, n)
@ -63,7 +57,7 @@ module Validations::HouseholdValidations
def validate_previous_housing_situation(record)
if record.is_relet_to_temp_tenant? && !record.previous_tenancy_was_temporary?
record.errors.add :prevten, I18n.t("validations.household.prevten.non_temp_accommodation")
record.errors.add :prevten, :non_temp_accommodation, message: I18n.t("validations.household.prevten.non_temp_accommodation")
end
if record.age1.present? && record.age1 > 19 && record.previous_tenancy_was_foster_care?

2
app/models/validations/property_validations.rb

@ -16,7 +16,7 @@ module Validations::PropertyValidations
end
if record.offered.negative? || record.offered > 20
record.errors.add :offered, I18n.t("validations.property.offered.relet_number")
record.errors.add :offered, :over_20, message: I18n.t("validations.property.offered.relet_number")
end
end

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

@ -36,6 +36,10 @@ module Validations::Sales::FinancialValidations
end
end
def validate_mortgage(record)
record.errors.add :mortgage, I18n.t("validations.financial.mortgage") if record.mortgage_used? && record.mortgage&.zero?
end
def validate_cash_discount(record)
return unless record.cashdis
@ -94,10 +98,10 @@ module Validations::Sales::FinancialValidations
if record.equity < range.min
record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min)
record.errors.add :equity, I18n.t("validations.financial.equity.under_min", min_equity: range.min)
record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min)
elsif record.equity > range.max
record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :equity, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max)
end
end

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

@ -1,4 +1,6 @@
module Validations::Sales::SaleInformationValidations
include CollectionTimeHelper
def validate_practical_completion_date_before_saledate(record)
return if record.saledate.blank? || record.hodate.blank?
@ -45,17 +47,14 @@ module Validations::Sales::SaleInformationValidations
end
def validate_discounted_ownership_value(record)
return unless record.saledate && collection_start_year(record.saledate) >= 2024
return unless record.value && record.deposit && record.ownershipsch
return unless record.mortgage || record.mortgageused == 2
return unless record.discount || record.grant || record.type == 29
discount_amount = record.discount ? record.value * record.discount / 100 : 0
grant_amount = record.grant || 0
mortgage_amount = record.mortgage || 0
value_with_discount = (record.value - discount_amount)
if mortgage_amount + record.deposit + grant_amount != value_with_discount && record.discounted_ownership_sale?
if record.mortgage_deposit_and_grant_total != record.value_with_discount && record.discounted_ownership_sale?
%i[mortgage deposit grant value discount ownershipsch].each do |field|
record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", value_with_discount))
record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", record.value_with_discount))
end
end
end

10
app/models/validations/sales/setup_validations.rb

@ -2,7 +2,7 @@ module Validations::Sales::SetupValidations
include Validations::SharedValidations
include CollectionTimeHelper
def validate_saledate(record)
def validate_saledate_collection_year(record)
return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_collection_window_validation_enabled?
unless record.saledate.between?(active_collection_start_date, current_collection_end_date)
@ -10,6 +10,14 @@ module Validations::Sales::SetupValidations
end
end
def validate_saledate_two_weeks(record)
return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_two_week_validation_enabled?
if record.saledate > Time.zone.today + 14.days
record.errors.add :saledate, I18n.t("validations.setup.saledate.later_than_14_days_after")
end
end
private
def active_collection_start_date

9
app/models/validations/sales/soft_validations.rb

@ -114,6 +114,15 @@ module Validations::Sales::SoftValidations
end
end
def discounted_ownership_value_invalid?
return unless saledate && collection_start_year <= 2023
return unless value && deposit && ownershipsch
return unless mortgage || mortgageused == 2
return unless discount || grant || type == 29
mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale?
end
private
def sale_range

2
app/models/validations/shared_validations.rb

@ -38,7 +38,7 @@ module Validations::SharedValidations
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.postcode")
record.errors.add :postcode_full, error_message
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end

10
app/models/validations/soft_validations.rb

@ -53,11 +53,11 @@ module Validations::SoftValidations
end
def no_females_in_a_pregnant_household?
!females_in_the_household? && all_tenants_age_and_gender_information_completed? && preg_occ == 1
!females_in_the_household? && all_tenants_gender_information_completed? && preg_occ == 1
end
def female_in_pregnant_household_in_soft_validation_range?
all_tenants_age_and_gender_information_completed? && (females_in_age_range(11, 15) || females_in_age_range(51, 65)) && !females_in_age_range(16, 50) && preg_occ == 1
all_tenants_age_and_gender_information_completed? && females_in_the_household? && !females_in_age_range(16, 50) && preg_occ == 1
end
def all_tenants_age_and_gender_information_completed?
@ -66,6 +66,12 @@ module Validations::SoftValidations
end
end
def all_tenants_gender_information_completed?
(1..hhmemb).all? do |n|
public_send("sex#{n}").present? && details_known_or_lead_tenant?(n)
end
end
TWO_YEARS_IN_DAYS = 730
TEN_YEARS_IN_DAYS = 3650

2
app/models/validations/tenancy_validations.rb

@ -43,7 +43,7 @@ module Validations::TenancyValidations
return unless record.collection_start_year && record.joint
if record.hhmemb == 1 && record.joint != 2 && record.collection_start_year >= 2022
record.errors.add :joint, I18n.t("validations.tenancy.not_joint")
record.errors.add :joint, :not_joint_tenancy, message: I18n.t("validations.tenancy.not_joint")
record.errors.add :hhmemb, I18n.t("validations.tenancy.joint_more_than_one_member")
end
end

135
app/services/bulk_upload/lettings/year2022/row_parser.rb

@ -282,13 +282,13 @@ class BulkUpload::Lettings::Year2022::RowParser
validates :field_4, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_1) } }
validates :field_12, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }
validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }
validates :field_14, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }
validates :field_15, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }
validates :field_16, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }
validates :field_17, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }
validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }
validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }
validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true
validates :field_14, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, allow_blank: true
validates :field_15, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, allow_blank: true
validates :field_16, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, allow_blank: true
validates :field_17, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, allow_blank: true
validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true
validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true
validates :field_96, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }
validates :field_97, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }
@ -308,14 +308,14 @@ class BulkUpload::Lettings::Year2022::RowParser
validate :validate_dont_know_disabled_needs_conjunction
validate :validate_no_and_dont_know_disabled_needs_conjunction
validate :validate_owning_org_permitted
validate :validate_owning_org_owns_stock
validate :validate_owning_org_exists
validate :validate_owning_org_data_given
validate :validate_owning_org_exists
validate :validate_owning_org_owns_stock
validate :validate_owning_org_permitted
validate :validate_managing_org_related
validate :validate_managing_org_exists
validate :validate_managing_org_data_given
validate :validate_managing_org_exists
validate :validate_managing_org_related
validate :validate_scheme_related
validate :validate_scheme_exists
@ -436,19 +436,26 @@ private
def validate_managing_org_related
if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation)
block_log_creation!
errors.add(:field_113, "This managing organisation does not have a relationship with the owning organisation")
if errors[:field_113].blank?
errors.add(:field_113, "This managing organisation does not have a relationship with the owning organisation")
end
end
end
def validate_managing_org_exists
if managing_organisation.nil?
errors.delete(:field_113)
errors.add(:field_113, "The managing organisation code is incorrect")
block_log_creation!
if errors[:field_113].blank?
errors.add(:field_113, "The managing organisation code is incorrect")
end
end
end
def validate_managing_org_data_given
if field_113.blank?
block_log_creation!
errors.add(:field_113, "The managing organisation code is incorrect", category: :setup)
end
end
@ -456,29 +463,40 @@ private
def validate_owning_org_owns_stock
if owning_organisation && !owning_organisation.holds_own_stock?
block_log_creation!
errors.delete(:field_111)
errors.add(:field_111, "The owning organisation code provided is for an organisation that does not own stock")
if errors[:field_111].blank?
errors.add(:field_111, "The owning organisation code provided is for an organisation that does not own stock")
end
end
end
def validate_owning_org_exists
if owning_organisation.nil?
errors.delete(:field_111)
errors.add(:field_111, "The owning organisation code is incorrect")
block_log_creation!
if errors[:field_111].blank?
errors.add(:field_111, "The owning organisation code is incorrect")
end
end
end
def validate_owning_org_data_given
if field_111.blank?
errors.add(:field_111, "The owning organisation code is incorrect", category: :setup)
block_log_creation!
if errors[:field_111].blank?
errors.add(:field_111, "The owning organisation code is incorrect", category: :setup)
end
end
end
def validate_owning_org_permitted
if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation)
block_log_creation!
errors.delete(:field_111)
errors.add(:field_111, "You do not have permission to add logs for this owning organisation")
if errors[:field_111].blank?
errors.add(:field_111, "You do not have permission to add logs for this owning organisation")
end
end
end
@ -502,7 +520,7 @@ private
end
def validate_only_one_housing_needs_type
if [field_55, field_56, field_57].compact.count.positive?
if [field_55, field_56, field_57].compact.count > 1
errors.add(:field_55, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
errors.add(:field_56, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
errors.add(:field_57, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
@ -848,28 +866,28 @@ private
attributes["tenancylength"] = field_11
attributes["declaration"] = field_132
attributes["age1_known"] = field_12 == "R" ? 1 : 0
attributes["age1_known"] = age1_known?
attributes["age1"] = field_12 if attributes["age1_known"].zero? && field_12&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age2_known"] = field_13 == "R" ? 1 : 0
attributes["age2_known"] = age2_known?
attributes["age2"] = field_13 if attributes["age2_known"].zero? && field_13&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age3_known"] = field_14 == "R" ? 1 : 0
attributes["age3_known"] = age3_known?
attributes["age3"] = field_14 if attributes["age3_known"].zero? && field_14&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age4_known"] = field_15 == "R" ? 1 : 0
attributes["age4_known"] = age4_known?
attributes["age4"] = field_15 if attributes["age4_known"].zero? && field_15&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age5_known"] = field_16 == "R" ? 1 : 0
attributes["age5_known"] = age5_known?
attributes["age5"] = field_16 if attributes["age5_known"].zero? && field_16&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age6_known"] = field_17 == "R" ? 1 : 0
attributes["age6_known"] = age6_known?
attributes["age6"] = field_17 if attributes["age6_known"].zero? && field_17&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age7_known"] = field_18 == "R" ? 1 : 0
attributes["age7_known"] = age7_known?
attributes["age7"] = field_18 if attributes["age7_known"].zero? && field_18&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age8_known"] = field_19 == "R" ? 1 : 0
attributes["age8_known"] = age8_known?
attributes["age8"] = field_19 if attributes["age8_known"].zero? && field_19&.match(/\A\d{1,3}\z|\AR\z/)
attributes["sex1"] = field_20
@ -902,13 +920,13 @@ private
attributes["ecstat7"] = field_41
attributes["ecstat8"] = field_42
attributes["details_known_2"] = details_known(2)
attributes["details_known_3"] = details_known(3)
attributes["details_known_4"] = details_known(4)
attributes["details_known_5"] = details_known(5)
attributes["details_known_6"] = details_known(6)
attributes["details_known_7"] = details_known(7)
attributes["details_known_8"] = details_known(8)
attributes["details_known_2"] = details_known?(2)
attributes["details_known_3"] = details_known?(3)
attributes["details_known_4"] = details_known?(4)
attributes["details_known_5"] = details_known?(5)
attributes["details_known_6"] = details_known?(6)
attributes["details_known_7"] = details_known?(7)
attributes["details_known_8"] = details_known?(8)
attributes["armedforces"] = field_45
attributes["leftreg"] = leftreg
@ -1094,7 +1112,32 @@ private
end
end
def details_known(person_n)
def age1_known?
return 1 if field_12 == "R"
return 1 if field_12.blank?
0
end
[
{ person: 2, field: :field_13 },
{ person: 3, field: :field_14 },
{ person: 4, field: :field_15 },
{ person: 5, field: :field_16 },
{ person: 6, field: :field_17 },
{ person: 7, field: :field_18 },
{ person: 8, field: :field_19 },
].each do |hash|
define_method("age#{hash[:person]}_known?") do
return 1 if public_send(hash[:field]) == "R"
return 0 if send("person_#{hash[:person]}_present?")
return 1 if public_send(hash[:field]).blank?
0
end
end
def details_known?(person_n)
send("person_#{person_n}_present?") ? 0 : 1
end
@ -1111,31 +1154,31 @@ private
end
def person_2_present?
field_13.present? && field_21.present? && field_28.present?
field_13.present? || field_21.present? || field_28.present?
end
def person_3_present?
field_14.present? && field_22.present? && field_29.present?
field_14.present? || field_22.present? || field_29.present?
end
def person_4_present?
field_15.present? && field_23.present? && field_30.present?
field_15.present? || field_23.present? || field_30.present?
end
def person_5_present?
field_16.present? && field_24.present? && field_31.present?
field_16.present? || field_24.present? || field_31.present?
end
def person_6_present?
field_17.present? && field_25.present? && field_32.present?
field_17.present? || field_25.present? || field_32.present?
end
def person_7_present?
field_18.present? && field_26.present? && field_33.present?
field_18.present? || field_26.present? || field_33.present?
end
def person_8_present?
field_19.present? && field_27.present? && field_34.present?
field_19.present? || field_27.present? || field_34.present?
end
def tshortfall_known

143
app/services/bulk_upload/lettings/year2023/row_parser.rb

@ -284,13 +284,13 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_16, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_5) } }
validates :field_46, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }
validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }
validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }
validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }
validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }
validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }
validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true
validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, allow_blank: true
validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, allow_blank: true
validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, allow_blank: true
validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, allow_blank: true
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true
validates :field_7, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }
validates :field_8, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }
@ -311,14 +311,14 @@ class BulkUpload::Lettings::Year2023::RowParser
validate :validate_dont_know_disabled_needs_conjunction
validate :validate_no_and_dont_know_disabled_needs_conjunction
validate :validate_owning_org_permitted
validate :validate_owning_org_owns_stock
validate :validate_owning_org_exists
validate :validate_owning_org_data_given
validate :validate_owning_org_exists
validate :validate_owning_org_owns_stock
validate :validate_owning_org_permitted
validate :validate_managing_org_related
validate :validate_managing_org_exists
validate :validate_managing_org_data_given
validate :validate_managing_org_exists
validate :validate_managing_org_related
validate :validate_scheme_related
validate :validate_scheme_exists
@ -419,7 +419,7 @@ private
end
def validate_only_one_housing_needs_type
if [field_83, field_84, field_85].compact.count.positive?
if [field_83, field_84, field_85].compact.count > 1
errors.add(:field_83, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
errors.add(:field_84, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
errors.add(:field_85, I18n.t("validations.household.housingneeds_type.only_one_option_permitted"))
@ -551,19 +551,26 @@ private
def validate_managing_org_related
if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation)
block_log_creation!
errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation")
if errors[:field_2].blank?
errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation")
end
end
end
def validate_managing_org_exists
if managing_organisation.nil?
errors.delete(:field_2)
errors.add(:field_2, "The managing organisation code is incorrect")
block_log_creation!
if errors[:field_2].blank?
errors.add(:field_2, "The managing organisation code is incorrect")
end
end
end
def validate_managing_org_data_given
if field_2.blank?
block_log_creation!
errors.add(:field_2, "The managing organisation code is incorrect", category: :setup)
end
end
@ -571,20 +578,26 @@ private
def validate_owning_org_owns_stock
if owning_organisation && !owning_organisation.holds_own_stock?
block_log_creation!
errors.delete(:field_1)
errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock")
if errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock")
end
end
end
def validate_owning_org_exists
if owning_organisation.nil?
errors.delete(:field_1)
errors.add(:field_1, "The owning organisation code is incorrect")
block_log_creation!
if errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code is incorrect")
end
end
end
def validate_owning_org_data_given
if field_1.blank?
block_log_creation!
errors.add(:field_1, "The owning organisation code is incorrect", category: :setup)
end
end
@ -592,8 +605,10 @@ private
def validate_owning_org_permitted
if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation)
block_log_creation!
errors.delete(:field_1)
errors.add(:field_1, "You do not have permission to add logs for this owning organisation")
if errors[:field_1].blank?
errors.add(:field_1, "You do not have permission to add logs for this owning organisation")
end
end
end
@ -751,6 +766,12 @@ private
mrcdate: %i[field_36 field_37 field_38],
voiddate: %i[field_33 field_34 field_35],
uprn: [:field_18],
address_line1: [:field_19],
address_line2: [:field_20],
town_or_city: [:field_21],
county: [:field_22],
}
end
@ -790,28 +811,28 @@ private
attributes["tenancylength"] = field_43
attributes["declaration"] = field_45
attributes["age1_known"] = field_46 == "R" ? 1 : 0
attributes["age1_known"] = age1_known?
attributes["age1"] = field_46 if attributes["age1_known"].zero? && field_46&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age2_known"] = field_52 == "R" ? 1 : 0
attributes["age2_known"] = age2_known?
attributes["age2"] = field_52 if attributes["age2_known"].zero? && field_52&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age3_known"] = field_56 == "R" ? 1 : 0
attributes["age3_known"] = age3_known?
attributes["age3"] = field_56 if attributes["age3_known"].zero? && field_56&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age4_known"] = field_60 == "R" ? 1 : 0
attributes["age4_known"] = age4_known?
attributes["age4"] = field_60 if attributes["age4_known"].zero? && field_60&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age5_known"] = field_64 == "R" ? 1 : 0
attributes["age5_known"] = age5_known?
attributes["age5"] = field_64 if attributes["age5_known"].zero? && field_64&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age6_known"] = field_68 == "R" ? 1 : 0
attributes["age6_known"] = age6_known?
attributes["age6"] = field_68 if attributes["age6_known"].zero? && field_68&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age7_known"] = field_72 == "R" ? 1 : 0
attributes["age7_known"] = age7_known?
attributes["age7"] = field_72 if attributes["age7_known"].zero? && field_72&.match(/\A\d{1,3}\z|\AR\z/)
attributes["age8_known"] = field_76 == "R" ? 1 : 0
attributes["age8_known"] = age8_known?
attributes["age8"] = field_76 if attributes["age8_known"].zero? && field_76&.match(/\A\d{1,3}\z|\AR\z/)
attributes["sex1"] = field_47
@ -844,13 +865,13 @@ private
attributes["ecstat7"] = field_74
attributes["ecstat8"] = field_78
attributes["details_known_2"] = details_known(2)
attributes["details_known_3"] = details_known(3)
attributes["details_known_4"] = details_known(4)
attributes["details_known_5"] = details_known(5)
attributes["details_known_6"] = details_known(6)
attributes["details_known_7"] = details_known(7)
attributes["details_known_8"] = details_known(8)
attributes["details_known_2"] = details_known?(2)
attributes["details_known_3"] = details_known?(3)
attributes["details_known_4"] = details_known?(4)
attributes["details_known_5"] = details_known?(5)
attributes["details_known_6"] = details_known?(6)
attributes["details_known_7"] = details_known?(7)
attributes["details_known_8"] = details_known?(8)
attributes["armedforces"] = field_79
attributes["leftreg"] = leftreg
@ -939,6 +960,13 @@ private
attributes["first_time_property_let_as_social_housing"] = first_time_property_let_as_social_housing
attributes["uprn_known"] = field_18.present? ? 1 : 0
attributes["uprn"] = field_18
attributes["address_line1"] = field_19
attributes["address_line2"] = field_20
attributes["town_or_city"] = field_21
attributes["county"] = field_22
attributes
end
@ -1055,36 +1083,61 @@ private
end
end
def details_known(person_n)
def age1_known?
return 1 if field_46 == "R"
return 1 if field_46.blank?
0
end
[
{ person: 2, field: :field_52 },
{ person: 3, field: :field_56 },
{ person: 4, field: :field_60 },
{ person: 5, field: :field_64 },
{ person: 6, field: :field_68 },
{ person: 7, field: :field_72 },
{ person: 8, field: :field_76 },
].each do |hash|
define_method("age#{hash[:person]}_known?") do
return 1 if public_send(hash[:field]) == "R"
return 0 if send("person_#{hash[:person]}_present?")
return 1 if public_send(hash[:field]).blank?
0
end
end
def details_known?(person_n)
send("person_#{person_n}_present?") ? 0 : 1
end
def person_2_present?
field_51.present? && field_52.present? && field_53.present?
field_51.present? || field_52.present? || field_53.present?
end
def person_3_present?
field_55.present? && field_56.present? && field_57.present?
field_55.present? || field_56.present? || field_57.present?
end
def person_4_present?
field_59.present? && field_60.present? && field_61.present?
field_59.present? || field_60.present? || field_61.present?
end
def person_5_present?
field_63.present? && field_64.present? && field_65.present?
field_63.present? || field_64.present? || field_65.present?
end
def person_6_present?
field_67.present? && field_68.present? && field_69.present?
field_67.present? || field_68.present? || field_69.present?
end
def person_7_present?
field_71.present? && field_72.present? && field_73.present?
field_71.present? || field_72.present? || field_73.present?
end
def person_8_present?
field_75.present? && field_76.present? && field_77.present?
field_75.present? || field_76.present? || field_77.present?
end
def leftreg

24
app/services/imports/lettings_logs_import_service.rb

@ -235,6 +235,7 @@ module Imports
attributes["retirement_value_check"] = 0
attributes["rent_value_check"] = 0
attributes["net_income_value_check"] = 0
attributes["carehome_charges_value_check"] = 0
# Sets the log creator
owner_id = meta_field_value(xml_doc, "owner-user-id").strip
@ -310,6 +311,27 @@ module Imports
attributes.delete("prevten")
attributes.delete("age1")
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:prevten, :non_temp_accommodation)
@logger.warn("Log #{lettings_log.old_id}: Removing vacancy reason and previous tenancy since this accommodation is not temporary")
@logs_overridden << lettings_log.old_id
attributes.delete("prevten")
attributes.delete("rsnvac")
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:joint, :not_joint_tenancy)
@logger.warn("Log #{lettings_log.old_id}: Removing joint tenancy as there is only 1 person in the household")
@logs_overridden << lettings_log.old_id
attributes.delete("joint")
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:offered, :over_20)
@logger.warn("Log #{lettings_log.old_id}: Removing offered as the value is above the maximum of 20")
@logs_overridden << lettings_log.old_id
attributes.delete("offered")
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:earnings, :over_hard_max)
@logger.warn("Log #{lettings_log.old_id}: Removing working situation because income is too high for it")
@logs_overridden << lettings_log.old_id
attributes.delete("ecstat1")
save_lettings_log(attributes, previous_status)
else
@logger.error("Log #{lettings_log.old_id}: Failed to import")
lettings_log.errors.each do |error|
@ -339,7 +361,7 @@ module Imports
end
def fields_not_present_in_softwire_data
%w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other created_by]
%w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check carehome_charges_value_check housingneeds_type housingneeds_other created_by]
end
def check_status_completed(lettings_log, previous_status)

30
app/services/imports/sales_logs_import_service.rb

@ -38,7 +38,7 @@ module Imports
attributes["ownershipsch"] = ownership_from_type(attributes) if attributes["ownershipsch"].blank? # sometimes Ownership is missing, but type is set
attributes["othtype"] = string_or_nil(xml_doc, "Q38OtherSale")
attributes["jointpur"] = unsafe_string_as_integer(xml_doc, "joint")
attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore") if attributes["jointpur"] == 1
attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore") || 3 if attributes["jointpur"] == 1
attributes["beds"] = safe_string_as_integer(xml_doc, "Q11Bedrooms")
attributes["companybuy"] = unsafe_string_as_integer(xml_doc, "company") if attributes["ownershipsch"] == 3
attributes["hholdcount"] = other_household_members(xml_doc, attributes)
@ -153,6 +153,7 @@ module Imports
attributes["income2_value_check"] = 0
attributes["monthly_charges_value_check"] = 0
attributes["student_not_child_value_check"] = 0
attributes["discounted_sale_value_check"] = 0
# Sets the log creator
owner_id = meta_field_value(xml_doc, "owner-user-id").strip
@ -188,8 +189,12 @@ module Imports
def rescue_validation_or_raise(sales_log, attributes, previous_status, exception)
if %w[saved submitted-invalid].include?(previous_status)
sales_log.errors.each do |error|
@logger.warn("Log #{sales_log.old_id}: Removing field #{error.attribute} from log triggering validation: #{error.type}")
attributes.delete(error.attribute.to_s)
unless error.attribute == :type || error.attribute == :ownershipsch
@logger.warn("Log #{sales_log.old_id}: Removing field #{error.attribute} from log triggering validation: #{error.type}")
attributes.delete(error.attribute.to_s)
end
attributes.delete("pcodenk") if error.attribute == :postcode_full
attributes.delete("ppcodenk") if error.attribute == :ppostcode_full
end
@logs_overridden << sales_log.old_id
save_sales_log(attributes, previous_status)
@ -209,6 +214,17 @@ module Imports
@logs_overridden << sales_log.old_id
attributes.delete("income1")
save_sales_log(attributes, previous_status)
elsif sales_log.errors.of_kind?(:equity, :over_max) || sales_log.errors.of_kind?(:equity, :under_min)
@logger.warn("Log #{sales_log.old_id}: Removing equity as the equity is invalid")
@logs_overridden << sales_log.old_id
attributes.delete("equity")
save_sales_log(attributes, previous_status)
elsif sales_log.errors.of_kind?(:postcode_full, :wrong_format)
@logger.warn("Log #{sales_log.old_id}: Removing postcode as the postcode is invalid")
@logs_overridden << sales_log.old_id
attributes.delete("postcode_full")
attributes["pcodenk"] = attributes["la"].present? ? 1 : nil
save_sales_log(attributes, previous_status)
else
@logger.error("Log #{sales_log.old_id}: Failed to import")
sales_log.errors.each do |error|
@ -255,7 +271,8 @@ module Imports
monthly_charges_value_check
hodate_check
saledate_check
student_not_child_value_check]
student_not_child_value_check
discounted_sale_value_check]
end
def check_status_completed(sales_log, previous_status)
@ -500,12 +517,12 @@ module Imports
def set_default_values(attributes)
attributes["armedforcesspouse"] ||= 7
attributes["hhregres"] ||= 8
attributes["hhregresstill"] ||= 7 if attributes["hhregres"] == 1
attributes["disabled"] ||= 3
attributes["wheel"] ||= 3
attributes["hb"] ||= 4
attributes["prevown"] ||= 3
attributes["savingsnk"] ||= attributes["savings"].present? ? 0 : 1
attributes["jointmore"] ||= 3 if attributes["jointpur"] == 1
attributes["inc1mort"] ||= 3
if [attributes["pregyrha"], attributes["pregla"], attributes["pregghb"], attributes["pregother"]].all?(&:blank?)
attributes["pregblank"] = 1
@ -515,6 +532,7 @@ module Imports
attributes["extrabor"] ||= 3 if attributes["mortgageused"] == 1
attributes["socprevten"] ||= 10 if attributes["ownershipsch"] == 1
attributes["fromprop"] ||= 0 if attributes["ownershipsch"] == 1
attributes["mortgagelender"] ||= 0 if attributes["mortgageused"] == 1
# buyer 1 characteristics
attributes["age1_known"] ||= 1
@ -537,7 +555,7 @@ module Imports
end
# other household members characteristics
(2..attributes["hhmemb"]).each do |index|
(2..[attributes["hhmemb"], 6].min).each do |index|
attributes["age#{index}_known"] ||= 1
attributes["sex#{index}"] ||= "R"
attributes["ecstat#{index}"] ||= 10

24
app/services/imports/scheme_location_import_service.rb

@ -35,7 +35,6 @@ module Imports
primary_client_group: attributes["primary_client_group"],
secondary_client_group: attributes["secondary_client_group"],
sensitive: attributes["sensitive"],
end_date: attributes["end_date"],
# These values were set by the scheme import (management groups)
owning_organisation_id: source_scheme.owning_organisation_id,
service_name: source_scheme.service_name,
@ -43,7 +42,7 @@ module Imports
old_id: source_scheme.old_id,
old_visible_id: source_scheme.old_visible_id,
)
confirm_scheme(scheme)
confirm_scheme_or_location(scheme)
scheme.save! && scheme
rescue ActiveRecord::RecordInvalid
@logger.error("Scheme #{source_scheme.old_visible_id}: Failed to import")
@ -59,18 +58,17 @@ module Imports
primary_client_group: attributes["primary_client_group"],
secondary_client_group: attributes["secondary_client_group"],
sensitive: attributes["sensitive"],
end_date: attributes["end_date"],
}
confirm_scheme(scheme)
confirm_scheme_or_location(scheme)
scheme.save! && scheme
end
def confirm_scheme(scheme)
scheme.confirmed = true
scheme.validate_confirmed
unless scheme.errors.empty?
scheme.confirmed = false
scheme.errors.clear
def confirm_scheme_or_location(obj)
obj.confirmed = true
obj.validate_confirmed
unless obj.errors.empty?
obj.confirmed = false
obj.errors.clear
end
end
@ -99,7 +97,7 @@ module Imports
end
def add_location(scheme, attributes)
Location.create!(
location = Location.create!(
name: attributes["location_name"],
postcode: attributes["postcode"],
mobility_type: attributes["mobility_type"],
@ -110,6 +108,10 @@ module Imports
startdate: attributes["start_date"],
scheme:,
)
if attributes["end_date"]
location.location_deactivation_periods.create!(deactivation_date: attributes["end_date"])
end
location
rescue ActiveRecord::RecordNotUnique
@logger.warn("Location is already present with legacy ID #{attributes['location_old_id']}, skipping")
rescue ActiveRecord::RecordInvalid

2
app/views/form/_check_answers_summary_list.html.erb

@ -9,7 +9,7 @@
class: "govuk-!-margin-right-4",
) %>
<% extra_value = question.get_extra_check_answer_value(@log) %>
<% if extra_value && question.answer_label(lettings_log, current_user).present? %>
<% if extra_value && question.answer_label(@log, current_user).present? %>
<%= simple_format(
extra_value,
wrapper_tag: "span",

6
app/views/form/check_answers.html.erb

@ -1,9 +1,9 @@
<% content_for :title, "#{subsection.id.humanize} - Check your answers" %>
<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: {
"Logs" => "/logs",
"Log #{@log.id}" => send("#{@log.class.name.underscore}_path", @log),
"Logs" => url_for(@log.class),
"Log #{@log.id}" => url_for(@log),
subsection.label => "",
}) %>
}) %>
<div class="govuk-grid-row">
<div class="govuk-grid-column-three-quarters-from-desktop">

22
app/views/form/review.html.erb

@ -1,18 +1,10 @@
<% if @log.sales? %>
<% content_for :title, "Review sales log" %>
<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: {
"Logs" => "/logs",
"Log #{@log.id}" => "/sales-logs/#{@log.id}",
"Review sales log" => "",
}) %>
<% else %>
<% content_for :title, "Review lettings log" %>
<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: {
"Logs" => "/logs",
"Log #{@log.id}" => "/lettings-logs/#{@log.id}",
"Review lettings log" => "",
}) %>
<% end %>
<% class_name = @log.class.model_name.human.downcase %>
<% content_for :title, "Review #{class_name}" %>
<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: {
"Logs" => url_for(@log.class),
"Log #{@log.id}" => url_for(@log),
"Review #{class_name}" => "",
}) %>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds-from-desktop">

38
config/forms/2021_2022.json

@ -1639,7 +1639,7 @@
"value": "Caribbean"
},
"14": {
"value": "Any other Black, African or Caribbean background"
"value": "Any other Black, African, Caribbean or Black British background"
}
}
}
@ -7812,6 +7812,42 @@
}
]
},
"care_home_charges_value_check": {
"depends_on": [
{
"care_home_charge_expected_not_provided?": true
}
],
"title_text": {
"translation": "soft_validations.care_home_charges.title_text"
},
"informative_text": {},
"questions": {
"carehome_charges_value_check": {
"check_answer_label": "Care home charges confirmation",
"hidden_in_check_answers": {
"depends_on": [
{
"carehome_charges_value_check": 0
},
{
"carehome_charges_value_check": 1
}
]
},
"header": "Are you sure there are no care home charges?",
"type": "interruption_screen",
"answer_options": {
"0": {
"value": "Yes"
},
"1": {
"value": "No"
}
}
}
}
},
"rent_weekly": {
"header": "Household rent and charges",
"description": "",

50
config/forms/2022_2023.json

@ -1,7 +1,7 @@
{
"form_type": "lettings",
"start_date": "2022-04-01T00:00:00.000+01:00",
"end_date": "2023-07-09T00:00:00.000+01:00",
"end_date": "2023-06-09T00:00:00.000+01:00",
"unresolved_log_redirect_page_id": "tenancy_start_date",
"sections": {
"tenancy_and_property": {
@ -939,7 +939,15 @@
}
}
}
}
},
"displayed_in_tasklist": [
{
"is_supported_housing?": false
},
{
"is_renewal?": false
}
]
},
"tenancy_information": {
"label": "Tenancy information",
@ -1671,7 +1679,7 @@
"value": "Caribbean"
},
"14": {
"value": "Any other Black, African or Caribbean background"
"value": "Any other Black, African, Caribbean or Black British background"
}
}
}
@ -7774,6 +7782,42 @@
}
]
},
"care_home_charges_value_check": {
"depends_on": [
{
"care_home_charge_expected_not_provided?": true
}
],
"title_text": {
"translation": "soft_validations.care_home_charges.title_text"
},
"informative_text": {},
"questions": {
"carehome_charges_value_check": {
"check_answer_label": "Care home charges confirmation",
"hidden_in_check_answers": {
"depends_on": [
{
"carehome_charges_value_check": 0
},
{
"carehome_charges_value_check": 1
}
]
},
"header": "Are you sure there are no care home charges?",
"type": "interruption_screen",
"answer_options": {
"0": {
"value": "Yes"
},
"1": {
"value": "No"
}
}
}
}
},
"rent_weekly": {
"header": "Household rent and charges",
"description": "",

6
config/initializers/feature_toggle.rb

@ -5,13 +5,17 @@ class FeatureToggle
end
def self.startdate_collection_window_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging?
Rails.env.production? || Rails.env.test?
end
def self.startdate_two_week_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging?
end
def self.saledate_two_week_validation_enabled?
Rails.env.production? || Rails.env.test? || Rails.env.staging? || Rails.env.review?
end
def self.sales_log_enabled?
true
end

37
config/locales/en.yml

@ -155,6 +155,7 @@ en:
intermediate_rent_product_name:
blank: "Enter name of other intermediate rent product"
saledate:
later_than_14_days_after: "Sale completion date must not be later than 14 days from today’s date"
current_collection_year:
Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long}
previous_and_current_collection_year:
@ -253,11 +254,11 @@ en:
less_than_shortfall: "Enter an amount that is more than the shortfall in basic rent"
scharge:
private_registered_provider:
general_needs: "Enter a value for the service charge between £0 and £55 per week if the landlord is a private registered provider and it is a general needs letting"
supported_housing: "Enter a value for the service charge between £0 and £280 per week if the landlord is a private registered provider and it is a supported housing letting"
general_needs: "Enter a value for the service charge between £0 and £155 per week if the landlord is a private registered provider and it is a general needs letting"
supported_housing: "Enter a value for the service charge between £0 and £480 per week if the landlord is a private registered provider and it is a supported housing letting"
local_authority:
general_needs: "Enter a value for the service charge between £0 and £45 per week if the landlord is a local authority and it is a general needs letting"
supported_housing: "Enter a value for the service charge between £0 and £165 per week if the landlord is a local authority and it is a supported housing letting"
general_needs: "Enter a value for the service charge between £0 and £155 per week if the landlord is a local authority and it is a general needs letting"
supported_housing: "Enter a value for the service charge between £0 and £365 per week if the landlord is a local authority and it is a supported housing letting"
pscharge:
private_registered_provider:
general_needs: "Enter a value for the personal service charge between £0 and £30 per week if the landlord is a private registered provider and it is a general needs letting"
@ -272,6 +273,8 @@ en:
local_authority:
general_needs: "Enter a value for the support charge between £0 and £60 per week if the landlord is a local authority and it is a general needs letting"
supported_housing: "Enter a value for the support charge between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting"
ecstat:
over_hard_max: "Net income of £%{hard_max} per week is too high for given the tenant’s working situation"
brent:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
@ -316,6 +319,7 @@ en:
equity:
under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%"
over_max: "The maximum initial equity stake is %{max_equity}%"
mortgage: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property"
household:
reasonpref:
@ -331,8 +335,6 @@ en:
leftreg:
question_required: "Tell us whether the person is still serving in the UK armed forces as you told us they’re a current or former regular"
question_not_required: "You cannot answer whether the person is still serving in the UK armed forces as you told us they’re not a current or former regular"
preg_occ:
no_female: "Enter ‘no’ as there are no female tenants aged 11-65 in the household"
age:
retired_male: "A male tenant who is retired must be 65 or over"
retired_female: "A female tenant who is retired must be 60 or over"
@ -467,16 +469,16 @@ en:
social_homebuy: "Social HomeBuy buyers should not have lived here before"
rent_to_buy: "Rent to Buy buyers should not have lived here before"
hodate:
must_be_before_saledate: "Practical completion or handover date must be before exchange date"
must_be_less_than_3_years_from_saledate: "You told us practical completion or handover date is more than 3 years before completion date"
must_be_before_saledate: "Practical completion or handover date must be before sale completion date"
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"
exdate:
must_be_before_saledate: "Contract exchange date must be before completion date"
must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before completion date"
must_be_before_saledate: "Contract exchange date must be before sale completion date"
must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before sale completion date"
saledate:
must_be_after_exdate: "Completion date must be after contract exchange date"
must_be_less_than_1_year_from_exdate: "Completion date must be less than 1 year after contract exchange date"
must_be_less_than_3_years_from_hodate: "You told us completion date is more than 3 years after practical completion or handover date"
must_be_after_hodate: "Completion date must be after practical completion or handover date"
must_be_after_exdate: "Sale completion date must be after contract exchange date"
must_be_less_than_1_year_from_exdate: "Sale completion date must be less than 1 year after contract exchange date"
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"
must_be_after_hodate: "Sale completion date must be after practical completion or handover date"
previous_property_type:
property_type_bedsit: "A bedsit cannot have more than 1 bedroom"
discounted_ownership_value: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
@ -512,7 +514,7 @@ en:
pregnancy:
title: "You told us somebody in the household is pregnant"
no_females: "You also told us there are no female tenants living at the property."
females_not_in_soft_age_range: "You also told us that any female tenants living at the property are in the following age ranges:<ul><li>11 to 16</li><li>50 to 65</li></ul>"
females_not_in_soft_age_range: "You also told us that any female tenants living at the property are in the following age ranges:<ul><li>under 16 years old</li><li>over 50 years old</li></ul>"
major_repairs_date:
title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years"
void_date:
@ -525,6 +527,11 @@ en:
title_text: "The amount of monthly charges is high for this type of property and sale type"
student_not_child:
title_text: "You told us this person is a student aged beween 16 and 19"
discounted_sale_value:
title_text: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
informative_text: "Your given mortgage, deposit and grant total is £%{mortgage_deposit_and_grant_total}"
care_home_charges:
title_text: "Care home charges should be provided if this is a care home accommodation"
devise:
two_factor_authentication:

5
db/migrate/20230313124749_add_carehome_charges_value_check.rb

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

5
db/migrate/20230316162737_add_discounted_sale_value_check.rb

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

3
db/schema.rb

@ -286,6 +286,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do
t.string "address_line2"
t.string "town_or_city"
t.string "county"
t.integer "carehome_charges_value_check"
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"
@ -568,6 +569,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do
t.string "address_line2"
t.string "town_or_city"
t.string "county"
t.integer "nationalbuy2"
t.integer "discounted_sale_value_check"
t.integer "student_not_child_value_check"
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"

147
spec/components/bulk_upload_error_summary_table_component_spec.rb

@ -9,87 +9,114 @@ RSpec.describe BulkUploadErrorSummaryTableComponent, type: :component do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 0)
end
context "when no errors" do
it "does not renders any tables" do
result = render_inline(component)
expect(result).not_to have_selector("table")
describe "#sorted_errors" do
context "when no errors" do
it "does not renders any tables" do
result = render_inline(component)
expect(result).not_to have_selector("table")
end
end
end
context "when below threshold" do
before do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 16)
context "when below threshold" do
before do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 16)
create(:bulk_upload_error, bulk_upload:, col: "A", row: 1)
end
create(:bulk_upload_error, bulk_upload:, col: "A", row: 1)
end
it "does not render tables" do
result = render_inline(component)
expect(result).to have_selector("table", count: 0)
it "does not render tables" do
result = render_inline(component)
expect(result).to have_selector("table", count: 0)
end
end
end
context "when there are 2 independent errors" do
let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) }
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) }
context "when there are 2 independent errors" do
let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) }
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) }
it "renders table for each error" do
result = render_inline(component)
expect(result).to have_selector("table", count: 2)
end
it "renders table for each error" do
result = render_inline(component)
expect(result).to have_selector("table", count: 2)
end
it "renders by col order" do
result = render_inline(component)
order = result.css("table thead th:nth-of-type(2)").map(&:content)
expect(order).to eql(["Column A", "Column B"])
end
it "renders by col order" do
result = render_inline(component)
order = result.css("table thead th:nth-of-type(2)").map(&:content)
expect(order).to eql(["Column A", "Column B"])
end
it "render correct data" do
result = render_inline(component)
it "render correct data" do
result = render_inline(component)
table_1 = result.css("table").first.css("th, td").map(&:content)
table_1 = result.css("table").first.css("th, td").map(&:content)
expect(table_1).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s,
"Column A",
error_1.error,
"1 error",
])
expect(table_1).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s,
"Column A",
error_1.error,
"1 error",
])
table_2 = result.css("table")[1].css("th, td").map(&:content)
table_2 = result.css("table")[1].css("th, td").map(&:content)
expect(table_2).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_2.field.to_sym).to_s,
"Column B",
error_2.error,
"1 error",
])
expect(table_2).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_2.field.to_sym).to_s,
"Column B",
error_2.error,
"1 error",
])
end
end
end
context "when there are 2 grouped errors" do
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, field: "field_1") }
context "when there are 2 grouped errors" do
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, field: "field_1") }
before do
create(:bulk_upload_error, bulk_upload:, col: "A", row: 2, field: "field_1")
end
before do
create(:bulk_upload_error, bulk_upload:, col: "A", row: 2, field: "field_1")
end
it "renders 1 table combining the errors" do
result = render_inline(component)
expect(result).to have_selector("table", count: 1)
end
it "renders 1 table combining the errors" do
result = render_inline(component)
expect(result).to have_selector("table", count: 1)
it "render correct data" do
result = render_inline(component)
table_1 = result.css("table").css("th, td").map(&:content)
expect(table_1).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s,
"Column A",
error_1.error,
"2 errors",
])
end
end
it "render correct data" do
result = render_inline(component)
context "when mix of setup and other errors" do
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, category: "setup") }
table_1 = result.css("table").css("th, td").map(&:content)
before do
create(:bulk_upload_error, bulk_upload:, col: "B", row: 2, category: nil)
end
it "only returns the setup errors" do
result = render_inline(component)
tables = result.css("table")
expect(table_1).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s,
"Column A",
error_1.error,
"2 errors",
])
expect(tables.size).to be(1)
table = result.css("table").css("th, td").map(&:content)
expect(table).to eql([
bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s,
"Column A",
error_1.error,
"1 error",
])
end
end
end

6
spec/factories/lettings_log.rb

@ -30,7 +30,7 @@ FactoryBot.define do
age1 { 34 }
sex1 { "M" }
ethnic { 2 }
national { 4 }
national { 18 }
ecstat1 { 2 }
hhmemb { 1 }
end
@ -43,7 +43,7 @@ FactoryBot.define do
sex1 { "F" }
ethnic_group { 0 }
ethnic { 2 }
national { 4 }
national { 13 }
prevten { 6 }
ecstat1 { 0 }
hhmemb { 2 }
@ -79,7 +79,7 @@ FactoryBot.define do
supcharg { 35 }
tcharge { 325 }
layear { 2 }
waityear { 1 }
waityear { 7 }
postcode_known { 1 }
postcode_full { Faker::Address.postcode }
reasonpref { 1 }

1
spec/features/form/page_routing_spec.rb

@ -16,7 +16,6 @@ RSpec.describe "Form Page Routing" do
before do
allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
allow(validator).to receive(:validate_pregnancy).and_return(true)
sign_in user
end

26
spec/features/lettings_log_spec.rb

@ -94,6 +94,32 @@ RSpec.describe "Lettings Log Features" do
end
end
context "when visiting a subsection check answers page" do
let(:lettings_log) { FactoryBot.create(:lettings_log, :about_completed) }
it "has the correct breadcrumbs with the correct links" do
visit lettings_log_setup_check_answers_path(lettings_log)
breadcrumbs = page.find_all(".govuk-breadcrumbs__link")
expect(breadcrumbs.first.text).to eq "Logs"
expect(breadcrumbs.first[:href]).to eq lettings_logs_path
expect(breadcrumbs[1].text).to eq "Log #{lettings_log.id}"
expect(breadcrumbs[1][:href]).to eq lettings_log_path(lettings_log)
end
end
context "when reviewing a complete log" do
let(:lettings_log) { FactoryBot.create(:lettings_log, :completed) }
it "has the correct breadcrumbs with the correct links" do
visit review_lettings_log_path(lettings_log)
breadcrumbs = page.find_all(".govuk-breadcrumbs__link")
expect(breadcrumbs.first.text).to eq "Logs"
expect(breadcrumbs.first[:href]).to eq lettings_logs_path
expect(breadcrumbs[1].text).to eq "Log #{lettings_log.id}"
expect(breadcrumbs[1][:href]).to eq lettings_log_path(lettings_log)
end
end
context "when the owning organisation question isn't answered" do
it "doesn't show the managing agent question" do
visit("/lettings-logs")

46
spec/features/sales_log_spec.rb

@ -28,7 +28,7 @@ RSpec.describe "Sales Log Features" do
click_link("Logs")
end
it "navigates you to the lettings logs page" do
it "navigates you to the sales logs page" do
expect(page).to have_current_path("/sales-logs")
end
end
@ -65,4 +65,48 @@ RSpec.describe "Sales Log Features" do
end
end
end
context "when signed in as a support user" do
let(:devise_notify_mailer) { DeviseNotifyMailer.new }
let(:notify_client) { instance_double(Notifications::Client) }
let(:otp) { "999111" }
let(:organisation) { FactoryBot.create(:organisation, name: "Big ORG") }
let(:user) { FactoryBot.create(:user, :support, last_sign_in_at: Time.zone.now, organisation:) }
let(:sales_log) { FactoryBot.create(:sales_log, :completed) }
before do
allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer)
allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client)
allow(notify_client).to receive(:send_email).and_return(true)
allow(SecureRandom).to receive(:random_number).and_return(otp)
visit("/sales-logs")
fill_in("user[email]", with: user.email)
fill_in("user[password]", with: user.password)
click_button("Sign in")
fill_in("code", with: otp)
click_button("Submit")
end
context "when visiting a subsection check answers page as a support user" do
it "has the correct breadcrumbs with the correct links" do
visit sales_log_setup_check_answers_path(sales_log.id)
breadcrumbs = page.find_all(".govuk-breadcrumbs__link")
expect(breadcrumbs.first.text).to eq "Logs"
expect(breadcrumbs.first[:href]).to eq sales_logs_path
expect(breadcrumbs[1].text).to eq "Log #{sales_log.id}"
expect(breadcrumbs[1][:href]).to eq sales_log_path(sales_log.id)
end
end
context "when reviewing a complete log" do
it "has the correct breadcrumbs with the correct links" do
visit review_sales_log_path(sales_log.id, sales_log: true)
breadcrumbs = page.find_all(".govuk-breadcrumbs__link")
expect(breadcrumbs.first.text).to eq "Logs"
expect(breadcrumbs.first[:href]).to eq sales_logs_path
expect(breadcrumbs[1].text).to eq "Log #{sales_log.id}"
expect(breadcrumbs[1][:href]).to eq sales_log_path(sales_log.id)
end
end
end
end

2
spec/fixtures/exports/general_needs_log.csv vendored

@ -1,2 +1,2 @@
status,tenancycode,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,ppcodenk,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,hhtype,new_old,vacdays,formid,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate
2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00
2,BZ737,35,F,2,13,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,7,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00

1 status tenancycode age1 sex1 ethnic national prevten ecstat1 hhmemb age2 sex2 ecstat2 age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap leftreg reservist illness preg_occ startertenancy tenancylength tenancy ppostcode_full rsnvac unittype_gn beds offered wchair earnings incfreq benefits period layear waityear postcode_full reasonpref cbl chr cap reasonother housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h illness_type_1 illness_type_2 illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother irproduct_other reason propcode la prevloc hb hbrentshortfall mrcdate incref startdate armedforces unitletas builtype voiddate renttype needstype lettype totchild totelder totadult nocharge referral brent scharge pscharge supcharg tcharge tshortfall chcharge ppcodenk has_benefits renewal wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat2 relat3 relat4 relat5 relat6 relat7 relat8 lar irproduct joint sheltered hhtype new_old vacdays formid owningorgid owningorgname hcnum maningorgid maningorgname manhcnum createddate uploaddate
2 2 BZ737 35 F 2 4 13 6 0 2 32 M 6 1 4 1 1 1 2 1 5 1 SE2 6RT 6 7 3 2 1 68 1 1 2 2 1 7 NW1 5TY 1 2 1 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 4 123 E09000003 E07000105 6 1 2020-05-05T10:36:49+01:00 0 2022-02-02T10:36:49+00:00 1 2 1 2019-11-03T00:00:00+00:00 2 1 7 0 0 2 0 2 200.0 50.0 40.0 35.0 325.0 12.0 1 1 0 100.0 25.0 20.0 17.5 162.5 6.0 0 1 2 P 4 2 638 {id} {owning_org_id} DLUHC 1234 {managing_org_id} DLUHC 1234 2022-05-01T00:00:00+01:00 2022-05-01T00:00:00+01:00

4
spec/fixtures/exports/general_needs_log.xml vendored

@ -6,7 +6,7 @@
<age1>35</age1>
<sex1>F</sex1>
<ethnic>2</ethnic>
<national>4</national>
<national>13</national>
<prevten>6</prevten>
<ecstat1>0</ecstat1>
<hhmemb>2</hhmemb>
@ -51,7 +51,7 @@
<benefits>1</benefits>
<period>2</period>
<layear>2</layear>
<waityear>1</waityear>
<waityear>7</waityear>
<postcode_full>NW1 5TY</postcode_full>
<reasonpref>1</reasonpref>
<cbl>2</cbl>

4
spec/fixtures/exports/supported_housing_logs.xml vendored

@ -6,7 +6,7 @@
<age1>35</age1>
<sex1>F</sex1>
<ethnic>2</ethnic>
<national>4</national>
<national>13</national>
<prevten>6</prevten>
<ecstat1>0</ecstat1>
<hhmemb>2</hhmemb>
@ -50,7 +50,7 @@
<benefits>1</benefits>
<period>2</period>
<layear>2</layear>
<waityear>1</waityear>
<waityear>7</waityear>
<postcode_full>SW1A 2AA</postcode_full>
<reasonpref>1</reasonpref>
<cbl>2</cbl>

4
spec/fixtures/files/lettings_logs_download.csv vendored

@ -1,2 +1,2 @@
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate}
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate}

1 id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year needstype renewal startdate rent_type_detail irproduct_other tenancycode propcode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 retirement_value_check ecstat2 armedforces leftreg illness housingneeds_a housingneeds_b housingneeds_c housingneeds_h is_previous_la_inferred prevloc_label prevloc illness_type_1 illness_type_2 is_la_inferred la_label la postcode_known postcode_full previous_la_known wchair preg_occ cbl earnings incfreq net_income_value_check benefits hb period brent scharge pscharge supcharg tcharge offered layear ppostcode_full mrcdate declaration ethnic national prevten age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap reservist startertenancy tenancylength tenancy rsnvac unittype_gn beds waityear reasonpref chr cap reasonother housingneeds_f housingneeds_g illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother property_owner_organisation property_manager_organisation purchaser_code reason majorrepairs hbrentshortfall property_relet incref first_time_property_let_as_social_housing unitletas builtype voiddate renttype lettype totchild totelder totadult net_income_known nocharge is_carehome household_charge referral tshortfall chcharge ppcodenk age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known ethnic_group letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 has_benefits wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat3 relat4 relat5 relat6 relat7 relat8 rent_value_check old_form_id lar irproduct old_id joint tshortfall_known sheltered pregnancy_value_check hhtype new_old vacdays major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other unresolved updated_by_id uprn uprn_known uprn_confirmed address_line1 address_line2 town_or_city county carehome_charges_value_check unittype_sh scheme_code scheme_service_name scheme_sensitive scheme_type 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_admin_district location_startdate
2 {id} in_progress 2022-02-08 16:52:15 +0000 2022-02-08 16:52:15 +0000 Danny Rojas No DLUHC DLUHC 2021 Supported housing 2 October 2021 London Affordable Rent No No Westminster E09000033 SE1 1TE No 2 8 0 0 0 0 0 0 9 1 6 {scheme_code} {scheme_service_name} {scheme_sensitive} Missing No DLUHC {scheme_primary_client_group} {scheme_secondary_client_group} {scheme_support_type} {scheme_intended_stay} 2021-04-01 00:00:00 +0100 {location_code} SE1 1TE Downing Street 20 Bungalow Fitted with equipment and adaptations Westminster {location_startdate}

4
spec/fixtures/files/lettings_logs_download_codes_only.csv vendored

@ -1,2 +1,2 @@
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate}
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate}

1 id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year needstype renewal startdate rent_type_detail irproduct_other tenancycode propcode age1 sex1 ecstat1 hhmemb relat2 age2 sex2 retirement_value_check ecstat2 armedforces leftreg illness housingneeds_a housingneeds_b housingneeds_c housingneeds_h is_previous_la_inferred prevloc_label prevloc illness_type_1 illness_type_2 is_la_inferred la_label la postcode_known postcode_full previous_la_known wchair preg_occ cbl earnings incfreq net_income_value_check benefits hb period brent scharge pscharge supcharg tcharge offered layear ppostcode_full mrcdate declaration ethnic national prevten age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap reservist startertenancy tenancylength tenancy rsnvac unittype_gn beds waityear reasonpref chr cap reasonother housingneeds_f housingneeds_g illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother property_owner_organisation property_manager_organisation purchaser_code reason majorrepairs hbrentshortfall property_relet incref first_time_property_let_as_social_housing unitletas builtype voiddate renttype lettype totchild totelder totadult net_income_known nocharge is_carehome household_charge referral tshortfall chcharge ppcodenk age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known ethnic_group letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 has_benefits wrent wscharge wpschrge wsupchrg wtcharge wtshortfall refused housingneeds wchchrg newprop relat3 relat4 relat5 relat6 relat7 relat8 rent_value_check old_form_id lar irproduct old_id joint tshortfall_known sheltered pregnancy_value_check hhtype new_old vacdays major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other unresolved updated_by_id uprn uprn_known uprn_confirmed address_line1 address_line2 town_or_city county carehome_charges_value_check unittype_sh scheme_code scheme_service_name scheme_sensitive scheme_type 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_admin_district location_startdate
2 {id} in_progress 2022-02-08 16:52:15 +0000 2022-02-08 16:52:15 +0000 Danny Rojas false DLUHC DLUHC 2021 2 2 October 2021 2 false false Westminster E09000033 SE1 1TE 2 2 8 0 0 0 0 0 0 9 1 6 {scheme_code} {scheme_service_name} {scheme_sensitive} 0 1 DLUHC {scheme_primary_client_group} {scheme_secondary_client_group} {scheme_support_type} {scheme_intended_stay} 2021-04-01 00:00:00 +0100 {location_code} SE1 1TE Downing Street 20 6 A Westminster {location_startdate}

4
spec/fixtures/files/lettings_logs_download_non_support.csv vendored

@ -1,2 +1,2 @@
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,renewal,startdate,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,relat2,age2,sex2,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,prevloc_label,illness_type_1,illness_type_2,la_label,postcode_full,wchair,preg_occ,cbl,earnings,incfreq,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,unitletas,builtype,voiddate,lettype,nocharge,household_charge,referral,tshortfall,chcharge,ppcodenk,ethnic_group,has_benefits,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,2 October 2021,,,,,,,,,,,,,,,,,,,,,Westminster,SE1 1TE,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,0,,,,,,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate}
id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,renewal,startdate,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,relat2,age2,sex2,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,prevloc_label,illness_type_1,illness_type_2,la_label,postcode_full,wchair,preg_occ,cbl,earnings,incfreq,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,unitletas,builtype,voiddate,lettype,nocharge,household_charge,referral,tshortfall,chcharge,ppcodenk,ethnic_group,has_benefits,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,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_admin_district,location_startdate
{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,2 October 2021,,,,,,,,,,,,,,,,,,,,,Westminster,SE1 1TE,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,0,,,,,,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate}

1 id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year renewal startdate irproduct_other tenancycode propcode age1 sex1 ecstat1 relat2 age2 sex2 ecstat2 armedforces leftreg illness housingneeds_a housingneeds_b housingneeds_c housingneeds_h prevloc_label illness_type_1 illness_type_2 la_label postcode_full wchair preg_occ cbl earnings incfreq benefits hb period brent scharge pscharge supcharg tcharge offered layear ppostcode_full mrcdate declaration ethnic national prevten age3 sex3 ecstat3 age4 sex4 ecstat4 age5 sex5 ecstat5 age6 sex6 ecstat6 age7 sex7 ecstat7 age8 sex8 ecstat8 homeless underoccupation_benefitcap reservist startertenancy tenancylength tenancy rsnvac unittype_gn beds waityear reasonpref chr cap reasonother housingneeds_f housingneeds_g illness_type_3 illness_type_4 illness_type_8 illness_type_5 illness_type_6 illness_type_7 illness_type_9 illness_type_10 rp_homeless rp_insan_unsat rp_medwel rp_hardship rp_dontknow tenancyother property_owner_organisation property_manager_organisation purchaser_code reason majorrepairs hbrentshortfall property_relet incref unitletas builtype voiddate lettype nocharge household_charge referral tshortfall chcharge ppcodenk ethnic_group has_benefits refused housingneeds wchchrg newprop relat3 relat4 relat5 relat6 relat7 relat8 lar irproduct joint sheltered major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other uprn uprn_known uprn_confirmed address_line1 address_line2 town_or_city county carehome_charges_value_check unittype_sh scheme_code scheme_service_name scheme_sensitive scheme_type 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_admin_district location_startdate
2 {id} in_progress 2022-02-08 16:52:15 +0000 2022-02-08 16:52:15 +0000 Danny Rojas No DLUHC DLUHC 2021 2 October 2021 Westminster SE1 1TE No 8 0 0 0 6 {scheme_code} {scheme_service_name} {scheme_sensitive} Missing No DLUHC {scheme_primary_client_group} {scheme_secondary_client_group} {scheme_support_type} {scheme_intended_stay} 2021-04-01 00:00:00 +0100 {location_code} SE1 1TE Downing Street 20 Bungalow Fitted with equipment and adaptations Westminster {location_startdate}

1
spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml vendored

@ -119,6 +119,7 @@
<Q10-g>Yes</Q10-g>
<Q10-h/>
<Q10ia>2 No</Q10ia>
<joint>2 No</joint>
<Q10ib-1/>
<Q10ib-2/>
<Q10ib-3/>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save