Browse Source

Merge branch 'main' into CLDC-3001-Handle-locations-and-logs-on-deactivate-schemes

pull/2605/head
Manny Dinssa 2 years ago committed by GitHub
parent
commit
1dd414c6f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      Gemfile.lock
  2. 80
      app/controllers/form_controller.rb
  3. 8
      app/controllers/users_controller.rb
  4. 9
      app/helpers/form_page_error_helper.rb
  5. 10
      app/models/csv_variable_definition.rb
  6. 4
      app/models/lettings_log.rb
  7. 8
      app/models/sales_log.rb
  8. 15
      app/models/user.rb
  9. 3
      app/models/validations/sales/financial_validations.rb
  10. 4
      app/models/validations/sales/sale_information_validations.rb
  11. 17
      app/services/csv/lettings_log_csv_service.rb
  12. 20
      app/services/csv/sales_log_csv_service.rb
  13. 4
      app/services/feature_toggle.rb
  14. 53
      app/services/imports/variable_definitions_service.rb
  15. 1
      app/views/form/check_errors.html.erb
  16. 7
      app/views/users/edit.html.erb
  17. 8
      app/views/users/new.html.erb
  18. 2
      app/views/users/show.html.erb
  19. 209
      config/csv/definitions/lettings_download_23_24.csv
  20. 220
      config/csv/definitions/lettings_download_24_25.csv
  21. 269
      config/csv/definitions/sales_download_23_24.csv
  22. 281
      config/csv/definitions/sales_download_24_25.csv
  23. 21
      config/initializers/rails_admin.rb
  24. 15
      db/migrate/20240726152326_create_csv_variable_definitions.rb
  25. 5
      db/migrate/20240819143150_add_phone_extension_to_users.rb
  26. 15
      db/schema.rb
  27. 2
      docs/Gemfile.lock
  28. 4
      lib/tasks/clear_unconfirmed_emails.rake
  29. 9
      lib/tasks/log_variable_definitions.rake
  30. 8
      spec/factories/csv_variable_definitions.rb
  31. 4
      spec/features/user_spec.rb
  32. 1
      spec/fixtures/files/lettings_log_csv_export_codes_23.csv
  33. 1
      spec/fixtures/files/lettings_log_csv_export_codes_24.csv
  34. 1
      spec/fixtures/files/lettings_log_csv_export_labels_23.csv
  35. 1
      spec/fixtures/files/lettings_log_csv_export_labels_24.csv
  36. 1
      spec/fixtures/files/lettings_log_csv_export_non_support_codes_23.csv
  37. 1
      spec/fixtures/files/lettings_log_csv_export_non_support_codes_24.csv
  38. 1
      spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv
  39. 1
      spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv
  40. 1
      spec/fixtures/files/sales_logs_csv_export_codes_23.csv
  41. 1
      spec/fixtures/files/sales_logs_csv_export_codes_24.csv
  42. 1
      spec/fixtures/files/sales_logs_csv_export_labels_23.csv
  43. 1
      spec/fixtures/files/sales_logs_csv_export_labels_24.csv
  44. 1
      spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv
  45. 209
      spec/fixtures/variable_definitions/lettings_download_23_24.csv
  46. 220
      spec/fixtures/variable_definitions/lettings_download_24_25.csv
  47. 269
      spec/fixtures/variable_definitions/sales_download_23_24.csv
  48. 281
      spec/fixtures/variable_definitions/sales_download_24_25.csv
  49. 4
      spec/helpers/filters_helper_spec.rb
  50. 18
      spec/helpers/form_page_error_helper_spec.rb
  51. 36
      spec/lib/tasks/clear_unconfirmed_emails_spec.rb
  52. 41
      spec/lib/tasks/log_variable_definitions_spec.rb
  53. 2
      spec/mailers/resend_invitation_mailer_spec.rb
  54. 10
      spec/models/validations/sales/financial_validations_spec.rb
  55. 311
      spec/requests/form_controller_spec.rb
  56. 2
      spec/requests/organisations_controller_spec.rb
  57. 32
      spec/requests/users_controller_spec.rb
  58. 120
      spec/services/csv/lettings_log_csv_service_spec.rb
  59. 131
      spec/services/csv/sales_log_csv_service_spec.rb
  60. 2
      spec/services/csv/scheme_csv_service_spec.rb
  61. 44
      spec/services/imports/variable_definitions_service_spec.rb
  62. 6
      yarn.lock

10
Gemfile.lock

@ -141,7 +141,7 @@ GEM
coderay (1.1.3) coderay (1.1.3)
coercible (1.0.0) coercible (1.0.0)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
concurrent-ruby (1.3.3) concurrent-ruby (1.3.4)
connection_pool (2.4.1) connection_pool (2.4.1)
crack (1.0.0) crack (1.0.0)
bigdecimal bigdecimal
@ -180,7 +180,7 @@ GEM
rubocop rubocop
smart_properties smart_properties
erubi (1.13.0) erubi (1.13.0)
et-orbi (1.2.7) et-orbi (1.2.11)
tzinfo tzinfo
event_stream_parser (1.0.0) event_stream_parser (1.0.0)
excon (0.109.0) excon (0.109.0)
@ -198,8 +198,8 @@ GEM
faraday-net_http (3.1.0) faraday-net_http (3.1.0)
net-http net-http
ffi (1.16.3) ffi (1.16.3)
fugit (1.10.0) fugit (1.11.1)
et-orbi (~> 1, >= 1.2.7) et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4) raabro (~> 1.4)
globalid (1.2.1) globalid (1.2.1)
activesupport (>= 6.1) activesupport (>= 6.1)
@ -379,7 +379,7 @@ GEM
responders (3.1.1) responders (3.1.1)
actionpack (>= 5.2) actionpack (>= 5.2)
railties (>= 5.2) railties (>= 5.2)
rexml (3.3.3) rexml (3.3.6)
strscan strscan
roo (2.10.1) roo (2.10.1)
nokogiri (~> 1) nokogiri (~> 1)

80
app/controllers/form_controller.rb

@ -26,6 +26,8 @@ class FormController < ApplicationController
flash[:notice] = "You have successfully updated #{updated_question_string}" flash[:notice] = "You have successfully updated #{updated_question_string}"
end end
update_duplication_tracking
pages_requiring_update = pages_requiring_update(shown_page_ids_with_unanswered_questions_before_update) pages_requiring_update = pages_requiring_update(shown_page_ids_with_unanswered_questions_before_update)
redirect_to(successful_redirect_path(pages_requiring_update)) redirect_to(successful_redirect_path(pages_requiring_update))
else else
@ -192,24 +194,49 @@ private
params[@log.model_name.param_key]["interruption_page_referrer_type"].presence params[@log.model_name.param_key]["interruption_page_referrer_type"].presence
end end
def successful_redirect_path(pages_to_check) def page_has_duplicate_check_question
if FeatureToggle.deduplication_flow_enabled? @page.questions.any? { |q| @log.duplicate_check_question_ids.include?(q.id) }
if is_referrer_type?("duplicate_logs") || is_referrer_type?("duplicate_logs_banner") end
return correcting_duplicate_logs_redirect_path
def update_duplication_tracking
return unless page_has_duplicate_check_question
class_name = @log.class.name.underscore
dynamic_duplicates = current_user.send(class_name.pluralize).duplicate_logs(@log)
if dynamic_duplicates.any?
saved_duplicates = @log.duplicates
if saved_duplicates.none? || duplicates_changed?(dynamic_duplicates, saved_duplicates)
duplicate_set_id = dynamic_duplicates.first.duplicate_set_id || new_duplicate_set_id(@log)
update_logs_with_duplicate_set_id(@log, dynamic_duplicates, duplicate_set_id)
saved_duplicates.first.update!(duplicate_set_id: nil) if saved_duplicates.count == 1
end end
else
remove_fixed_duplicate_set_ids(@log)
end
end
dynamic_duplicates = @log.lettings? ? current_user.lettings_logs.duplicate_logs(@log) : current_user.sales_logs.duplicate_logs(@log) def successful_redirect_path(pages_to_check)
if dynamic_duplicates.any? class_name = @log.class.name.underscore
saved_duplicates = @log.duplicates
if saved_duplicates.none? || duplicates_changed?(dynamic_duplicates, saved_duplicates) if is_referrer_type?("duplicate_logs") || is_referrer_type?("duplicate_logs_banner")
duplicate_set_id = dynamic_duplicates.first.duplicate_set_id || new_duplicate_set_id(@log) original_log = current_user.send(class_name.pluralize).find_by(id: from_referrer_query("original_log_id"))
update_logs_with_duplicate_set_id(@log, dynamic_duplicates, duplicate_set_id)
saved_duplicates.first.update!(duplicate_set_id: nil) if saved_duplicates.count == 1 if original_log.present? && current_user.send(class_name.pluralize).duplicate_logs(original_log).any?
if @log.duplicate_set_id.nil?
flash[:notice] = deduplication_success_banner
end end
return send("#{@log.class.name.underscore}_duplicate_logs_path", @log, original_log_id: @log.id) return send("#{class_name}_duplicate_logs_path", original_log, original_log_id: original_log.id, referrer: params[:referrer], organisation_id: params[:organisation_id])
else
flash[:notice] = deduplication_success_banner
return send("#{class_name}_duplicate_logs_path", "#{class_name}_id".to_sym => from_referrer_query("first_remaining_duplicate_id"), original_log_id: from_referrer_query("original_log_id"), referrer: params[:referrer], organisation_id: params[:organisation_id])
end end
end end
unless @log.duplicate_set_id.nil?
return send("#{@log.class.name.underscore}_duplicate_logs_path", @log, original_log_id: @log.id)
end
if is_referrer_type?("check_answers") if is_referrer_type?("check_answers")
next_page_id = form.next_page_id(@page, @log, current_user) next_page_id = form.next_page_id(@page, @log, current_user)
next_page = form.get_page(next_page_id) next_page = form.get_page(next_page_id)
@ -315,35 +342,6 @@ private
CONFIRMATION_PAGE_IDS = %w[uprn_confirmation uprn_selection].freeze CONFIRMATION_PAGE_IDS = %w[uprn_confirmation uprn_selection].freeze
def correcting_duplicate_logs_redirect_path
class_name = @log.class.name.underscore
original_log = current_user.send(class_name.pluralize).find_by(id: from_referrer_query("original_log_id"))
dynamic_duplicates = current_user.send(class_name.pluralize).duplicate_logs(@log)
if dynamic_duplicates.any?
saved_duplicates = @log.duplicates
if duplicates_changed?(dynamic_duplicates, saved_duplicates)
duplicate_set_id = dynamic_duplicates.first.duplicate_set_id || new_duplicate_set_id(@log)
update_logs_with_duplicate_set_id(@log, dynamic_duplicates, duplicate_set_id)
saved_duplicates.first.update!(duplicate_set_id: nil) if saved_duplicates.count == 1
end
else
remove_fixed_duplicate_set_ids(@log)
end
if original_log.present? && current_user.send(class_name.pluralize).duplicate_logs(original_log).any?
if dynamic_duplicates.none?
flash[:notice] = deduplication_success_banner
end
send("#{class_name}_duplicate_logs_path", original_log, original_log_id: original_log.id, referrer: params[:referrer], organisation_id: params[:organisation_id])
else
remove_fixed_duplicate_set_ids(original_log)
flash[:notice] = deduplication_success_banner
send("#{class_name}_duplicate_logs_path", "#{class_name}_id".to_sym => from_referrer_query("first_remaining_duplicate_id"), original_log_id: from_referrer_query("original_log_id"), referrer: params[:referrer], organisation_id: params[:organisation_id])
end
end
def deduplication_success_banner def deduplication_success_banner
deduplicated_log_link = "<a class=\"govuk-notification-banner__link govuk-!-font-weight-bold\" href=\"#{send("#{@log.class.name.underscore}_path", @log)}\">Log #{@log.id}</a>" deduplicated_log_link = "<a class=\"govuk-notification-banner__link govuk-!-font-weight-bold\" href=\"#{send("#{@log.class.name.underscore}_path", @log)}\">Log #{@log.id}</a>"
changed_labels = { changed_labels = {

8
app/controllers/users_controller.rb

@ -192,14 +192,14 @@ private
def user_params def user_params
if @user == current_user if @user == current_user
if current_user.data_coordinator? || current_user.support? if current_user.data_coordinator? || current_user.support?
params.require(:user).permit(:email, :phone, :name, :password, :password_confirmation, :role, :is_dpo, :is_key_contact, :initial_confirmation_sent) params.require(:user).permit(:email, :phone, :phone_extension, :name, :password, :password_confirmation, :role, :is_dpo, :is_key_contact, :initial_confirmation_sent)
else else
params.require(:user).permit(:email, :phone, :name, :password, :password_confirmation, :initial_confirmation_sent) params.require(:user).permit(:email, :phone, :phone_extension, :name, :password, :password_confirmation, :initial_confirmation_sent)
end end
elsif current_user.data_coordinator? elsif current_user.data_coordinator?
params.require(:user).permit(:email, :phone, :name, :role, :is_dpo, :is_key_contact, :active, :initial_confirmation_sent) params.require(:user).permit(:email, :phone, :phone_extension, :name, :role, :is_dpo, :is_key_contact, :active, :initial_confirmation_sent)
elsif current_user.support? elsif current_user.support?
params.require(:user).permit(:email, :phone, :name, :role, :is_dpo, :is_key_contact, :organisation_id, :active, :initial_confirmation_sent) params.require(:user).permit(:email, :phone, :phone_extension, :name, :role, :is_dpo, :is_key_contact, :organisation_id, :active, :initial_confirmation_sent)
end end
end end

9
app/helpers/form_page_error_helper.rb

@ -4,6 +4,15 @@ module FormPageErrorHelper
other_page_error_ids.each { |id| lettings_log.errors.delete(id) } other_page_error_ids.each { |id| lettings_log.errors.delete(id) }
end end
def remove_duplicate_page_errors(lettings_log)
lettings_log.errors.group_by(&:message).each do |_, errors|
next if errors.size == 1
errors.shift
errors.each { |error| lettings_log.errors.delete(error.attribute) }
end
end
def all_questions_affected_by_errors(log) def all_questions_affected_by_errors(log)
log.errors.map(&:attribute) - [:base] log.errors.map(&:attribute) - [:base]
end end

10
app/models/csv_variable_definition.rb

@ -0,0 +1,10 @@
class CsvVariableDefinition < ApplicationRecord
validates :variable, presence: true
validates :definition, presence: true
validates :log_type, presence: true, inclusion: { in: %w[lettings sales] }
validates :year, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 2000, less_than_or_equal_to: 2099 }
attribute :last_accessed, :datetime
scope :lettings, -> { where(log_type: "lettings") }
scope :sales, -> { where(log_type: "sales") }
end

4
app/models/lettings_log.rb

@ -701,7 +701,9 @@ class LettingsLog < Log
end end
def duplicates def duplicates
LettingsLog.where.not(duplicate_set_id: nil).where(duplicate_set_id:).where.not(id:) return LettingsLog.none if duplicate_set_id.nil?
LettingsLog.where(duplicate_set_id:).where.not(id:)
end end
def address_search_given? def address_search_given?

8
app/models/sales_log.rb

@ -514,7 +514,9 @@ class SalesLog < Log
end end
def duplicates def duplicates
SalesLog.where.not(duplicate_set_id: nil).where(duplicate_set_id:).where.not(id:) return SalesLog.none if duplicate_set_id.nil?
SalesLog.where(duplicate_set_id:).where.not(id:)
end end
def nationality2_uk_or_prefers_not_to_say? def nationality2_uk_or_prefers_not_to_say?
@ -542,4 +544,8 @@ class SalesLog < Log
def address_search_given? def address_search_given?
address_line1_input.present? && postcode_full_input.present? address_line1_input.present? && postcode_full_input.present?
end end
def is_resale?
resale == 1
end
end end

15
app/models/user.rb

@ -19,6 +19,7 @@ class User < ApplicationRecord
validates :password, presence: { if: :password_required? } validates :password, presence: { if: :password_required? }
validates :password, length: { within: Devise.password_length, allow_blank: true } validates :password, length: { within: Devise.password_length, allow_blank: true }
validates :password, confirmation: { if: :password_required? } validates :password, confirmation: { if: :password_required? }
validates :phone_extension, format: { with: /\A\d+\z/, allow_blank: true, message: I18n.t("validations.numeric.format", field: "") }
after_validation :send_data_protection_confirmation_reminder, if: :is_dpo_changed? after_validation :send_data_protection_confirmation_reminder, if: :is_dpo_changed?
@ -142,6 +143,7 @@ class User < ApplicationRecord
sign_in_count: 0, sign_in_count: 0,
initial_confirmation_sent: false, initial_confirmation_sent: false,
reactivate_with_organisation:, reactivate_with_organisation:,
unconfirmed_email: nil,
) )
end end
@ -156,7 +158,6 @@ class User < ApplicationRecord
RESET_PASSWORD_TEMPLATE_ID = "2c410c19-80a7-481c-a531-2bcb3264f8e6".freeze RESET_PASSWORD_TEMPLATE_ID = "2c410c19-80a7-481c-a531-2bcb3264f8e6".freeze
CONFIRMABLE_TEMPLATE_ID = "3fc2e3a7-0835-4b84-ab7a-ce51629eb614".freeze CONFIRMABLE_TEMPLATE_ID = "3fc2e3a7-0835-4b84-ab7a-ce51629eb614".freeze
RECONFIRMABLE_TEMPLATE_ID = "bcdec787-f0a7-46e9-8d63-b3e0a06ee455".freeze RECONFIRMABLE_TEMPLATE_ID = "bcdec787-f0a7-46e9-8d63-b3e0a06ee455".freeze
BETA_ONBOARDING_TEMPLATE_ID = "b48bc2cd-5887-4611-8296-d0ab3ed0e7fd".freeze
USER_REACTIVATED_TEMPLATE_ID = "ac45a899-490e-4f59-ae8d-1256fc0001f9".freeze USER_REACTIVATED_TEMPLATE_ID = "ac45a899-490e-4f59-ae8d-1256fc0001f9".freeze
FOR_OLD_EMAIL_CHANGED_BY_OTHER_USER_TEMPLATE_ID = "3eb80517-1051-4dfc-b4cc-cb18228a3829".freeze FOR_OLD_EMAIL_CHANGED_BY_OTHER_USER_TEMPLATE_ID = "3eb80517-1051-4dfc-b4cc-cb18228a3829".freeze
FOR_NEW_EMAIL_CHANGED_BY_OTHER_USER_TEMPLATE_ID = "0cdd0be1-7fa5-4808-8225-ae4c5a002352".freeze FOR_NEW_EMAIL_CHANGED_BY_OTHER_USER_TEMPLATE_ID = "0cdd0be1-7fa5-4808-8225-ae4c5a002352".freeze
@ -168,8 +169,6 @@ class User < ApplicationRecord
def confirmable_template def confirmable_template
if last_sign_in_at.present? && (unconfirmed_email.blank? || unconfirmed_email == email) if last_sign_in_at.present? && (unconfirmed_email.blank? || unconfirmed_email == email)
USER_REACTIVATED_TEMPLATE_ID USER_REACTIVATED_TEMPLATE_ID
elsif was_migrated_from_softwire? && last_sign_in_at.blank?
BETA_ONBOARDING_TEMPLATE_ID
elsif initial_confirmation_sent && !confirmed? elsif initial_confirmation_sent && !confirmed?
RECONFIRMABLE_TEMPLATE_ID RECONFIRMABLE_TEMPLATE_ID
else else
@ -177,10 +176,6 @@ class User < ApplicationRecord
end end
end end
def was_migrated_from_softwire?
legacy_users.any? || old_user_id.present?
end
def send_confirmation_instructions def send_confirmation_instructions
return unless active? return unless active?
@ -269,6 +264,12 @@ class User < ApplicationRecord
save!(validate: false) save!(validate: false)
end end
def phone_with_extension
return phone if phone_extension.blank?
"#{phone}, Ext. #{phone_extension}"
end
protected protected
# Checks whether a password is needed or not. For validations only. # Checks whether a password is needed or not. For validations only.

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

@ -96,9 +96,10 @@ module Validations::Sales::FinancialValidations
if record.equity < range.min if record.equity < range.min
record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min) record.errors.add :type, 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) record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min)
elsif record.equity > range.max elsif !record.is_resale? && record.equity > range.max
record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max) record.errors.add :type, 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) record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :resale, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
end end
end end

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

@ -222,7 +222,7 @@ module Validations::Sales::SaleInformationValidations
value: record.field_formatted_as_currency("value"), value: record.field_formatted_as_currency("value"),
equity: "#{record.equity}%", equity: "#{record.equity}%",
mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"),
expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")) expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")).html_safe
end end
record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used", record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used",
mortgage: record.field_formatted_as_currency("mortgage"), mortgage: record.field_formatted_as_currency("mortgage"),
@ -230,7 +230,7 @@ module Validations::Sales::SaleInformationValidations
value: record.field_formatted_as_currency("value"), value: record.field_formatted_as_currency("value"),
equity: "#{record.equity}%", equity: "#{record.equity}%",
mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"),
expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")) expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")).html_safe
end end
elsif record.mortgage_not_used? elsif record.mortgage_not_used?
if over_tolerance?(record.deposit, record.expected_shared_ownership_deposit_value, 1) if over_tolerance?(record.deposit, record.expected_shared_ownership_deposit_value, 1)

17
app/services/csv/lettings_log_csv_service.rb

@ -5,10 +5,17 @@ module Csv
@export_type = export_type @export_type = export_type
@year = year @year = year
@attributes = lettings_log_attributes @attributes = lettings_log_attributes
@definitions = lettings_log_definitions
end end
def prepare_csv(logs) def prepare_csv(logs)
CSV.generate(headers: true) do |csv| CSV.generate(headers: true) do |csv|
if @year >= 2023
csv << @attributes.map do |attribute|
record = @definitions.find { |r| r.variable == attribute.downcase }
record&.tap { |r| r.update!(last_accessed: Time.zone.now) }&.definition
end
end
csv << @attributes csv << @attributes
logs.find_each do |log| logs.find_each do |log|
@ -258,6 +265,16 @@ module Csv
@user.support? ? final_attributes : final_attributes - SUPPORT_ONLY_ATTRIBUTES - soft_validations_attributes @user.support? ? final_attributes : final_attributes - SUPPORT_ONLY_ATTRIBUTES - soft_validations_attributes
end end
def lettings_log_definitions
CsvVariableDefinition.lettings.group_by { |record| [record.variable, record.definition] }
.map do |_, options|
exact_match = options.find { |definition| definition.year == @year }
next exact_match if exact_match
options.max_by(&:year)
end
end
def insert_derived_and_related_attributes(ordered_questions) def insert_derived_and_related_attributes(ordered_questions)
ordered_questions.flat_map do |question| ordered_questions.flat_map do |question|
if question.type == "checkbox" if question.type == "checkbox"

20
app/services/csv/sales_log_csv_service.rb

@ -5,11 +5,19 @@ module Csv
@export_type = export_type @export_type = export_type
@year = year @year = year
@attributes = sales_log_attributes @attributes = sales_log_attributes
@definitions = sales_log_definitions
end end
def prepare_csv(logs) def prepare_csv(logs)
CSV.generate(headers: true) do |csv| CSV.generate(headers: true) do |csv|
csv << formatted_attribute_headers formatted_attributes = formatted_attribute_headers
if @year >= 2023
csv << formatted_attributes.map do |attribute|
record = @definitions.find { |r| r.variable == attribute.downcase }
record&.tap { |r| r.update!(last_accessed: Time.zone.now) }&.definition
end
end
csv << formatted_attributes
logs.find_each do |log| logs.find_each do |log|
csv << @attributes.map { |attribute| value(attribute, log) } csv << @attributes.map { |attribute| value(attribute, log) }
@ -161,6 +169,16 @@ module Csv
@user.support? ? final_attributes : final_attributes - SUPPORT_ONLY_ATTRIBUTES @user.support? ? final_attributes : final_attributes - SUPPORT_ONLY_ATTRIBUTES
end end
def sales_log_definitions
CsvVariableDefinition.sales.group_by { |record| [record.variable, record.definition] }
.map do |_, options|
exact_match = options.find { |definition| definition.year == @year }
next exact_match if exact_match
options.max_by(&:year)
end
end
def insert_derived_and_related_attributes(ordered_questions) def insert_derived_and_related_attributes(ordered_questions)
ordered_questions.flat_map do |question| ordered_questions.flat_map do |question|
if question.type == "checkbox" if question.type == "checkbox"

4
app/services/feature_toggle.rb

@ -11,10 +11,6 @@ class FeatureToggle
!Rails.env.development? !Rails.env.development?
end end
def self.deduplication_flow_enabled?
true
end
def self.duplicate_summary_enabled? def self.duplicate_summary_enabled?
true true
end end

53
app/services/imports/variable_definitions_service.rb

@ -0,0 +1,53 @@
require "csv"
module Imports
class VariableDefinitionsService
attr_reader :path, :count
def initialize(path:)
@path = path
@count = 0
end
def call
files = Dir.glob(File.join(@path, "*.csv"))
files.each do |file|
process_file(file)
end
end
private
def process_file(file)
file_name = File.basename(file, ".csv")
parsed_file_name = file_name.split("_")
log_type = parsed_file_name[0]
year = "20#{parsed_file_name[2]}".to_i
records_added = 0
CSV.foreach(file) do |row|
next if row.empty?
variable = row[0].downcase
definition = row[1..].join(",")
next if variable.nil? || definition.nil?
existing_record = CsvVariableDefinition.find_by(variable: variable.strip, definition: definition.strip, log_type:)
if existing_record.nil?
CsvVariableDefinition.create!(
variable: variable.strip,
definition: definition.strip,
log_type:,
year:,
)
records_added += 1
end
end
Rails.logger.debug "Added #{records_added} variable/definition records for file: #{file_name}. Duplicates excluded."
@count += records_added
end
end
end

1
app/views/form/check_errors.html.erb

@ -2,6 +2,7 @@
<div class="govuk-grid-column-three-quarters-from-desktop"> <div class="govuk-grid-column-three-quarters-from-desktop">
<%= form_with model: @log, url: send("#{@log.model_name.param_key}_confirm_clear_answer_path", @log), method: "post", local: true do |f| %> <%= form_with model: @log, url: send("#{@log.model_name.param_key}_confirm_clear_answer_path", @log), method: "post", local: true do |f| %>
<% remove_duplicate_page_errors(@log) %>
<%= f.govuk_error_summary %> <%= f.govuk_error_summary %>
<%= f.hidden_field :page_id, value: @page.id %> <%= f.hidden_field :page_id, value: @page.id %>

7
app/views/users/edit.html.erb

@ -24,7 +24,12 @@
<%= f.govuk_phone_field :phone, <%= f.govuk_phone_field :phone,
label: { text: "Telephone number", size: "m" }, label: { text: "Telephone number", size: "m" },
autocomplete: "phone", autocomplete: "tel-national",
spellcheck: "false" %>
<%= f.govuk_phone_field :phone_extension,
label: { text: "Extension number (optional)", size: "m" },
autocomplete: "tel-extension",
spellcheck: "false" %> spellcheck: "false" %>
<% if current_user.data_coordinator? || current_user.support? %> <% if current_user.data_coordinator? || current_user.support? %>

8
app/views/users/new.html.erb

@ -25,10 +25,16 @@
<%= f.govuk_phone_field :phone, <%= f.govuk_phone_field :phone,
label: { text: "Telephone number", size: "m" }, label: { text: "Telephone number", size: "m" },
autocomplete: "phone", autocomplete: "tel-national",
spellcheck: "false", spellcheck: "false",
value: @user.phone %> value: @user.phone %>
<%= f.govuk_phone_field :phone_extension,
label: { text: "Extension number (optional)", size: "m" },
autocomplete: "tel-extension",
spellcheck: "false",
value: @user.phone_extension %>
<% if current_user.support? %> <% if current_user.support? %>
<% null_option = [OpenStruct.new(id: "", name: "Select an option")] %> <% null_option = [OpenStruct.new(id: "", name: "Select an option")] %>
<% organisations = Organisation.filter_by_active.map { |org| OpenStruct.new(id: org.id, name: org.name) } %> <% organisations = Organisation.filter_by_active.map { |org| OpenStruct.new(id: org.id, name: org.name) } %>

2
app/views/users/show.html.erb

@ -43,7 +43,7 @@
<%= summary_list.with_row do |row| <%= summary_list.with_row do |row|
row.with_key { "Telephone number" } row.with_key { "Telephone number" }
row.with_value { @user.phone } row.with_value { @user.phone_with_extension }
if UserPolicy.new(current_user, @user).edit_telephone_numbers? if UserPolicy.new(current_user, @user).edit_telephone_numbers?
row.with_action(visually_hidden_text: "telephone number", href: aliased_user_edit(@user, current_user), html_attributes: { "data-qa": "change-telephone-number" }) row.with_action(visually_hidden_text: "telephone number", href: aliased_user_edit(@user, current_user), html_attributes: { "data-qa": "change-telephone-number" })
else else

209
config/csv/definitions/lettings_download_23_24.csv

@ -0,0 +1,209 @@
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_by,User the log is created by
is_dpo,Is the user in the assigned_to column the data protection officer?
created_at,Time and date the log was created
updated_by,User who last updated the log
updated_at,Time and date the log was last updated
creation_method,Was the log submitted in-service or via bulk upload?
old_id,The (internal) ID on the old service
old_form_id,The ID the users saw on the old service
collection_start_year,Year collection period opened
assigned_to,User the log is assigned to
owning_organisation_name,Which organisation owns this property?
managing_organisation_name,Which organisation manages this letting?
needstype,What is the needs type?
lettype,What is the letting type?
renewal,Is this letting a renewal?
startdate,What is the tenancy start date?
renttype,What is the rent type? (grouped into SR, IR or AR)
renttype_detail,What is the rent type?
irproduct,Which type of Intermediate Rent is this letting?
irproduct_other,Which 'Other' type of Intermediate Rent is this letting?
lar,Is this a London Affordable Rent letting?
tenancycode,What is the tenant code?
propcode,What is the property reference?
uprn_known,Is the UPRN known?
uprn,If known, property's UPRN
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town or City
county,County
postcode_full,Postcode
is_la_inferred,The internal value to indicate if the LA was inferred from the postcode
la_label,What is the property's local authority?
la,Local authority code
first_time_property_let_as_social_housing,Is this the first time the property has been let as social housing?
unitletas,What rent product was the property most recently let as?
rsnvac,What is the reason for the property being vacant?
newprop,Is this property new to the social rented sector?
offered,How many times was the property offered between becoming vacant and this letting?
unittype_gn,What type of unit is the property?
builtype,Which type of building is the property?
wchair,Is the property built or adapted to wheelchair-user standards?
beds,How many bedrooms does the property have?
voiddate,What is the void date?
vacdays,Number of days the property was vacant
void_date_value_check,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.
majorrepairs,Were any major repairs carried out during the void period?
mrcdate,What date were any major repairs completed on?
major_repairs_date_value_check,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.
joint,Is this a joint tenancy?
startertenancy,Is this a starter tenancy?
tenancy,What is the type of tenancy?
tenancyother,If 'Other', what is the type of tenancy?
tenancylength,What is the length of the fixed-term tenancy to the nearest year?
sheltered,Is this letting in sheltered accommodation?
declaration,Has the tenant seen the MHCLG privacy notice?
hhmemb,How many people live in the household at this letting?
pregnancy_value_check,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.
refused,Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8
hhtype,Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other
totchild,Total number of dependent children in the household (Sum of when RELAT2-8 = C)
totelder,Total number of elders in household (Sum of when AGE1-8 >= 60)
totadult,Total number of adults in household
age1,What is the lead tenant's age?
retirement_value_check,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.
sex1,Which of these best describes the lead tenant's gender identity?
ethnic_group,What is the lead tenant's ethnic group?
ethnic,Which of these best describes the lead tenant's ethnic background?
national,What is the lead tenant's nationality?
ecstat1,Which of these best describes the lead tenant's working situation?
details_known_2,Are the details of tenant 2 known?
relat2,What is person 2's relationship to the lead tenant?
age2,What is person 2's age?
sex2,Which of these best describes person 2's gender identity?
ecstat2,Which of these best describes person 2's working situation?
details_known_3,Are the details of tenant 3 known?
relat3,What is person 3's relationship to the lead tenant?
age3,What is person 3's age?
sex3,Which of these best describes person 3's gender identity?
ecstat3,Which of these best describes person 3's working situation?
details_known_4,Are the details of tenant 4 known?
relat4,What is person 4's relationship to the lead tenant?
age4,What is person 4's age?
sex4,Which of these best describes person 4's gender identity?
ecstat4,Which of these best describes person 4's working situation?
details_known_5,Are the details of tenant 5 known?
relat5,What is person 5's relationship to the lead tenant?
age5,What is person 5's age?
sex5,Which of these best describes person 5's gender identity?
ecstat5,Which of these best describes person 5's working situation?
details_known_6,Are the details of tenant 6 known?
relat6,What is person 6's relationship to the lead tenant?
age6,What is person 6's age?
sex6,Which of these best describes person 6's gender identity?
ecstat6,Which of these best describes person 6's working situation?
details_known_7,Are the details of tenant 7 known?
relat7,What is person 7's relationship to the lead tenant?
age7,What is person 7's age?
sex7,Which of these best describes person 7's gender identity?
ecstat7,Which of these best describes person 7's working situation?
details_known_8,Are the details of tenant 8 known?
relat8,What is person 8's relationship to the lead tenant?
age8,What is person 8's age?
sex8,Which of these best describes person 8's gender identity?
ecstat8,Which of these best describes person 8's working situation?
armedforces,Does anybody in the household have links to the UK armed forces?
leftreg,Is this person still serving in the UK armed forces?
reservist,Was this person seriously injured or ill as a result of serving in the UK armed forces?
preg_occ,Is anybody in the household pregnant?
housingneeds,Does anybody in the household have any disabled access needs?
housingneeds_type,What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)
housingneeds_a,Disabled access needs a) Fully wheelchair-accessible housing
housingneeds_b,Disabled access needs b) Wheelchair access to essential rooms
housingneeds_c,Disabled access needs c) Level access housing
housingneeds_f,Disabled access needs f) Other disabled access needs
housingneeds_g,Disabled access needs g) No disabled access needs
housingneeds_h,Disabled access needs h) Don't know
housingneeds_other,Do they have any other disabled access needs?
illness,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?
illness_type_4,Does this person's condition affect their dexterity?
illness_type_5,Does this person's condition affect their learning or understanding or concentrating?
illness_type_2,Does this person's condition affect their hearing?
illness_type_6,Does this person's condition affect their memory?
illness_type_7,Does this person's condition affect their mental health?
illness_type_3,Does this person's condition affect their mobility?
illness_type_9,Does this person's condition affect them socially or behaviourally?
illness_type_8,Does this person's condition affect their stamina or breathing or fatigue?
illness_type_1,Does this person's condition affect their vision?
illness_type_10,Does this person's condition affect them in another way?
layear,How long has the household continuously lived in the local authority area of the new letting?
waityear,How long has the household been on the local authority waiting list for the new letting?
reason,What is the tenant's main reason for the household leaving their last settled home?
reasonother,If 'Other', what was the main reason for leaving their last settled home?
prevten,Where was the household immediately before this letting?
homeless,Did the household experience homelessness immediately before this letting?
ppcodenk,Previous postcode unknown or previous accommodation was temporary
ppostcode_full,What is the postcode of the household's last settled home?
previous_la_known,Was the local authority of the household's last settled home known?
is_previous_la_inferred,The internal value to indicate if the previous LA was inferred from the postcode
prevloc_label,Previous location LA name
prevloc,Previous location's ONS LA Code
reasonpref,Was the household given reasonable preference by the local authority?
rp_homeless,Reasonable preference reason - They were homeless or about to lose their home (within 56 days)
rp_insan_unsat,Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing
rp_medwel,Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)
rp_hardship,Reasonable preference reason - They needed to move to avoid hardship to themselves or others
rp_dontknow,Reasonable preference reason - Don't Know
cbl,Was the letting made under Choice-Based Lettings (CBL)?
cap,Was the letting made under the Common Allocation Policy (CAP)?
chr,Was the letting made under the Common Housing Register (CHR)?
letting_allocation_none,The letting was not allocated under CBL, CAP, CHR or Accessible Register.
referral,What was the source of referral for this letting?
referral_value_check,The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.
net_income_known,Do you know the household's combined income after tax?
incref,Was the household income refused?
earnings,How much income does the household have in total?
incfreq,How often does the household receive income?
net_income_value_check,Populated when someone hits the soft validation and confirmed in the service
hb,Is the tenant likely to be receiving any of these housing-related benefits?
has_benefits,Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank
benefits,How much of the household's income is from Universal Credit, state pensions or benefits?
household_charge,Does the household pay rent or other charges for the accommodation?
nocharge,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no
period,How often does the household pay rent and other charges?
is_carehome,Is this accommodation a care home?
chcharge,If this is a care home, how much does the household pay every [time period]?
wchchrg,Weekly care home charge
carehome_charges_value_check,Populated when the soft validation and confirmed in the service
brent,What is the basic rent?
wrent,Weekly rent
rent_value_check,Populated when the soft validation and confirmed in the service
scharge,What is the service charge?
wscharge,Weekly service charge
pscharge,What is the personal service charge?
wpschrge,Weekly personal service charge
supcharg,What is the support charge?
wsupchrg,Weekly support charge
tcharge,Total charge to the tenant
wtcharge,Weekly total charge to the tenant
scharge_value_check,Populated when the soft validation and confirmed in the service
pscharge_value_check,Populated when the soft validation and confirmed in the service
supcharg_value_check,Populated when the soft validation and confirmed in the service
hbrentshortfall,After the household has received any housing-related benefits, will they still need to pay for rent and charges?
tshortfall_known,Can you estimate the outstanding amount?
tshortfall,Estimated outstanding amount
wtshortfall,Weekly total rent shortfall charge for tenant receiving housing benefit
scheme_code,What scheme does this letting belong to?
scheme_service_name,From scheme code, we map to the scheme name
scheme_confidential,Does the scheme contain confidential information?
SCHTYPE,What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing
scheme_registered_under_care_act,Is this scheme registered under the Care Standards Act 2000?
scheme_owning_organisation_name,Which organisation owns the housing stock for this scheme?
scheme_primary_client_group,What client group is this scheme intended for?
scheme_has_other_client_group,Does this scheme provide for another client group?
scheme_secondary_client_group,What is the other client group?
scheme_support_type,What support does this scheme provide?
scheme_intended_stay,Intended length of stay
scheme_created_at,Date scheme was created
location_code,Which location is this letting for?
location_postcode,What is the postcode for this location?
location_name,What is the name of this location?
location_units,How many units are at this location?
location_type_of_unit,What is the most common type of unit at this location?
location_mobility_type,What are the mobility standards for the majority of the units in this location?
location_local_authority,What is the local authority of this postcode?
location_startdate,When did the first property in this location become available under this scheme?
Can't render this file because it has a wrong number of fields in line 20.

220
config/csv/definitions/lettings_download_24_25.csv

@ -0,0 +1,220 @@
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_by,User the log is created by
is_dpo,Is the user in the assigned_to column the data protection officer?
created_at,Time and date the log was created
updated_by,User who last updated the log
updated_at,Time and date the log was last updated
creation_method,Was the log submitted in-service or via bulk upload?
collection_start_year,Year collection period opened
address_line1_as_entered,Address line 1 entered in bulk upload file
address_line2_as_entered,Address line 2 entered in bulk upload file
town_or_city_as_entered,Town or city entered in bulk upload file
county_as_entered,County entered in bulk upload file
postcode_full_as_entered,Postcode entered in bulk upload file
la_as_entered,Local authority entered in bulk upload file
bulk_upload_id,ID of a set of bulk uploaded logs
assigned_to,User the log is assigned to
owning_organisation_name,Which organisation owns this property?
managing_organisation_name,Which organisation manages this letting?
needstype,What is the needs type?
lettype,What is the letting type?
renewal,Is this letting a renewal?
startdate,What is the tenancy start date?
renttype,What is the rent type? (grouped into SR, IR or AR)
renttype_detail,What is the rent type?
irproduct,Which type of Intermediate Rent is this letting?
irproduct_other,Which 'Other' type of Intermediate Rent is this letting?
lar,Is this a London Affordable Rent letting?
tenancycode,What is the tenant code?
propcode,What is the property reference?
uprn_known,Is the UPRN known?
uprn,If known, property's UPRN
address_line1_input,Address line 1 input from address matching feature
postcode_full_input,Postcode input from address matching feature
address_search_value_check,Was the 'No address found' page seen?
uprn_selection,UPRN of the address selected
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town or City
county,County
postcode_full,Postcode
is_la_inferred,The internal value to indicate if the LA was inferred from the postcode
la_label,What is the property's local authority?
la,Local authority code
first_time_property_let_as_social_housing,Is this the first time the property has been let as social housing?
unitletas,What rent product was the property most recently let as?
rsnvac,What is the reason for the property being vacant?
newprop,Is this property new to the social rented sector?
unittype_gn,What type of unit is the property?
builtype,Which type of building is the property?
wchair,Is the property built or adapted to wheelchair-user standards?
beds,How many bedrooms does the property have?
voiddate,What is the void date?
vacdays,Number of days the property was vacant
void_date_value_check,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.
majorrepairs,Were any major repairs carried out during the void period?
mrcdate,What date were any major repairs completed on?
major_repairs_date_value_check,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.
joint,Is this a joint tenancy?
startertenancy,Is this a starter tenancy?
tenancy,What is the type of tenancy?
tenancyother,If 'Other', what is the type of tenancy?
tenancylength,What is the length of the fixed-term tenancy to the nearest year?
sheltered,Is this letting in sheltered accommodation?
declaration,Has the tenant seen the MHCLG privacy notice?
hhmemb,How many people live in the household at this letting?
pregnancy_value_check,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.
refused,Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8
hhtype,Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other
totchild,Total number of dependent children in the household (Sum of when RELAT2-8 = C)
totelder,Total number of elders in household (Sum of when AGE1-8 >= 60)
totadult,Total number of adults in household
age1,What is the lead tenant's age?
retirement_value_check,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.
sex1,Which of these best describes the lead tenant's gender identity?
ethnic_group,What is the lead tenant's ethnic group?
ethnic,Which of these best describes the lead tenant's ethnic background?
nationality_all,What is the lead tenant's nationality?
ecstat1,Which of these best describes the lead tenant's working situation?
details_known_2,Are the details of tenant 2 known?
relat2,What is person 2's relationship to the lead tenant?
partner_under_16_value_check,The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?
multiple_partners_value_check,The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?
age2,What is person 2's age?
sex2,Which of these best describes person 2's gender identity?
ecstat2,Which of these best describes person 2's working situation?
details_known_3,Are the details of tenant 3 known?
relat3,What is person 3's relationship to the lead tenant?
age3,What is person 3's age?
sex3,Which of these best describes person 3's gender identity?
ecstat3,Which of these best describes person 3's working situation?
details_known_4,Are the details of tenant 4 known?
relat4,What is person 4's relationship to the lead tenant?
age4,What is person 4's age?
sex4,Which of these best describes person 4's gender identity?
ecstat4,Which of these best describes person 4's working situation?
details_known_5,Are the details of tenant 5 known?
relat5,What is person 5's relationship to the lead tenant?
age5,What is person 5's age?
sex5,Which of these best describes person 5's gender identity?
ecstat5,Which of these best describes person 5's working situation?
details_known_6,Are the details of tenant 6 known?
relat6,What is person 6's relationship to the lead tenant?
age6,What is person 6's age?
sex6,Which of these best describes person 6's gender identity?
ecstat6,Which of these best describes person 6's working situation?
details_known_7,Are the details of tenant 7 known?
relat7,What is person 7's relationship to the lead tenant?
age7,What is person 7's age?
sex7,Which of these best describes person 7's gender identity?
ecstat7,Which of these best describes person 7's working situation?
details_known_8,Are the details of tenant 8 known?
relat8,What is person 8's relationship to the lead tenant?
age8,What is person 8's age?
sex8,Which of these best describes person 8's gender identity?
ecstat8,Which of these best describes person 8's working situation?
armedforces,Does anybody in the household have links to the UK armed forces?
leftreg,Is this person still serving in the UK armed forces?
reservist,Was this person seriously injured or ill as a result of serving in the UK armed forces?
preg_occ,Is anybody in the household pregnant?
housingneeds,Does anybody in the household have any disabled access needs?
housingneeds_type,What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)
housingneeds_a,Disabled access needs a) Fully wheelchair-accessible housing
housingneeds_b,Disabled access needs b) Wheelchair access to essential rooms
housingneeds_c,Disabled access needs c) Level access housing
housingneeds_f,Disabled access needs f) Other disabled access needs
housingneeds_g,Disabled access needs g) No disabled access needs
housingneeds_h,Disabled access needs h) Don't know
housingneeds_other,Do they have any other disabled access needs?
illness,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?
illness_type_4,Does this person's condition affect their dexterity?
illness_type_5,Does this person's condition affect their learning or understanding or concentrating?
illness_type_2,Does this person's condition affect their hearing?
illness_type_6,Does this person's condition affect their memory?
illness_type_7,Does this person's condition affect their mental health?
illness_type_3,Does this person's condition affect their mobility?
illness_type_9,Does this person's condition affect them socially or behaviourally?
illness_type_8,Does this person's condition affect their stamina or breathing or fatigue?
illness_type_1,Does this person's condition affect their vision?
illness_type_10,Does this person's condition affect them in another way?
layear,How long has the household continuously lived in the local authority area of the new letting?
waityear,How long has the household been on the local authority waiting list for the new letting?
reason,What is the tenant's main reason for the household leaving their last settled home?
reasonother,If 'Other', what was the main reason for leaving their last settled home?
reasonother_value_check,The soft validation was confirmed
prevten,Where was the household immediately before this letting?
homeless,Did the household experience homelessness immediately before this letting?
ppcodenk,Previous postcode unknown or previous accommodation was temporary
ppostcode_full,What is the postcode of the household's last settled home?
previous_la_known,Was the local authority of the household's last settled home known?
is_previous_la_inferred,The internal value to indicate if the previous LA was inferred from the postcode
prevloc_label,Previous location LA name
prevloc,Previous location's ONS LA Code
reasonpref,Was the household given reasonable preference by the local authority?
rp_homeless,Reasonable preference reason - They were homeless or about to lose their home (within 56 days)
rp_insan_unsat,Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing
rp_medwel,Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)
rp_hardship,Reasonable preference reason - They needed to move to avoid hardship to themselves or others
rp_dontknow,Reasonable preference reason - Don't Know
cbl,Was the letting made under Choice-Based Lettings (CBL)?
cap,Was the letting made under the Common Allocation Policy (CAP)?
chr,Was the letting made under the Common Housing Register (CHR)?
accessible_register,Was the letting made under the Accessible Register?
letting_allocation_none,The letting was not allocated under CBL, CAP, CHR or Accessible Register.
referral,What was the source of referral for this letting?
referral_value_check,The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.
net_income_known,Do you know the household's combined income after tax?
incref,Was the household income refused?
earnings,How much income does the household have in total?
incfreq,How often does the household receive income?
net_income_value_check,Populated when someone hits the soft validation and confirmed in the service
hb,Is the tenant likely to be receiving any of these housing-related benefits?
has_benefits,Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank
benefits,How much of the household's income is from Universal Credit, state pensions or benefits?
household_charge,Does the household pay rent or other charges for the accommodation?
nocharge,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no
period,How often does the household pay rent and other charges?
is_carehome,Is this accommodation a care home?
chcharge,If this is a care home, how much does the household pay every [time period]?
wchchrg,Weekly care home charge
carehome_charges_value_check,Populated when the soft validation and confirmed in the service
brent,What is the basic rent?
wrent,Weekly rent
rent_value_check,Populated when the soft validation and confirmed in the service
scharge,What is the service charge?
wscharge,Weekly service charge
pscharge,What is the personal service charge?
wpschrge,Weekly personal service charge
supcharg,What is the support charge?
wsupchrg,Weekly support charge
tcharge,Total charge to the tenant
wtcharge,Weekly total charge to the tenant
scharge_value_check,Populated when the soft validation and confirmed in the service
pscharge_value_check,Populated when the soft validation and confirmed in the service
supcharg_value_check,Populated when the soft validation and confirmed in the service
hbrentshortfall,After the household has received any housing-related benefits, will they still need to pay for rent and charges?
tshortfall_known,Can you estimate the outstanding amount?
tshortfall,Estimated outstanding amount
wtshortfall,Weekly total rent shortfall charge for tenant receiving housing benefit
scheme_code,What scheme does this letting belong to?
scheme_service_name,From scheme code, we map to the scheme name
scheme_confidential,Does the scheme contain confidential information?
SCHTYPE,What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing
scheme_registered_under_care_act,Is this scheme registered under the Care Standards Act 2000?
scheme_owning_organisation_name,Which organisation owns the housing stock for this scheme?
scheme_primary_client_group,What client group is this scheme intended for?
scheme_has_other_client_group,Does this scheme provide for another client group?
scheme_secondary_client_group,What is the other client group?
scheme_support_type,What support does this scheme provide?
scheme_intended_stay,Intended length of stay
scheme_created_at,Date scheme was created
location_code,Which location is this letting for?
location_postcode,What is the postcode for this location?
location_name,What is the name of this location?
location_units,How many units are at this location?
location_type_of_unit,What is the most common type of unit at this location?
location_mobility_type,What are the mobility standards for the majority of the units in this location?
location_local_authority,What is the local authority of this postcode?
location_startdate,When did the first property in this location become available under this scheme?
Can't render this file because it has a wrong number of fields in line 25.

269
config/csv/definitions/sales_download_23_24.csv

@ -0,0 +1,269 @@
ID,Log ID
STATUS,Status of log
DUPLICATESET,ID of a set of duplicate logs
CREATEDDATE,Time and date the log was created
UPLOADDATE,Time and date the log was last updated
FORM,The ID on the old service
COLLECTIONYEAR,Year collection period opened
CREATIONMETHOD,Was the log submitted in-service or via bulk upload?
DATAPROTECT,Is the user in the created_by column the data protection officer?
OWNINGORGNAME,Which organisation owned this property before the sale?
MANINGORGNAME,Which organisation reported the sale?
CREATEDBY,User that created the log
USERNAME,User the log is assigned to
DAY,Day of sale completion date
MONTH,Month of sale completion date
YEAR,Year of sale completion date
PURCHID,What is the purchaser code?
OWNERSHIP,Was this purchase made through an ownership scheme?
TYPE,What is the type of shared ownership/discounted ownership/outright sale?
OTHTYPE,If type = 'Other', what is the type of outright sale?
COMPANY,Is the buyer a company?
LIVEINBUYER,Will the buyer(s) live in the property?
JOINT,Is this a joint purchase?
JOINTMORE,Are there more than 2 joint buyers of this property?
BEDS,How many bedrooms does the property have?
PROPTYPE,What type of unit is the property?
BUILTYPE,Which type of building is the property?
UPRN,What is the UPRN of the property?
UPRNCONFIRMED,We found an address that might be this property. Is this the property address?
ADDRESS1,Address line 1
ADDRESS2,Address line 2
TOWNCITY,Town/City
COUNTY,County
PCODE1,Part 1 of the property's postcode
PCODE2,Part 2 of the property's postcode
LA,LA code
LANAME,LA name
WCHAIR,Is the property built or adapted to wheelchair-user standards?
NOINT,Did you interview the buyer to answer these questions?
PRIVACYNOTICE,Has the buyer seen the MHCLG privacy notice?
AGE1,What is buyer 1's age?
SEX1,Which of these best describes buyer 1's gender identity?
ETHNICGROUP1,What is buyer 1's ethnic group?
ETHNIC,Which of the following best describes buyer 1's ethnic background?
NATIONAL,What is buyer 1's nationality?
ECSTAT1,Which of these best describes buyer 1's working situation?
LIVEINBUYER1,Will buyer 1 live in the property?
RELAT2,What is buyer 2 or person 2's relationship to buyer 1?
AGE2,What is buyer 2 or person 2's age?
SEX2,Which of these best describes buyer 2 or person 2's gender identity?
ETHNICGROUP2,What is buyer 2's ethnic group?
ETHNIC2,Which of the following best describes buyer 2's ethnic background?
NATIONAL2,What is buyer 2's nationality?
ECSTAT2,What is buyer 2 or person 2's working situation?
LIVEINBUYER2,Will buyer 2 live in the property?
HHTYPE,Besides the buyer(s), how many other people live or will live in the property?
RELAT3,What is person 3's relationship to buyer 1?
AGE3,What is person 3's age?
SEX3,What is person 3's gender identity?
ECSTAT3,What is person 3's working situation?
RELAT4,What is person 4's relationship to buyer 1?
AGE4,What is person 4's age?
SEX4,What is person 4's gender identity?
ECSTAT4,What is person 4's working situation?
RELAT5,What is person 5's relationship to buyer 1?
AGE5,What is person 5's age?
SEX5,What is person 5's gender identity?
ECSTAT5,What is person 5's working situation?
RELAT6,What is person 6's relationship to buyer 1?
AGE6,What is person 6's age?
SEX6,What is person 6's gender identity?
ECSTAT6,What is person 6's working situation?
PREVTEN,What was buyer 1's previous tenure?
PPCODENK,Do you know the postcode of buyer 1's last settled accommodation?
PPOSTC1,Part 1 of postcode of buyer 1's last settled accommodation
PPOSTC2,Part 2 of postcode of buyer 1's last settled accommodation
PREVIOUSLAKNOWN,Do you know the local authority of buyer 1's last settled accommodation?
PREVLOC,The local authority code of buyer 1's last settled accommodation
PREVLOCNAME,The local authority name of buyer 1's last settled accommodation
PREGYRHA,Was the buyer registered with their PRP (HA)?
PREGOTHER,Was the buyer registered with another PRP (HA)?
PREGLA,Was the buyer registered with the local authority?
PREGGHB,Was the buyer registered with a Help to Buy agent?
PREGBLANK,Populated if pregyrha, pregother, pregla and pregghb are blank
BUY2LIVING,At the time of purchase, was buyer 2 living at the same address as buyer 1?
PREVTEN2,What was buyer 2's previous tenure?
HHREGRES,Have any of the buyers ever served as a regular in the UK armed forces?
HHREGRESSTILL,Is the buyer still serving in the UK armed forces?
ARMEDFORCESSPOUSE,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
DISABLED,Does anyone in the household consider themselves to have a disability?
WHEEL,Does anyone in the household use a wheelchair?
INC1NK,Is buyer 1's annual income known?
INCOME1,What is buyer 1's annual income?
INC1MORT,Was buyer 1's income used for a mortgage application?
INC2NK,Is buyer 1's annual income known?
INCOME2,What is buyer 2's annual income?
INC2MORT,Was buyer 2's income used for a mortgage application?
HB,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
SAVINGSNK,Is the the total amount the buyers had in savings known?
SAVINGS,What is the total amount the buyers had in savings before they paid any deposit for the property?
PREVOWN,Have any of the buyers previously owned a property?
PREVSHARED,Was the previous property under shared ownership?
PROPLEN,How long did the buyer(s) live in the property before purchasing it?
STAIRCASE,Is this a staircasing transaction?
STAIRBOUGHT,What percentage of the property has been bought in this staircasing transaction?
STAIROWNED,What percentage of the property do the buyers now own in total?
STAIRCASETOSALE,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
RESALE,Is this a resale?
EXDAY,Day of the exchange of contracts
EXMONTH,Month of the exchange of contracts
EXYEAR,Year of the exchange of contracts
HODAY,Day of the practical completion or handover date
HOMONTH,Month of the practical completion or handover date
HOYEAR,Year of the practical completion or handover date
LANOMAGR,Was the household rehoused under a local authority nominations agreement?
SOCTEN,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
FROMBEDS,How many bedrooms did the buyer's previous property have?
FROMPROP,What was the previous property type?
SOCPREVTEN,What was the rent type of buyer's previous tenure?
VALUE,What is the full purchase price?
VALUE_VALUE_CHECK,Populated if a soft validation is confirmed.
EQUITY,What was the initial percentage equity stake purchased?
MORTGAGEUSED,Was a mortgage used to buy this property?
MORTGAGE,What is the mortgage amount?
MORTGAGELENDER,What is the name of the mortgage lender?
MORTGAGELENDEROTHER,If mortgagelender = 'Other', what is the name of the mortgage lender?
MORTLEN1,What is the length of the mortgage in years?
EXTRABOR,Does this include any extra borrowing?
DEPOSIT,How much was the cash deposit paid on the property?
CASHDIS,How much cash discount was given through Social Homebuy?
MRENT,What is the basic monthly rent?
HASMSCHARGE,Does the property have any monthly leasehold charges?
MSCHARGE,What are the total monthly leasehold charges for the property?
MSCHARGE_VALUE_CHECK,Populated if a soft validation is confirmed.
DISCOUNT,What was the percentage discount?
GRANT,What was the amount of any loan, grant, discount or subsidy given?
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_at,Time and date the log was created
updated_at,Time and date the log was last updated
old_form_id,The ID on the old service
collection_start_year,Year collection period opened
creation_method,Was the log submitted in-service or via bulk upload?
is_dpo,Is the user in the assigned_to column the data protection officer?
owning_organisation_name,Which organisation owned this property before the sale?
managing_organisation_name,Which organisation reported the sale?
assigned_to,User the log is assigned to
day,Day of sale completion date
month,Month of sale completion date
year,Year of sale completion date
purchid,What is the purchaser code?
ownershipsch,Was this purchase made through an ownership scheme?
type,What is the type of shared ownership/discounted ownership/outright sale?
othtype,If type = 'Other', what is the type of outright sale?
companybuy,Is the buyer a company?
buylivein,Will the buyer(s) live in the property?
jointpur,Is this a joint purchase?
jointmore,Are there more than 2 joint buyers of this property?
beds,How many bedrooms does the property have?
proptype,What type of unit is the property?
builtype,Which type of building is the property?
uprn,What is the UPRN of the property?
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town/City
county,County
pcode1,Part 1 of the property's postcode
pcode2,Part 2 of the property's postcode
la,LA code
la_label,LA name
wchair,Is the property built or adapted to wheelchair-user standards?
noint,Did you interview the buyer to answer these questions?
privacynotice,Has the buyer seen the MHCLG privacy notice?
age1,What is buyer 1's age?
sex1,Which of these best describes buyer 1's gender identity?
ethnic_group,What is buyer 1's ethnic group?
ethnic,Which of the following best describes buyer 1's ethnic background?
national,What is buyer 1's nationality?
ecstat1,Which of these best describes buyer 1's working situation?
buy1livein,Will buyer 1 live in the property?
relat2,What is buyer 2 or person 2's relationship to buyer 1?
age2,What is buyer 2 or person 2's age?
sex2,Which of these best describes buyer 2 or person 2's gender identity?
ethnic_group2,What is buyer 2's ethnic group?
ethnicbuy2,Which of the following best describes buyer 2's ethnic background?
nationalbuy2,What is buyer 2's nationality?
ecstat2,What is buyer 2 or person 2's working situation?
buy2livein,Will buyer 2 live in the property?
hholdcount,Besides the buyer(s), how many other people live or will live in the property?
relat3,What is person 3's relationship to buyer 1?
age3,What is person 3's age?
sex3,What is person 3's gender identity?
ecstat3,What is person 3's working situation?
relat4,What is person 4's relationship to buyer 1?
age4,What is person 4's age?
sex4,What is person 4's gender identity?
ecstat4,What is person 4's working situation?
relat5,What is person 5's relationship to buyer 1?
age5,What is person 5's age?
sex5,What is person 5's gender identity?
ecstat5,What is person 5's working situation?
relat6,What is person 6's relationship to buyer 1?
age6,What is person 6's age?
sex6,What is person 6's gender identity?
ecstat6,What is person 6's working situation?
prevten,What was buyer 1's previous tenure?
ppcodenk,Do you know the postcode of buyer 1's last settled accommodation?
ppostc1,Part 1 of postcode of buyer 1's last settled accommodation
ppostc2,Part 2 of postcode of buyer 1's last settled accommodation
previous_la_known,Do you know the local authority of buyer 1's last settled accommodation?
prevloc,The local authority code of buyer 1's last settled accommodation
prevloc_label,The local authority name of buyer 1's last settled accommodation
pregyrha,Was the buyer registered with their PRP (HA)?
pregother,Was the buyer registered with another PRP (HA)?
pregla,Was the buyer registered with the local authority?
pregghb,Was the buyer registered with a Help to Buy agent?
pregblank,Populated if pregyrha, pregother, pregla and pregghb are blank
buy2living,At the time of purchase, was buyer 2 living at the same address as buyer 1?
prevtenbuy2,What was buyer 2's previous tenure?
hhregres,Have any of the buyers ever served as a regular in the UK armed forces?
hhregresstill,Is the buyer still serving in the UK armed forces?
armedforcesspouse,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
disabled,Does anyone in the household consider themselves to have a disability?
wheel,Does anyone in the household use a wheelchair?
income1nk,Is buyer 1's annual income known?
income1,What is buyer 1's annual income?
inc1mort,Was buyer 1's income used for a mortgage application?
income2nk,Is buyer 2's annual income known?
income2,What is buyer 2's annual income?
inc2mort,Was buyer 2's income used for a mortgage application?
hb,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
savingsnk,Is the the total amount the buyers had in savings known?
savings,What is the total amount the buyers had in savings before they paid any deposit for the property?
prevown,Have any of the buyers previously owned a property?
prevshared,Was the previous property under shared ownership?
proplen,How long did the buyer(s) live in the property before purchasing it?
staircase,Is this a staircasing transaction?
stairbought,What percentage of the property has been bought in this staircasing transaction?
stairowned,What percentage of the property do the buyers now own in total?
staircasesale,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
resale,Is this a resale?
exday,Day of the exchange of contracts
exmonth,Month of the exchange of contracts
exyear,Year of the exchange of contracts
hoday,Day of the practical completion or handover date
homonth,Month of the practical completion or handover date
hoyear,Year of the practical completion or handover date
lanomagr,Was the household rehoused under a local authority nominations agreement?
soctenant,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
frombeds,How many bedrooms did the buyer's previous property have?
fromprop,What was the previous property type?
socprevten,What was the rent type of buyer's previous tenure?
value,What is the full purchase price?
equity,What was the initial percentage equity stake purchased?
mortgageused,Was a mortgage used to buy this property?
mortgage,What is the mortgage amount?
mortgagelender,What is the name of the mortgage lender?
mortgagelenderother,If mortgagelender = 'Other', what is the name of the mortgage lender?
mortlen,What is the length of the mortgage in years?
extrabor,Does this include any extra borrowing?
deposit,How much was the cash deposit paid on the property?
cashdis,How much cash discount was given through Social Homebuy?
mrent,What is the basic monthly rent?
has_mscharge,Does the property have any monthly leasehold charges?
mscharge,What are the total monthly leasehold charges for the property?
discount,What was the percentage discount?
grant,What was the amount of any loan, grant, discount or subsidy given?
Can't render this file because it has a wrong number of fields in line 20.

281
config/csv/definitions/sales_download_24_25.csv

@ -0,0 +1,281 @@
ID,Log ID
STATUS,Status of log
DUPLICATESET,ID of a set of duplicate logs
CREATEDDATE,Time and date the log was created
UPLOADDATE,Time and date the log was last updated
COLLECTIONYEAR,Year collection period opened
CREATIONMETHOD,Was the log submitted in-service or via bulk upload?
BULKUPLOADID,ID of a set of bulk uploaded logs
DATAPROTECT,Is the user in the created_by column the data protection officer?
OWNINGORGNAME,Which organisation owned this property before the sale?
MANINGORGNAME,Which organisation reported the sale?
CREATEDBY,User that created the log
USERNAME,User the log is assigned to
DAY,Day of sale completion date
MONTH,Month of sale completion date
YEAR,Year of sale completion date
PURCHID,What is the purchaser code?
OWNERSHIP,Was this purchase made through an ownership scheme?
TYPE,What is the type of shared ownership/discounted ownership/outright sale?
OTHTYPE,If type = 'Other', what is the type of outright sale?
COMPANY,Is the buyer a company?
LIVEINBUYER,Will the buyer(s) live in the property?
JOINT,Is this a joint purchase?
JOINTMORE,Are there more than 2 joint buyers of this property?
NOINT,Did you interview the buyer to answer these questions?
PRIVACYNOTICE,Has the buyer seen the MHCLG privacy notice?
UPRN,What is the UPRN of the property?
ADDRESS1,Address line 1
ADDRESS2,Address line 2
TOWNCITY,Town/City
COUNTY,County
POSTCODE,Postcode
ISLAINFERRED,The internal value to indicate if the LA was inferred from the postcode
LANAME,LA name
LA,LA code
UPRNSELECTED,UPRN of the address selected
ADDRESS_SEARCH_VALUE_CHECK,Was the 'No address found' page seen?
ADDRESS1INPUT,Address line 1 input from address matching feature
POSTCODEINPUT,Postcode input from address matching feature
BULKADDRESS1,Address line 1 entered in bulk upload file
BULKADDRESS2,Address line 2 entered in bulk upload file
BULKTOWNCITY,Town or city entered in bulk upload file
BULKCOUNTY,County entered in bulk upload file
BULKPOSTCODE,Postcode entered in bulk upload file
BULKLA,Local authority entered in bulk upload file
BEDS,How many bedrooms does the property have?
PROPTYPE,What type of unit is the property?
BUILTYPE,Which type of building is the property?
WCHAIR,Is the property built or adapted to wheelchair-user standards?
AGE1,What is buyer 1's age?
SEX1,Which of these best describes buyer 1's gender identity?
ETHNICGROUP1,What is buyer 1's ethnic group?
ETHNIC,Which of the following best describes buyer 1's ethnic background?
NATIONALITYALL1,What is buyer 1's nationality?
ECSTAT1,Which of these best describes buyer 1's working situation?
LIVEINBUYER1,Will buyer 1 live in the property?
RELAT2,What is buyer 2 or person 2's relationship to buyer 1?
AGE2,What is buyer 2 or person 2's age?
SEX2,Which of these best describes buyer 2 or person 2's gender identity?
ETHNICGROUP2,What is buyer 2's ethnic group?
ETHNIC2,Which of the following best describes buyer 2's ethnic background?
NATIONALITYALL2,What is buyer 2's nationality?
ECSTAT2,What is buyer 2 or person 2's working situation?
LIVEINBUYER2,Will buyer 2 live in the property?
HHTYPE,Besides the buyer(s), how many other people live or will live in the property?
RELAT3,What is person 3's relationship to buyer 1?
AGE3,What is person 3's age?
SEX3,What is person 3's gender identity?
ECSTAT3,What is person 3's working situation?
RELAT4,What is person 4's relationship to buyer 1?
AGE4,What is person 4's age?
SEX4,What is person 4's gender identity?
ECSTAT4,What is person 4's working situation?
RELAT5,What is person 5's relationship to buyer 1?
AGE5,What is person 5's age?
SEX5,What is person 5's gender identity?
ECSTAT5,What is person 5's working situation?
RELAT6,What is person 6's relationship to buyer 1?
AGE6,What is person 6's age?
SEX6,What is person 6's gender identity?
ECSTAT6,What is person 6's working situation?
PREVTEN,What was buyer 1's previous tenure?
PPCODENK,Do you know the postcode of buyer 1's last settled accommodation?
PPOSTC1,Part 1 of postcode of buyer 1's last settled accommodation
PPOSTC2,Part 2 of postcode of buyer 1's last settled accommodation
PREVIOUSLAKNOWN,Do you know the local authority of buyer 1's last settled accommodation?
PREVLOC,The local authority code of buyer 1's last settled accommodation
PREVLOCNAME,The local authority name of buyer 1's last settled accommodation
PREGYRHA,Was the buyer registered with their PRP (HA)?
PREGOTHER,Was the buyer registered with another PRP (HA)?
PREGLA,Was the buyer registered with the local authority?
PREGGHB,Was the buyer registered with a Help to Buy agent?
PREGBLANK,Populated if pregyrha, pregother, pregla and pregghb are blank
BUY2LIVING,At the time of purchase, was buyer 2 living at the same address as buyer 1?
PREVTEN2,What was buyer 2's previous tenure?
HHREGRES,Have any of the buyers ever served as a regular in the UK armed forces?
HHREGRESSTILL,Is the buyer still serving in the UK armed forces?
ARMEDFORCESSPOUSE,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
DISABLED,Does anyone in the household consider themselves to have a disability?
WHEEL,Does anyone in the household use a wheelchair?
INC1NK,Is buyer 1's annual income known?
INCOME1,What is buyer 1's annual income?
INC1MORT,Was buyer 1's income used for a mortgage application?
INC2NK,Is buyer 1's annual income known?
INCOME2,What is buyer 2's annual income?
INC2MORT,Was buyer 2's income used for a mortgage application?
HB,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
SAVINGSNK,Is the the total amount the buyers had in savings known?
SAVINGS,What is the total amount the buyers had in savings before they paid any deposit for the property?
PREVOWN,Have any of the buyers previously owned a property?
PREVSHARED,Was the previous property under shared ownership?
PROPLEN,How long did the buyer(s) live in the property before purchasing it?
STAIRCASE,Is this a staircasing transaction?
STAIRBOUGHT,What percentage of the property has been bought in this staircasing transaction?
STAIROWNED,What percentage of the property do the buyers now own in total?
STAIRCASETOSALE,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
RESALE,Is this a resale?
EXDAY,Day of the exchange of contracts
EXMONTH,Month of the exchange of contracts
EXYEAR,Year of the exchange of contracts
HODAY,Day of the practical completion or handover date
HOMONTH,Month of the practical completion or handover date
HOYEAR,Year of the practical completion or handover date
LANOMAGR,Was the household rehoused under a local authority nominations agreement?
SOCTEN,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
FROMBEDS,How many bedrooms did the buyer's previous property have?
FROMPROP,What was the previous property type?
SOCPREVTEN,What was the rent type of buyer's previous tenure?
VALUE,What is the full purchase price?
VALUE_VALUE_CHECK,Populated if a soft validation is confirmed.
EQUITY,What was the initial percentage equity stake purchased?
MORTGAGEUSED,Was a mortgage used to buy this property?
MORTGAGE,What is the mortgage amount?
MORTGAGELENDER,What is the name of the mortgage lender?
MORTGAGELENDEROTHER,If mortgagelender = 'Other', what is the name of the mortgage lender?
MORTLEN1,What is the length of the mortgage in years?
EXTRABOR,Does this include any extra borrowing?
DEPOSIT,How much was the cash deposit paid on the property?
CASHDIS,How much cash discount was given through Social Homebuy?
MRENT,What is the basic monthly rent?
HASMSCHARGE,Does the property have any monthly leasehold charges?
MSCHARGE,What are the total monthly leasehold charges for the property?
MSCHARGE_VALUE_CHECK,Populated if a soft validation is confirmed.
DISCOUNT,What was the percentage discount?
GRANT,What was the amount of any loan, grant, discount or subsidy given?
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_at,Time and date the log was created
updated_at,Time and date the log was last updated
old_form_id,The ID on the old service
collection_start_year,Year collection period opened
creation_method,Was the log submitted in-service or via bulk upload?
is_dpo,Is the user in the assigned_to column the data protection officer?
owning_organisation_name,Which organisation owned this property before the sale?
managing_organisation_name,Which organisation reported the sale?
assigned_to,User the log is assigned to
day,Day of sale completion date
month,Month of sale completion date
year,Year of sale completion date
purchid,What is the purchaser code?
ownershipsch,Was this purchase made through an ownership scheme?
type,What is the type of shared ownership/discounted ownership/outright sale?
othtype,If type = 'Other', what is the type of outright sale?
companybuy,Is the buyer a company?
buylivein,Will the buyer(s) live in the property?
jointpur,Is this a joint purchase?
jointmore,Are there more than 2 joint buyers of this property?
beds,How many bedrooms does the property have?
proptype,What type of unit is the property?
builtype,Which type of building is the property?
uprn,What is the UPRN of the property?
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1_input,Address line 1 input from address matching feature
postcode_full_input,Postcode input from address matching feature
uprn_selection,UPRN of the address selected
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town/City
county,County
pcode1,Part 1 of the property's postcode
pcode2,Part 2 of the property's postcode
la,LA code
la_label,LA name
wchair,Is the property built or adapted to wheelchair-user standards?
noint,Did you interview the buyer to answer these questions?
privacynotice,Has the buyer seen the MHCLG privacy notice?
age1,What is buyer 1's age?
sex1,Which of these best describes buyer 1's gender identity?
ethnic_group,What is buyer 1's ethnic group?
ethnic,Which of the following best describes buyer 1's ethnic background?
nationality_all,What is buyer 1's nationality?
ecstat1,Which of these best describes buyer 1's working situation?
buy1livein,Will buyer 1 live in the property?
relat2,What is buyer 2 or person 2's relationship to buyer 1?
age2,What is buyer 2 or person 2's age?
sex2,Which of these best describes buyer 2 or person 2's gender identity?
ethnic_group2,What is buyer 2's ethnic group?
ethnicbuy2,Which of the following best describes buyer 2's ethnic background?
nationality_all_buyer2,What is buyer 2's nationality?
ecstat2,What is buyer 2 or person 2's working situation?
buy2livein,Will buyer 2 live in the property?
hholdcount,Besides the buyer(s), how many other people live or will live in the property?
relat3,What is person 3's relationship to buyer 1?
age3,What is person 3's age?
sex3,What is person 3's gender identity?
ecstat3,What is person 3's working situation?
relat4,What is person 4's relationship to buyer 1?
age4,What is person 4's age?
sex4,What is person 4's gender identity?
ecstat4,What is person 4's working situation?
relat5,What is person 5's relationship to buyer 1?
age5,What is person 5's age?
sex5,What is person 5's gender identity?
ecstat5,What is person 5's working situation?
relat6,What is person 6's relationship to buyer 1?
age6,What is person 6's age?
sex6,What is person 6's gender identity?
ecstat6,What is person 6's working situation?
prevten,What was buyer 1's previous tenure?
ppcodenk,Do you know the postcode of buyer 1's last settled accommodation?
ppostc1,Part 1 of postcode of buyer 1's last settled accommodation
ppostc2,Part 2 of postcode of buyer 1's last settled accommodation
previous_la_known,Do you know the local authority of buyer 1's last settled accommodation?
prevloc,The local authority code of buyer 1's last settled accommodation
prevloc_label,The local authority name of buyer 1's last settled accommodation
pregyrha,Was the buyer registered with their PRP (HA)?
pregother,Was the buyer registered with another PRP (HA)?
pregla,Was the buyer registered with the local authority?
pregghb,Was the buyer registered with a Help to Buy agent?
pregblank,Populated if pregyrha, pregother, pregla and pregghb are blank
buy2living,At the time of purchase, was buyer 2 living at the same address as buyer 1?
prevtenbuy2,What was buyer 2's previous tenure?
hhregres,Have any of the buyers ever served as a regular in the UK armed forces?
hhregresstill,Is the buyer still serving in the UK armed forces?
armedforcesspouse,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
disabled,Does anyone in the household consider themselves to have a disability?
wheel,Does anyone in the household use a wheelchair?
income1nk,Is buyer 1's annual income known?
income1,What is buyer 1's annual income?
inc1mort,Was buyer 1's income used for a mortgage application?
income2nk,Is buyer 2's annual income known?
income2,What is buyer 2's annual income?
inc2mort,Was buyer 2's income used for a mortgage application?
hb,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
savingsnk,Is the the total amount the buyers had in savings known?
savings,What is the total amount the buyers had in savings before they paid any deposit for the property?
prevown,Have any of the buyers previously owned a property?
prevshared,Was the previous property under shared ownership?
proplen,How long did the buyer(s) live in the property before purchasing it?
staircase,Is this a staircasing transaction?
stairbought,What percentage of the property has been bought in this staircasing transaction?
stairowned,What percentage of the property do the buyers now own in total?
staircasesale,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
resale,Is this a resale?
exday,Day of the exchange of contracts
exmonth,Month of the exchange of contracts
exyear,Year of the exchange of contracts
hoday,Day of the practical completion or handover date
homonth,Month of the practical completion or handover date
hoyear,Year of the practical completion or handover date
lanomagr,Was the household rehoused under a local authority nominations agreement?
soctenant,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
frombeds,How many bedrooms did the buyer's previous property have?
fromprop,What was the previous property type?
socprevten,What was the rent type of buyer's previous tenure?
value,What is the full purchase price?
equity,What was the initial percentage equity stake purchased?
mortgageused,Was a mortgage used to buy this property?
mortgage,What is the mortgage amount?
mortgagelender,What is the name of the mortgage lender?
mortgagelenderother,If mortgagelender = 'Other', what is the name of the mortgage lender?
mortlen,What is the length of the mortgage in years?
extrabor,Does this include any extra borrowing?
deposit,How much was the cash deposit paid on the property?
cashdis,How much cash discount was given through Social Homebuy?
mrent,What is the basic monthly rent?
has_mscharge,Does the property have any monthly leasehold charges?
mscharge,What are the total monthly leasehold charges for the property?
discount,What was the percentage discount?
grant,What was the amount of any loan, grant, discount or subsidy given?
Can't render this file because it has a wrong number of fields in line 20.

21
config/initializers/rails_admin.rb

@ -25,8 +25,25 @@ RailsAdmin.config do |config|
## == Gravatar integration == ## == Gravatar integration ==
## To disable Gravatar integration in Navigation Bar set to false ## To disable Gravatar integration in Navigation Bar set to false
# config.show_gravatar = true config.show_gravatar = false
config.included_models = %w[LogValidation] config.included_models = %w[LogValidation CsvVariableDefinition]
config.model "LogValidation" do
label "Log Validation"
end
config.model "CsvVariableDefinition" do
label "CSV Variable Definition"
edit do
exclude_fields :last_accessed
field :log_type do
help "Required. Specify the type of log associated with this variable: 'lettings' or 'sales'."
end
field :year do
help "Required. Specify the year this definition should be available from. This definition will be used in subsequent years unless superseded by a newer definition."
end
end
end
config.actions do config.actions do
dashboard # mandatory dashboard # mandatory

15
db/migrate/20240726152326_create_csv_variable_definitions.rb

@ -0,0 +1,15 @@
class CreateCsvVariableDefinitions < ActiveRecord::Migration[7.0]
def change
create_table :csv_variable_definitions do |t|
t.string :variable, null: false
t.string :definition, null: false
t.string :log_type, null: false
t.integer :year, null: false
t.datetime :last_accessed
t.timestamps
end
add_check_constraint :csv_variable_definitions, "log_type IN ('lettings', 'sales')", name: "log_type_check"
add_check_constraint :csv_variable_definitions, "year BETWEEN 2000 AND 2099", name: "year_check"
end
end

5
db/migrate/20240819143150_add_phone_extension_to_users.rb

@ -0,0 +1,5 @@
class AddPhoneExtensionToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :phone_extension, :string
end
end

15
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2024_07_15_082338) do ActiveRecord::Schema[7.0].define(version: 2024_08_19_143150) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -46,6 +46,18 @@ ActiveRecord::Schema[7.0].define(version: 2024_07_15_082338) do
t.index ["user_id"], name: "index_bulk_uploads_on_user_id" t.index ["user_id"], name: "index_bulk_uploads_on_user_id"
end end
create_table "csv_variable_definitions", force: :cascade do |t|
t.string "variable", null: false
t.string "definition", null: false
t.string "log_type", null: false
t.integer "year", null: false
t.datetime "last_accessed"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.check_constraint "log_type::text = ANY (ARRAY['lettings'::character varying::text, 'sales'::character varying::text])", name: "log_type_check"
t.check_constraint "year >= 2000 AND year <= 2099", name: "year_check"
end
create_table "data_protection_confirmations", force: :cascade do |t| create_table "data_protection_confirmations", force: :cascade do |t|
t.bigint "organisation_id" t.bigint "organisation_id"
t.bigint "data_protection_officer_id" t.bigint "data_protection_officer_id"
@ -788,6 +800,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_07_15_082338) do
t.boolean "initial_confirmation_sent" t.boolean "initial_confirmation_sent"
t.boolean "reactivate_with_organisation" t.boolean "reactivate_with_organisation"
t.datetime "discarded_at" t.datetime "discarded_at"
t.string "phone_extension"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true t.index ["email"], name: "index_users_on_email", unique: true
t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true

2
docs/Gemfile.lock

@ -226,7 +226,7 @@ GEM
rb-fsevent (0.11.2) rb-fsevent (0.11.2)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) ffi (~> 1.0)
rexml (3.3.3) rexml (3.3.6)
strscan strscan
rouge (3.26.0) rouge (3.26.0)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)

4
lib/tasks/clear_unconfirmed_emails.rake

@ -0,0 +1,4 @@
desc "Clear unconfimed emails for deactivated users"
task clear_unconfirmed_emails: :environment do
User.deactivated.where.not(unconfirmed_email: nil).update(unconfirmed_email: nil)
end

9
lib/tasks/log_variable_definitions.rake

@ -0,0 +1,9 @@
namespace :data_import do
desc "Add CsvVariableDefinition records for each file in the specified directory"
task :add_variable_definitions, [:path] => :environment do |_task, args|
path = Rails.root.join(args[:path])
service = Imports::VariableDefinitionsService.new(path:)
service.call
Rails.logger.info "CSV Variable Definitions: #{service.count} total records added"
end
end

8
spec/factories/csv_variable_definitions.rb

@ -0,0 +1,8 @@
FactoryBot.define do
factory :csv_variable_definition do
variable { "variable" }
definition { "definition" }
log_type { "lettings" }
year { 2024 }
end
end

4
spec/features/user_spec.rb

@ -600,8 +600,8 @@ RSpec.describe "User Features" do
visit(user_path(other_user)) visit(user_path(other_user))
end end
it "sends beta onboarding email to be sent when user is legacy" do it "sends initial confirmable template email when user is legacy" do
expect(notify_client).to receive(:send_email).with(email_address: "new_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:).once expect(notify_client).to receive(:send_email).with(email_address: "new_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:).once
click_button("Resend invite link") click_button("Resend invite link")
end end
end end

1
spec/fixtures/files/lettings_log_csv_export_codes_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_codes_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_labels_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_labels_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_non_support_codes_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_non_support_codes_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/sales_logs_csv_export_codes_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/sales_logs_csv_export_codes_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/sales_logs_csv_export_labels_23.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/sales_logs_csv_export_labels_24.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv vendored

File diff suppressed because one or more lines are too long

209
spec/fixtures/variable_definitions/lettings_download_23_24.csv vendored

@ -0,0 +1,209 @@
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_by,User the log is created by
is_dpo,Is the user in the assigned_to column the data protection officer?
created_at,Time and date the log was created
updated_by,User who last updated the log
updated_at,Time and date the log was last updated
creation_method,Was the log submitted in-service or via bulk upload?
old_id,The (internal) ID on the old service
old_form_id,The ID the users saw on the old service
collection_start_year,Year collection period opened
assigned_to,User the log is assigned to
owning_organisation_name,Which organisation owns this property?
managing_organisation_name,Which organisation manages this letting?
needstype,What is the needs type?
lettype,What is the letting type?
renewal,Is this letting a renewal?
startdate,What is the tenancy start date?
renttype,What is the rent type? (grouped into SR, IR or AR)
renttype_detail,What is the rent type?
irproduct,Which type of Intermediate Rent is this letting?
irproduct_other,Which 'Other' type of Intermediate Rent is this letting?
lar,Is this a London Affordable Rent letting?
tenancycode,What is the tenant code?
propcode,What is the property reference?
uprn_known,Is the UPRN known?
uprn,If known, property's UPRN
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town or City
county,County
postcode_full,Postcode
is_la_inferred,The internal value to indicate if the LA was inferred from the postcode
la_label,What is the property's local authority?
la,Local authority code
first_time_property_let_as_social_housing,Is this the first time the property has been let as social housing?
unitletas,What rent product was the property most recently let as?
rsnvac,What is the reason for the property being vacant?
newprop,Is this property new to the social rented sector?
offered,How many times was the property offered between becoming vacant and this letting?
unittype_gn,What type of unit is the property?
builtype,Which type of building is the property?
wchair,Is the property built or adapted to wheelchair-user standards?
beds,How many bedrooms does the property have?
voiddate,What is the void date?
vacdays,Number of days the property was vacant
void_date_value_check,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.
majorrepairs,Were any major repairs carried out during the void period?
mrcdate,What date were any major repairs completed on?
major_repairs_date_value_check,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.
joint,Is this a joint tenancy?
startertenancy,Is this a starter tenancy?
tenancy,What is the type of tenancy?
tenancyother,If 'Other', what is the type of tenancy?
tenancylength,What is the length of the fixed-term tenancy to the nearest year?
sheltered,Is this letting in sheltered accommodation?
declaration,Has the tenant seen the MHCLG privacy notice?
hhmemb,How many people live in the household at this letting?
pregnancy_value_check,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.
refused,Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8
hhtype,Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other
totchild,Total number of dependent children in the household (Sum of when RELAT2-8 = C)
totelder,Total number of elders in household (Sum of when AGE1-8 >= 60)
totadult,Total number of adults in household
age1,What is the lead tenant's age?
retirement_value_check,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.
sex1,Which of these best describes the lead tenant's gender identity?
ethnic_group,What is the lead tenant's ethnic group?
ethnic,Which of these best describes the lead tenant's ethnic background?
national,What is the lead tenant's nationality?
ecstat1,Which of these best describes the lead tenant's working situation?
details_known_2,Are the details of tenant 2 known?
relat2,What is person 2's relationship to the lead tenant?
age2,What is person 2's age?
sex2,Which of these best describes person 2's gender identity?
ecstat2,Which of these best describes person 2's working situation?
details_known_3,Are the details of tenant 3 known?
relat3,What is person 3's relationship to the lead tenant?
age3,What is person 3's age?
sex3,Which of these best describes person 3's gender identity?
ecstat3,Which of these best describes person 3's working situation?
details_known_4,Are the details of tenant 4 known?
relat4,What is person 4's relationship to the lead tenant?
age4,What is person 4's age?
sex4,Which of these best describes person 4's gender identity?
ecstat4,Which of these best describes person 4's working situation?
details_known_5,Are the details of tenant 5 known?
relat5,What is person 5's relationship to the lead tenant?
age5,What is person 5's age?
sex5,Which of these best describes person 5's gender identity?
ecstat5,Which of these best describes person 5's working situation?
details_known_6,Are the details of tenant 6 known?
relat6,What is person 6's relationship to the lead tenant?
age6,What is person 6's age?
sex6,Which of these best describes person 6's gender identity?
ecstat6,Which of these best describes person 6's working situation?
details_known_7,Are the details of tenant 7 known?
relat7,What is person 7's relationship to the lead tenant?
age7,What is person 7's age?
sex7,Which of these best describes person 7's gender identity?
ecstat7,Which of these best describes person 7's working situation?
details_known_8,Are the details of tenant 8 known?
relat8,What is person 8's relationship to the lead tenant?
age8,What is person 8's age?
sex8,Which of these best describes person 8's gender identity?
ecstat8,Which of these best describes person 8's working situation?
armedforces,Does anybody in the household have links to the UK armed forces?
leftreg,Is this person still serving in the UK armed forces?
reservist,Was this person seriously injured or ill as a result of serving in the UK armed forces?
preg_occ,Is anybody in the household pregnant?
housingneeds,Does anybody in the household have any disabled access needs?
housingneeds_type,What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)
housingneeds_a,Disabled access needs a) Fully wheelchair-accessible housing
housingneeds_b,Disabled access needs b) Wheelchair access to essential rooms
housingneeds_c,Disabled access needs c) Level access housing
housingneeds_f,Disabled access needs f) Other disabled access needs
housingneeds_g,Disabled access needs g) No disabled access needs
housingneeds_h,Disabled access needs h) Don't know
housingneeds_other,Do they have any other disabled access needs?
illness,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?
illness_type_4,Does this person's condition affect their dexterity?
illness_type_5,Does this person's condition affect their learning or understanding or concentrating?
illness_type_2,Does this person's condition affect their hearing?
illness_type_6,Does this person's condition affect their memory?
illness_type_7,Does this person's condition affect their mental health?
illness_type_3,Does this person's condition affect their mobility?
illness_type_9,Does this person's condition affect them socially or behaviourally?
illness_type_8,Does this person's condition affect their stamina or breathing or fatigue?
illness_type_1,Does this person's condition affect their vision?
illness_type_10,Does this person's condition affect them in another way?
layear,How long has the household continuously lived in the local authority area of the new letting?
waityear,How long has the household been on the local authority waiting list for the new letting?
reason,What is the tenant's main reason for the household leaving their last settled home?
reasonother,If 'Other', what was the main reason for leaving their last settled home?
prevten,Where was the household immediately before this letting?
homeless,Did the household experience homelessness immediately before this letting?
ppcodenk,Previous postcode unknown or previous accommodation was temporary
ppostcode_full,What is the postcode of the household's last settled home?
previous_la_known,Was the local authority of the household's last settled home known?
is_previous_la_inferred,The internal value to indicate if the previous LA was inferred from the postcode
prevloc_label,Previous location LA name
prevloc,Previous location's ONS LA Code
reasonpref,Was the household given reasonable preference by the local authority?
rp_homeless,Reasonable preference reason - They were homeless or about to lose their home (within 56 days)
rp_insan_unsat,Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing
rp_medwel,Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)
rp_hardship,Reasonable preference reason - They needed to move to avoid hardship to themselves or others
rp_dontknow,Reasonable preference reason - Don't Know
cbl,Was the letting made under Choice-Based Lettings (CBL)?
cap,Was the letting made under the Common Allocation Policy (CAP)?
chr,Was the letting made under the Common Housing Register (CHR)?
letting_allocation_none,The letting was not allocated under CBL, CAP, CHR or Accessible Register.
referral,What was the source of referral for this letting?
referral_value_check,The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.
net_income_known,Do you know the household's combined income after tax?
incref,Was the household income refused?
earnings,How much income does the household have in total?
incfreq,How often does the household receive income?
net_income_value_check,Populated when someone hits the soft validation and confirmed in the service
hb,Is the tenant likely to be receiving any of these housing-related benefits?
has_benefits,Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank
benefits,How much of the household's income is from Universal Credit, state pensions or benefits?
household_charge,Does the household pay rent or other charges for the accommodation?
nocharge,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no
period,How often does the household pay rent and other charges?
is_carehome,Is this accommodation a care home?
chcharge,If this is a care home, how much does the household pay every [time period]?
wchchrg,Weekly care home charge
carehome_charges_value_check,Populated when the soft validation and confirmed in the service
brent,What is the basic rent?
wrent,Weekly rent
rent_value_check,Populated when the soft validation and confirmed in the service
scharge,What is the service charge?
wscharge,Weekly service charge
pscharge,What is the personal service charge?
wpschrge,Weekly personal service charge
supcharg,What is the support charge?
wsupchrg,Weekly support charge
tcharge,Total charge to the tenant
wtcharge,Weekly total charge to the tenant
scharge_value_check,Populated when the soft validation and confirmed in the service
pscharge_value_check,Populated when the soft validation and confirmed in the service
supcharg_value_check,Populated when the soft validation and confirmed in the service
hbrentshortfall,After the household has received any housing-related benefits, will they still need to pay for rent and charges?
tshortfall_known,Can you estimate the outstanding amount?
tshortfall,Estimated outstanding amount
wtshortfall,Weekly total rent shortfall charge for tenant receiving housing benefit
scheme_code,What scheme does this letting belong to?
scheme_service_name,From scheme code, we map to the scheme name
scheme_confidential,Does the scheme contain confidential information?
SCHTYPE,What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing
scheme_registered_under_care_act,Is this scheme registered under the Care Standards Act 2000?
scheme_owning_organisation_name,Which organisation owns the housing stock for this scheme?
scheme_primary_client_group,What client group is this scheme intended for?
scheme_has_other_client_group,Does this scheme provide for another client group?
scheme_secondary_client_group,What is the other client group?
scheme_support_type,What support does this scheme provide?
scheme_intended_stay,Intended length of stay
scheme_created_at,Date scheme was created
location_code,Which location is this letting for?
location_postcode,What is the postcode for this location?
location_name,What is the name of this location?
location_units,How many units are at this location?
location_type_of_unit,What is the most common type of unit at this location?
location_mobility_type,What are the mobility standards for the majority of the units in this location?
location_local_authority,What is the local authority of this postcode?
location_startdate,When did the first property in this location become available under this scheme?
Can't render this file because it has a wrong number of fields in line 20.

220
spec/fixtures/variable_definitions/lettings_download_24_25.csv vendored

@ -0,0 +1,220 @@
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_by,User the log is created by
is_dpo,Is the user in the assigned_to column the data protection officer?
created_at,Time and date the log was created
updated_by,User who last updated the log
updated_at,Time and date the log was last updated
creation_method,Was the log submitted in-service or via bulk upload?
collection_start_year,Year collection period opened
address_line1_as_entered,Address line 1 entered in bulk upload file
address_line2_as_entered,Address line 2 entered in bulk upload file
town_or_city_as_entered,Town or city entered in bulk upload file
county_as_entered,County entered in bulk upload file
postcode_full_as_entered,Postcode entered in bulk upload file
la_as_entered,Local authority entered in bulk upload file
bulk_upload_id,ID of a set of bulk uploaded logs
assigned_to,User the log is assigned to
owning_organisation_name,Which organisation owns this property?
managing_organisation_name,Which organisation manages this letting?
needstype,What is the needs type?
lettype,What is the letting type?
renewal,Is this letting a renewal?
startdate,What is the tenancy start date?
renttype,What is the rent type? (grouped into SR, IR or AR)
renttype_detail,What is the rent type?
irproduct,Which type of Intermediate Rent is this letting?
irproduct_other,Which 'Other' type of Intermediate Rent is this letting?
lar,Is this a London Affordable Rent letting?
tenancycode,What is the tenant code?
propcode,What is the property reference?
uprn_known,Is the UPRN known?
uprn,If known, property's UPRN
address_line1_input,Address line 1 input from address matching feature
postcode_full_input,Postcode input from address matching feature
address_search_value_check,Was the 'No address found' page seen?
uprn_selection,UPRN of the address selected
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town or City
county,County
postcode_full,Postcode
is_la_inferred,The internal value to indicate if the LA was inferred from the postcode
la_label,What is the property's local authority?
la,Local authority code
first_time_property_let_as_social_housing,Is this the first time the property has been let as social housing?
unitletas,What rent product was the property most recently let as?
rsnvac,What is the reason for the property being vacant?
newprop,Is this property new to the social rented sector?
unittype_gn,What type of unit is the property?
builtype,Which type of building is the property?
wchair,Is the property built or adapted to wheelchair-user standards?
beds,How many bedrooms does the property have?
voiddate,What is the void date?
vacdays,Number of days the property was vacant
void_date_value_check,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.
majorrepairs,Were any major repairs carried out during the void period?
mrcdate,What date were any major repairs completed on?
major_repairs_date_value_check,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.
joint,Is this a joint tenancy?
startertenancy,Is this a starter tenancy?
tenancy,What is the type of tenancy?
tenancyother,If 'Other', what is the type of tenancy?
tenancylength,What is the length of the fixed-term tenancy to the nearest year?
sheltered,Is this letting in sheltered accommodation?
declaration,Has the tenant seen the MHCLG privacy notice?
hhmemb,How many people live in the household at this letting?
pregnancy_value_check,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.
refused,Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8
hhtype,Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other
totchild,Total number of dependent children in the household (Sum of when RELAT2-8 = C)
totelder,Total number of elders in household (Sum of when AGE1-8 >= 60)
totadult,Total number of adults in household
age1,What is the lead tenant's age?
retirement_value_check,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.
sex1,Which of these best describes the lead tenant's gender identity?
ethnic_group,What is the lead tenant's ethnic group?
ethnic,Which of these best describes the lead tenant's ethnic background?
nationality_all,What is the lead tenant's nationality?
ecstat1,Which of these best describes the lead tenant's working situation?
details_known_2,Are the details of tenant 2 known?
relat2,What is person 2's relationship to the lead tenant?
partner_under_16_value_check,The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?
multiple_partners_value_check,The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?
age2,What is person 2's age?
sex2,Which of these best describes person 2's gender identity?
ecstat2,Which of these best describes person 2's working situation?
details_known_3,Are the details of tenant 3 known?
relat3,What is person 3's relationship to the lead tenant?
age3,What is person 3's age?
sex3,Which of these best describes person 3's gender identity?
ecstat3,Which of these best describes person 3's working situation?
details_known_4,Are the details of tenant 4 known?
relat4,What is person 4's relationship to the lead tenant?
age4,What is person 4's age?
sex4,Which of these best describes person 4's gender identity?
ecstat4,Which of these best describes person 4's working situation?
details_known_5,Are the details of tenant 5 known?
relat5,What is person 5's relationship to the lead tenant?
age5,What is person 5's age?
sex5,Which of these best describes person 5's gender identity?
ecstat5,Which of these best describes person 5's working situation?
details_known_6,Are the details of tenant 6 known?
relat6,What is person 6's relationship to the lead tenant?
age6,What is person 6's age?
sex6,Which of these best describes person 6's gender identity?
ecstat6,Which of these best describes person 6's working situation?
details_known_7,Are the details of tenant 7 known?
relat7,What is person 7's relationship to the lead tenant?
age7,What is person 7's age?
sex7,Which of these best describes person 7's gender identity?
ecstat7,Which of these best describes person 7's working situation?
details_known_8,Are the details of tenant 8 known?
relat8,What is person 8's relationship to the lead tenant?
age8,What is person 8's age?
sex8,Which of these best describes person 8's gender identity?
ecstat8,Which of these best describes person 8's working situation?
armedforces,Does anybody in the household have links to the UK armed forces?
leftreg,Is this person still serving in the UK armed forces?
reservist,Was this person seriously injured or ill as a result of serving in the UK armed forces?
preg_occ,Is anybody in the household pregnant?
housingneeds,Does anybody in the household have any disabled access needs?
housingneeds_type,What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)
housingneeds_a,Disabled access needs a) Fully wheelchair-accessible housing
housingneeds_b,Disabled access needs b) Wheelchair access to essential rooms
housingneeds_c,Disabled access needs c) Level access housing
housingneeds_f,Disabled access needs f) Other disabled access needs
housingneeds_g,Disabled access needs g) No disabled access needs
housingneeds_h,Disabled access needs h) Don't know
housingneeds_other,Do they have any other disabled access needs?
illness,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?
illness_type_4,Does this person's condition affect their dexterity?
illness_type_5,Does this person's condition affect their learning or understanding or concentrating?
illness_type_2,Does this person's condition affect their hearing?
illness_type_6,Does this person's condition affect their memory?
illness_type_7,Does this person's condition affect their mental health?
illness_type_3,Does this person's condition affect their mobility?
illness_type_9,Does this person's condition affect them socially or behaviourally?
illness_type_8,Does this person's condition affect their stamina or breathing or fatigue?
illness_type_1,Does this person's condition affect their vision?
illness_type_10,Does this person's condition affect them in another way?
layear,How long has the household continuously lived in the local authority area of the new letting?
waityear,How long has the household been on the local authority waiting list for the new letting?
reason,What is the tenant's main reason for the household leaving their last settled home?
reasonother,If 'Other', what was the main reason for leaving their last settled home?
reasonother_value_check,The soft validation was confirmed
prevten,Where was the household immediately before this letting?
homeless,Did the household experience homelessness immediately before this letting?
ppcodenk,Previous postcode unknown or previous accommodation was temporary
ppostcode_full,What is the postcode of the household's last settled home?
previous_la_known,Was the local authority of the household's last settled home known?
is_previous_la_inferred,The internal value to indicate if the previous LA was inferred from the postcode
prevloc_label,Previous location LA name
prevloc,Previous location's ONS LA Code
reasonpref,Was the household given reasonable preference by the local authority?
rp_homeless,Reasonable preference reason - They were homeless or about to lose their home (within 56 days)
rp_insan_unsat,Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing
rp_medwel,Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)
rp_hardship,Reasonable preference reason - They needed to move to avoid hardship to themselves or others
rp_dontknow,Reasonable preference reason - Don't Know
cbl,Was the letting made under Choice-Based Lettings (CBL)?
cap,Was the letting made under the Common Allocation Policy (CAP)?
chr,Was the letting made under the Common Housing Register (CHR)?
accessible_register,Was the letting made under the Accessible Register?
letting_allocation_none,The letting was not allocated under CBL, CAP, CHR or Accessible Register.
referral,What was the source of referral for this letting?
referral_value_check,The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.
net_income_known,Do you know the household's combined income after tax?
incref,Was the household income refused?
earnings,How much income does the household have in total?
incfreq,How often does the household receive income?
net_income_value_check,Populated when someone hits the soft validation and confirmed in the service
hb,Is the tenant likely to be receiving any of these housing-related benefits?
has_benefits,Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank
benefits,How much of the household's income is from Universal Credit, state pensions or benefits?
household_charge,Does the household pay rent or other charges for the accommodation?
nocharge,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no
period,How often does the household pay rent and other charges?
is_carehome,Is this accommodation a care home?
chcharge,If this is a care home, how much does the household pay every [time period]?
wchchrg,Weekly care home charge
carehome_charges_value_check,Populated when the soft validation and confirmed in the service
brent,What is the basic rent?
wrent,Weekly rent
rent_value_check,Populated when the soft validation and confirmed in the service
scharge,What is the service charge?
wscharge,Weekly service charge
pscharge,What is the personal service charge?
wpschrge,Weekly personal service charge
supcharg,What is the support charge?
wsupchrg,Weekly support charge
tcharge,Total charge to the tenant
wtcharge,Weekly total charge to the tenant
scharge_value_check,Populated when the soft validation and confirmed in the service
pscharge_value_check,Populated when the soft validation and confirmed in the service
supcharg_value_check,Populated when the soft validation and confirmed in the service
hbrentshortfall,After the household has received any housing-related benefits, will they still need to pay for rent and charges?
tshortfall_known,Can you estimate the outstanding amount?
tshortfall,Estimated outstanding amount
wtshortfall,Weekly total rent shortfall charge for tenant receiving housing benefit
scheme_code,What scheme does this letting belong to?
scheme_service_name,From scheme code, we map to the scheme name
scheme_confidential,Does the scheme contain confidential information?
SCHTYPE,What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing
scheme_registered_under_care_act,Is this scheme registered under the Care Standards Act 2000?
scheme_owning_organisation_name,Which organisation owns the housing stock for this scheme?
scheme_primary_client_group,What client group is this scheme intended for?
scheme_has_other_client_group,Does this scheme provide for another client group?
scheme_secondary_client_group,What is the other client group?
scheme_support_type,What support does this scheme provide?
scheme_intended_stay,Intended length of stay
scheme_created_at,Date scheme was created
location_code,Which location is this letting for?
location_postcode,What is the postcode for this location?
location_name,What is the name of this location?
location_units,How many units are at this location?
location_type_of_unit,What is the most common type of unit at this location?
location_mobility_type,What are the mobility standards for the majority of the units in this location?
location_local_authority,What is the local authority of this postcode?
location_startdate,When did the first property in this location become available under this scheme?
Can't render this file because it has a wrong number of fields in line 25.

269
spec/fixtures/variable_definitions/sales_download_23_24.csv vendored

@ -0,0 +1,269 @@
ID,Log ID
STATUS,Status of log
DUPLICATESET,ID of a set of duplicate logs
CREATEDDATE,Time and date the log was created
UPLOADDATE,Time and date the log was last updated
FORM,The ID on the old service
COLLECTIONYEAR,Year collection period opened
CREATIONMETHOD,Was the log submitted in-service or via bulk upload?
DATAPROTECT,Is the user in the created_by column the data protection officer?
OWNINGORGNAME,Which organisation owned this property before the sale?
MANINGORGNAME,Which organisation reported the sale?
CREATEDBY,User that created the log
USERNAME,User the log is assigned to
DAY,Day of sale completion date
MONTH,Month of sale completion date
YEAR,Year of sale completion date
PURCHID,What is the purchaser code?
OWNERSHIP,Was this purchase made through an ownership scheme?
TYPE,What is the type of shared ownership/discounted ownership/outright sale?
OTHTYPE,If type = 'Other', what is the type of outright sale?
COMPANY,Is the buyer a company?
LIVEINBUYER,Will the buyer(s) live in the property?
JOINT,Is this a joint purchase?
JOINTMORE,Are there more than 2 joint buyers of this property?
BEDS,How many bedrooms does the property have?
PROPTYPE,What type of unit is the property?
BUILTYPE,Which type of building is the property?
UPRN,What is the UPRN of the property?
UPRNCONFIRMED,We found an address that might be this property. Is this the property address?
ADDRESS1,Address line 1
ADDRESS2,Address line 2
TOWNCITY,Town/City
COUNTY,County
PCODE1,Part 1 of the property's postcode
PCODE2,Part 2 of the property's postcode
LA,LA code
LANAME,LA name
WCHAIR,Is the property built or adapted to wheelchair-user standards?
NOINT,Did you interview the buyer to answer these questions?
PRIVACYNOTICE,Has the buyer seen the MHCLG privacy notice?
AGE1,What is buyer 1's age?
SEX1,Which of these best describes buyer 1's gender identity?
ETHNICGROUP1,What is buyer 1's ethnic group?
ETHNIC,Which of the following best describes buyer 1's ethnic background?
NATIONAL,What is buyer 1's nationality?
ECSTAT1,Which of these best describes buyer 1's working situation?
LIVEINBUYER1,Will buyer 1 live in the property?
RELAT2,What is buyer 2 or person 2's relationship to buyer 1?
AGE2,What is buyer 2 or person 2's age?
SEX2,Which of these best describes buyer 2 or person 2's gender identity?
ETHNICGROUP2,What is buyer 2's ethnic group?
ETHNIC2,Which of the following best describes buyer 2's ethnic background?
NATIONAL2,What is buyer 2's nationality?
ECSTAT2,What is buyer 2 or person 2's working situation?
LIVEINBUYER2,Will buyer 2 live in the property?
HHTYPE,Besides the buyer(s), how many other people live or will live in the property?
RELAT3,What is person 3's relationship to buyer 1?
AGE3,What is person 3's age?
SEX3,What is person 3's gender identity?
ECSTAT3,What is person 3's working situation?
RELAT4,What is person 4's relationship to buyer 1?
AGE4,What is person 4's age?
SEX4,What is person 4's gender identity?
ECSTAT4,What is person 4's working situation?
RELAT5,What is person 5's relationship to buyer 1?
AGE5,What is person 5's age?
SEX5,What is person 5's gender identity?
ECSTAT5,What is person 5's working situation?
RELAT6,What is person 6's relationship to buyer 1?
AGE6,What is person 6's age?
SEX6,What is person 6's gender identity?
ECSTAT6,What is person 6's working situation?
PREVTEN,What was buyer 1's previous tenure?
PPCODENK,Do you know the postcode of buyer 1's last settled accommodation?
PPOSTC1,Part 1 of postcode of buyer 1's last settled accommodation
PPOSTC2,Part 2 of postcode of buyer 1's last settled accommodation
PREVIOUSLAKNOWN,Do you know the local authority of buyer 1's last settled accommodation?
PREVLOC,The local authority code of buyer 1's last settled accommodation
PREVLOCNAME,The local authority name of buyer 1's last settled accommodation
PREGYRHA,Was the buyer registered with their PRP (HA)?
PREGOTHER,Was the buyer registered with another PRP (HA)?
PREGLA,Was the buyer registered with the local authority?
PREGGHB,Was the buyer registered with a Help to Buy agent?
PREGBLANK,Populated if pregyrha, pregother, pregla and pregghb are blank
BUY2LIVING,At the time of purchase, was buyer 2 living at the same address as buyer 1?
PREVTEN2,What was buyer 2's previous tenure?
HHREGRES,Have any of the buyers ever served as a regular in the UK armed forces?
HHREGRESSTILL,Is the buyer still serving in the UK armed forces?
ARMEDFORCESSPOUSE,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
DISABLED,Does anyone in the household consider themselves to have a disability?
WHEEL,Does anyone in the household use a wheelchair?
INC1NK,Is buyer 1's annual income known?
INCOME1,What is buyer 1's annual income?
INC1MORT,Was buyer 1's income used for a mortgage application?
INC2NK,Is buyer 1's annual income known?
INCOME2,What is buyer 2's annual income?
INC2MORT,Was buyer 2's income used for a mortgage application?
HB,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
SAVINGSNK,Is the the total amount the buyers had in savings known?
SAVINGS,What is the total amount the buyers had in savings before they paid any deposit for the property?
PREVOWN,Have any of the buyers previously owned a property?
PREVSHARED,Was the previous property under shared ownership?
PROPLEN,How long did the buyer(s) live in the property before purchasing it?
STAIRCASE,Is this a staircasing transaction?
STAIRBOUGHT,What percentage of the property has been bought in this staircasing transaction?
STAIROWNED,What percentage of the property do the buyers now own in total?
STAIRCASETOSALE,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
RESALE,Is this a resale?
EXDAY,Day of the exchange of contracts
EXMONTH,Month of the exchange of contracts
EXYEAR,Year of the exchange of contracts
HODAY,Day of the practical completion or handover date
HOMONTH,Month of the practical completion or handover date
HOYEAR,Year of the practical completion or handover date
LANOMAGR,Was the household rehoused under a local authority nominations agreement?
SOCTEN,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
FROMBEDS,How many bedrooms did the buyer's previous property have?
FROMPROP,What was the previous property type?
SOCPREVTEN,What was the rent type of buyer's previous tenure?
VALUE,What is the full purchase price?
VALUE_VALUE_CHECK,Populated if a soft validation is confirmed.
EQUITY,What was the initial percentage equity stake purchased?
MORTGAGEUSED,Was a mortgage used to buy this property?
MORTGAGE,What is the mortgage amount?
MORTGAGELENDER,What is the name of the mortgage lender?
MORTGAGELENDEROTHER,If mortgagelender = 'Other', what is the name of the mortgage lender?
MORTLEN1,What is the length of the mortgage in years?
EXTRABOR,Does this include any extra borrowing?
DEPOSIT,How much was the cash deposit paid on the property?
CASHDIS,How much cash discount was given through Social Homebuy?
MRENT,What is the basic monthly rent?
HASMSCHARGE,Does the property have any monthly leasehold charges?
MSCHARGE,What are the total monthly leasehold charges for the property?
MSCHARGE_VALUE_CHECK,Populated if a soft validation is confirmed.
DISCOUNT,What was the percentage discount?
GRANT,What was the amount of any loan, grant, discount or subsidy given?
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_at,Time and date the log was created
updated_at,Time and date the log was last updated
old_form_id,The ID on the old service
collection_start_year,Year collection period opened
creation_method,Was the log submitted in-service or via bulk upload?
is_dpo,Is the user in the assigned_to column the data protection officer?
owning_organisation_name,Which organisation owned this property before the sale?
managing_organisation_name,Which organisation reported the sale?
assigned_to,User the log is assigned to
day,Day of sale completion date
month,Month of sale completion date
year,Year of sale completion date
purchid,What is the purchaser code?
ownershipsch,Was this purchase made through an ownership scheme?
type,What is the type of shared ownership/discounted ownership/outright sale?
othtype,If type = 'Other', what is the type of outright sale?
companybuy,Is the buyer a company?
buylivein,Will the buyer(s) live in the property?
jointpur,Is this a joint purchase?
jointmore,Are there more than 2 joint buyers of this property?
beds,How many bedrooms does the property have?
proptype,What type of unit is the property?
builtype,Which type of building is the property?
uprn,What is the UPRN of the property?
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town/City
county,County
pcode1,Part 1 of the property's postcode
pcode2,Part 2 of the property's postcode
la,LA code
la_label,LA name
wchair,Is the property built or adapted to wheelchair-user standards?
noint,Did you interview the buyer to answer these questions?
privacynotice,Has the buyer seen the MHCLG privacy notice?
age1,What is buyer 1's age?
sex1,Which of these best describes buyer 1's gender identity?
ethnic_group,What is buyer 1's ethnic group?
ethnic,Which of the following best describes buyer 1's ethnic background?
national,What is buyer 1's nationality?
ecstat1,Which of these best describes buyer 1's working situation?
buy1livein,Will buyer 1 live in the property?
relat2,What is buyer 2 or person 2's relationship to buyer 1?
age2,What is buyer 2 or person 2's age?
sex2,Which of these best describes buyer 2 or person 2's gender identity?
ethnic_group2,What is buyer 2's ethnic group?
ethnicbuy2,Which of the following best describes buyer 2's ethnic background?
nationalbuy2,What is buyer 2's nationality?
ecstat2,What is buyer 2 or person 2's working situation?
buy2livein,Will buyer 2 live in the property?
hholdcount,Besides the buyer(s), how many other people live or will live in the property?
relat3,What is person 3's relationship to buyer 1?
age3,What is person 3's age?
sex3,What is person 3's gender identity?
ecstat3,What is person 3's working situation?
relat4,What is person 4's relationship to buyer 1?
age4,What is person 4's age?
sex4,What is person 4's gender identity?
ecstat4,What is person 4's working situation?
relat5,What is person 5's relationship to buyer 1?
age5,What is person 5's age?
sex5,What is person 5's gender identity?
ecstat5,What is person 5's working situation?
relat6,What is person 6's relationship to buyer 1?
age6,What is person 6's age?
sex6,What is person 6's gender identity?
ecstat6,What is person 6's working situation?
prevten,What was buyer 1's previous tenure?
ppcodenk,Do you know the postcode of buyer 1's last settled accommodation?
ppostc1,Part 1 of postcode of buyer 1's last settled accommodation
ppostc2,Part 2 of postcode of buyer 1's last settled accommodation
previous_la_known,Do you know the local authority of buyer 1's last settled accommodation?
prevloc,The local authority code of buyer 1's last settled accommodation
prevloc_label,The local authority name of buyer 1's last settled accommodation
pregyrha,Was the buyer registered with their PRP (HA)?
pregother,Was the buyer registered with another PRP (HA)?
pregla,Was the buyer registered with the local authority?
pregghb,Was the buyer registered with a Help to Buy agent?
pregblank,Populated if pregyrha, pregother, pregla and pregghb are blank
buy2living,At the time of purchase, was buyer 2 living at the same address as buyer 1?
prevtenbuy2,What was buyer 2's previous tenure?
hhregres,Have any of the buyers ever served as a regular in the UK armed forces?
hhregresstill,Is the buyer still serving in the UK armed forces?
armedforcesspouse,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
disabled,Does anyone in the household consider themselves to have a disability?
wheel,Does anyone in the household use a wheelchair?
income1nk,Is buyer 1's annual income known?
income1,What is buyer 1's annual income?
inc1mort,Was buyer 1's income used for a mortgage application?
income2nk,Is buyer 2's annual income known?
income2,What is buyer 2's annual income?
inc2mort,Was buyer 2's income used for a mortgage application?
hb,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
savingsnk,Is the the total amount the buyers had in savings known?
savings,What is the total amount the buyers had in savings before they paid any deposit for the property?
prevown,Have any of the buyers previously owned a property?
prevshared,Was the previous property under shared ownership?
proplen,How long did the buyer(s) live in the property before purchasing it?
staircase,Is this a staircasing transaction?
stairbought,What percentage of the property has been bought in this staircasing transaction?
stairowned,What percentage of the property do the buyers now own in total?
staircasesale,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
resale,Is this a resale?
exday,Day of the exchange of contracts
exmonth,Month of the exchange of contracts
exyear,Year of the exchange of contracts
hoday,Day of the practical completion or handover date
homonth,Month of the practical completion or handover date
hoyear,Year of the practical completion or handover date
lanomagr,Was the household rehoused under a local authority nominations agreement?
soctenant,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
frombeds,How many bedrooms did the buyer's previous property have?
fromprop,What was the previous property type?
socprevten,What was the rent type of buyer's previous tenure?
value,What is the full purchase price?
equity,What was the initial percentage equity stake purchased?
mortgageused,Was a mortgage used to buy this property?
mortgage,What is the mortgage amount?
mortgagelender,What is the name of the mortgage lender?
mortgagelenderother,If mortgagelender = 'Other', what is the name of the mortgage lender?
mortlen,What is the length of the mortgage in years?
extrabor,Does this include any extra borrowing?
deposit,How much was the cash deposit paid on the property?
cashdis,How much cash discount was given through Social Homebuy?
mrent,What is the basic monthly rent?
has_mscharge,Does the property have any monthly leasehold charges?
mscharge,What are the total monthly leasehold charges for the property?
discount,What was the percentage discount?
grant,What was the amount of any loan, grant, discount or subsidy given?
Can't render this file because it has a wrong number of fields in line 20.

281
spec/fixtures/variable_definitions/sales_download_24_25.csv vendored

@ -0,0 +1,281 @@
ID,Log ID
STATUS,Status of log
DUPLICATESET,ID of a set of duplicate logs
CREATEDDATE,Time and date the log was created
UPLOADDATE,Time and date the log was last updated
COLLECTIONYEAR,Year collection period opened
CREATIONMETHOD,Was the log submitted in-service or via bulk upload?
BULKUPLOADID,ID of a set of bulk uploaded logs
DATAPROTECT,Is the user in the created_by column the data protection officer?
OWNINGORGNAME,Which organisation owned this property before the sale?
MANINGORGNAME,Which organisation reported the sale?
CREATEDBY,User that created the log
USERNAME,User the log is assigned to
DAY,Day of sale completion date
MONTH,Month of sale completion date
YEAR,Year of sale completion date
PURCHID,What is the purchaser code?
OWNERSHIP,Was this purchase made through an ownership scheme?
TYPE,What is the type of shared ownership/discounted ownership/outright sale?
OTHTYPE,If type = 'Other', what is the type of outright sale?
COMPANY,Is the buyer a company?
LIVEINBUYER,Will the buyer(s) live in the property?
JOINT,Is this a joint purchase?
JOINTMORE,Are there more than 2 joint buyers of this property?
NOINT,Did you interview the buyer to answer these questions?
PRIVACYNOTICE,Has the buyer seen the MHCLG privacy notice?
UPRN,What is the UPRN of the property?
ADDRESS1,Address line 1
ADDRESS2,Address line 2
TOWNCITY,Town/City
COUNTY,County
POSTCODE,Postcode
ISLAINFERRED,The internal value to indicate if the LA was inferred from the postcode
LANAME,LA name
LA,LA code
UPRNSELECTED,UPRN of the address selected
ADDRESS_SEARCH_VALUE_CHECK,Was the 'No address found' page seen?
ADDRESS1INPUT,Address line 1 input from address matching feature
POSTCODEINPUT,Postcode input from address matching feature
BULKADDRESS1,Address line 1 entered in bulk upload file
BULKADDRESS2,Address line 2 entered in bulk upload file
BULKTOWNCITY,Town or city entered in bulk upload file
BULKCOUNTY,County entered in bulk upload file
BULKPOSTCODE,Postcode entered in bulk upload file
BULKLA,Local authority entered in bulk upload file
BEDS,How many bedrooms does the property have?
PROPTYPE,What type of unit is the property?
BUILTYPE,Which type of building is the property?
WCHAIR,Is the property built or adapted to wheelchair-user standards?
AGE1,What is buyer 1's age?
SEX1,Which of these best describes buyer 1's gender identity?
ETHNICGROUP1,What is buyer 1's ethnic group?
ETHNIC,Which of the following best describes buyer 1's ethnic background?
NATIONALITYALL1,What is buyer 1's nationality?
ECSTAT1,Which of these best describes buyer 1's working situation?
LIVEINBUYER1,Will buyer 1 live in the property?
RELAT2,What is buyer 2 or person 2's relationship to buyer 1?
AGE2,What is buyer 2 or person 2's age?
SEX2,Which of these best describes buyer 2 or person 2's gender identity?
ETHNICGROUP2,What is buyer 2's ethnic group?
ETHNIC2,Which of the following best describes buyer 2's ethnic background?
NATIONALITYALL2,What is buyer 2's nationality?
ECSTAT2,What is buyer 2 or person 2's working situation?
LIVEINBUYER2,Will buyer 2 live in the property?
HHTYPE,Besides the buyer(s), how many other people live or will live in the property?
RELAT3,What is person 3's relationship to buyer 1?
AGE3,What is person 3's age?
SEX3,What is person 3's gender identity?
ECSTAT3,What is person 3's working situation?
RELAT4,What is person 4's relationship to buyer 1?
AGE4,What is person 4's age?
SEX4,What is person 4's gender identity?
ECSTAT4,What is person 4's working situation?
RELAT5,What is person 5's relationship to buyer 1?
AGE5,What is person 5's age?
SEX5,What is person 5's gender identity?
ECSTAT5,What is person 5's working situation?
RELAT6,What is person 6's relationship to buyer 1?
AGE6,What is person 6's age?
SEX6,What is person 6's gender identity?
ECSTAT6,What is person 6's working situation?
PREVTEN,What was buyer 1's previous tenure?
PPCODENK,Do you know the postcode of buyer 1's last settled accommodation?
PPOSTC1,Part 1 of postcode of buyer 1's last settled accommodation
PPOSTC2,Part 2 of postcode of buyer 1's last settled accommodation
PREVIOUSLAKNOWN,Do you know the local authority of buyer 1's last settled accommodation?
PREVLOC,The local authority code of buyer 1's last settled accommodation
PREVLOCNAME,The local authority name of buyer 1's last settled accommodation
PREGYRHA,Was the buyer registered with their PRP (HA)?
PREGOTHER,Was the buyer registered with another PRP (HA)?
PREGLA,Was the buyer registered with the local authority?
PREGGHB,Was the buyer registered with a Help to Buy agent?
PREGBLANK,Populated if pregyrha, pregother, pregla and pregghb are blank
BUY2LIVING,At the time of purchase, was buyer 2 living at the same address as buyer 1?
PREVTEN2,What was buyer 2's previous tenure?
HHREGRES,Have any of the buyers ever served as a regular in the UK armed forces?
HHREGRESSTILL,Is the buyer still serving in the UK armed forces?
ARMEDFORCESSPOUSE,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
DISABLED,Does anyone in the household consider themselves to have a disability?
WHEEL,Does anyone in the household use a wheelchair?
INC1NK,Is buyer 1's annual income known?
INCOME1,What is buyer 1's annual income?
INC1MORT,Was buyer 1's income used for a mortgage application?
INC2NK,Is buyer 1's annual income known?
INCOME2,What is buyer 2's annual income?
INC2MORT,Was buyer 2's income used for a mortgage application?
HB,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
SAVINGSNK,Is the the total amount the buyers had in savings known?
SAVINGS,What is the total amount the buyers had in savings before they paid any deposit for the property?
PREVOWN,Have any of the buyers previously owned a property?
PREVSHARED,Was the previous property under shared ownership?
PROPLEN,How long did the buyer(s) live in the property before purchasing it?
STAIRCASE,Is this a staircasing transaction?
STAIRBOUGHT,What percentage of the property has been bought in this staircasing transaction?
STAIROWNED,What percentage of the property do the buyers now own in total?
STAIRCASETOSALE,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
RESALE,Is this a resale?
EXDAY,Day of the exchange of contracts
EXMONTH,Month of the exchange of contracts
EXYEAR,Year of the exchange of contracts
HODAY,Day of the practical completion or handover date
HOMONTH,Month of the practical completion or handover date
HOYEAR,Year of the practical completion or handover date
LANOMAGR,Was the household rehoused under a local authority nominations agreement?
SOCTEN,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
FROMBEDS,How many bedrooms did the buyer's previous property have?
FROMPROP,What was the previous property type?
SOCPREVTEN,What was the rent type of buyer's previous tenure?
VALUE,What is the full purchase price?
VALUE_VALUE_CHECK,Populated if a soft validation is confirmed.
EQUITY,What was the initial percentage equity stake purchased?
MORTGAGEUSED,Was a mortgage used to buy this property?
MORTGAGE,What is the mortgage amount?
MORTGAGELENDER,What is the name of the mortgage lender?
MORTGAGELENDEROTHER,If mortgagelender = 'Other', what is the name of the mortgage lender?
MORTLEN1,What is the length of the mortgage in years?
EXTRABOR,Does this include any extra borrowing?
DEPOSIT,How much was the cash deposit paid on the property?
CASHDIS,How much cash discount was given through Social Homebuy?
MRENT,What is the basic monthly rent?
HASMSCHARGE,Does the property have any monthly leasehold charges?
MSCHARGE,What are the total monthly leasehold charges for the property?
MSCHARGE_VALUE_CHECK,Populated if a soft validation is confirmed.
DISCOUNT,What was the percentage discount?
GRANT,What was the amount of any loan, grant, discount or subsidy given?
id,Log ID
status,Status of log
duplicate_set_id,ID of a set of duplicate logs
created_at,Time and date the log was created
updated_at,Time and date the log was last updated
old_form_id,The ID on the old service
collection_start_year,Year collection period opened
creation_method,Was the log submitted in-service or via bulk upload?
is_dpo,Is the user in the assigned_to column the data protection officer?
owning_organisation_name,Which organisation owned this property before the sale?
managing_organisation_name,Which organisation reported the sale?
assigned_to,User the log is assigned to
day,Day of sale completion date
month,Month of sale completion date
year,Year of sale completion date
purchid,What is the purchaser code?
ownershipsch,Was this purchase made through an ownership scheme?
type,What is the type of shared ownership/discounted ownership/outright sale?
othtype,If type = 'Other', what is the type of outright sale?
companybuy,Is the buyer a company?
buylivein,Will the buyer(s) live in the property?
jointpur,Is this a joint purchase?
jointmore,Are there more than 2 joint buyers of this property?
beds,How many bedrooms does the property have?
proptype,What type of unit is the property?
builtype,Which type of building is the property?
uprn,What is the UPRN of the property?
uprn_confirmed,We found an address that might be this property. Is this the property address?
address_line1_input,Address line 1 input from address matching feature
postcode_full_input,Postcode input from address matching feature
uprn_selection,UPRN of the address selected
address_line1,Address line 1
address_line2,Address line 2
town_or_city,Town/City
county,County
pcode1,Part 1 of the property's postcode
pcode2,Part 2 of the property's postcode
la,LA code
la_label,LA name
wchair,Is the property built or adapted to wheelchair-user standards?
noint,Did you interview the buyer to answer these questions?
privacynotice,Has the buyer seen the MHCLG privacy notice?
age1,What is buyer 1's age?
sex1,Which of these best describes buyer 1's gender identity?
ethnic_group,What is buyer 1's ethnic group?
ethnic,Which of the following best describes buyer 1's ethnic background?
nationality_all,What is buyer 1's nationality?
ecstat1,Which of these best describes buyer 1's working situation?
buy1livein,Will buyer 1 live in the property?
relat2,What is buyer 2 or person 2's relationship to buyer 1?
age2,What is buyer 2 or person 2's age?
sex2,Which of these best describes buyer 2 or person 2's gender identity?
ethnic_group2,What is buyer 2's ethnic group?
ethnicbuy2,Which of the following best describes buyer 2's ethnic background?
nationality_all_buyer2,What is buyer 2's nationality?
ecstat2,What is buyer 2 or person 2's working situation?
buy2livein,Will buyer 2 live in the property?
hholdcount,Besides the buyer(s), how many other people live or will live in the property?
relat3,What is person 3's relationship to buyer 1?
age3,What is person 3's age?
sex3,What is person 3's gender identity?
ecstat3,What is person 3's working situation?
relat4,What is person 4's relationship to buyer 1?
age4,What is person 4's age?
sex4,What is person 4's gender identity?
ecstat4,What is person 4's working situation?
relat5,What is person 5's relationship to buyer 1?
age5,What is person 5's age?
sex5,What is person 5's gender identity?
ecstat5,What is person 5's working situation?
relat6,What is person 6's relationship to buyer 1?
age6,What is person 6's age?
sex6,What is person 6's gender identity?
ecstat6,What is person 6's working situation?
prevten,What was buyer 1's previous tenure?
ppcodenk,Do you know the postcode of buyer 1's last settled accommodation?
ppostc1,Part 1 of postcode of buyer 1's last settled accommodation
ppostc2,Part 2 of postcode of buyer 1's last settled accommodation
previous_la_known,Do you know the local authority of buyer 1's last settled accommodation?
prevloc,The local authority code of buyer 1's last settled accommodation
prevloc_label,The local authority name of buyer 1's last settled accommodation
pregyrha,Was the buyer registered with their PRP (HA)?
pregother,Was the buyer registered with another PRP (HA)?
pregla,Was the buyer registered with the local authority?
pregghb,Was the buyer registered with a Help to Buy agent?
pregblank,Populated if pregyrha, pregother, pregla and pregghb are blank
buy2living,At the time of purchase, was buyer 2 living at the same address as buyer 1?
prevtenbuy2,What was buyer 2's previous tenure?
hhregres,Have any of the buyers ever served as a regular in the UK armed forces?
hhregresstill,Is the buyer still serving in the UK armed forces?
armedforcesspouse,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?
disabled,Does anyone in the household consider themselves to have a disability?
wheel,Does anyone in the household use a wheelchair?
income1nk,Is buyer 1's annual income known?
income1,What is buyer 1's annual income?
inc1mort,Was buyer 1's income used for a mortgage application?
income2nk,Is buyer 2's annual income known?
income2,What is buyer 2's annual income?
inc2mort,Was buyer 2's income used for a mortgage application?
hb,Were the buyers receiving any of these housing-related benefits immediately before buying this property?
savingsnk,Is the the total amount the buyers had in savings known?
savings,What is the total amount the buyers had in savings before they paid any deposit for the property?
prevown,Have any of the buyers previously owned a property?
prevshared,Was the previous property under shared ownership?
proplen,How long did the buyer(s) live in the property before purchasing it?
staircase,Is this a staircasing transaction?
stairbought,What percentage of the property has been bought in this staircasing transaction?
stairowned,What percentage of the property do the buyers now own in total?
staircasesale,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?
resale,Is this a resale?
exday,Day of the exchange of contracts
exmonth,Month of the exchange of contracts
exyear,Year of the exchange of contracts
hoday,Day of the practical completion or handover date
homonth,Month of the practical completion or handover date
hoyear,Year of the practical completion or handover date
lanomagr,Was the household rehoused under a local authority nominations agreement?
soctenant,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?
frombeds,How many bedrooms did the buyer's previous property have?
fromprop,What was the previous property type?
socprevten,What was the rent type of buyer's previous tenure?
value,What is the full purchase price?
equity,What was the initial percentage equity stake purchased?
mortgageused,Was a mortgage used to buy this property?
mortgage,What is the mortgage amount?
mortgagelender,What is the name of the mortgage lender?
mortgagelenderother,If mortgagelender = 'Other', what is the name of the mortgage lender?
mortlen,What is the length of the mortgage in years?
extrabor,Does this include any extra borrowing?
deposit,How much was the cash deposit paid on the property?
cashdis,How much cash discount was given through Social Homebuy?
mrent,What is the basic monthly rent?
has_mscharge,Does the property have any monthly leasehold charges?
mscharge,What are the total monthly leasehold charges for the property?
discount,What was the percentage discount?
grant,What was the amount of any loan, grant, discount or subsidy given?
Can't render this file because it has a wrong number of fields in line 20.

4
spec/helpers/filters_helper_spec.rb

@ -168,7 +168,7 @@ RSpec.describe FiltersHelper do
before do before do
FactoryBot.create(:organisation_relationship, parent_organisation:, child_organisation:) FactoryBot.create(:organisation_relationship, parent_organisation:, child_organisation:)
FactoryBot.create(:organisation, name: "Other organisation", id: 99) FactoryBot.create(:organisation, name: "Other organisation", id: 9_999_999)
user.organisation.reload user.organisation.reload
end end
@ -326,7 +326,7 @@ RSpec.describe FiltersHelper do
before do before do
FactoryBot.create(:organisation_relationship, parent_organisation:, child_organisation:) FactoryBot.create(:organisation_relationship, parent_organisation:, child_organisation:)
FactoryBot.create(:organisation, name: "Other organisation", id: 99) FactoryBot.create(:organisation, name: "Other organisation", id: 9_999_999)
user.organisation.reload user.organisation.reload
end end

18
spec/helpers/form_page_error_helper_spec.rb

@ -21,4 +21,22 @@ RSpec.describe FormPageErrorHelper do
end end
end end
end end
describe "#remove_duplicate_page_errors" do
context "when non base other questions are removed" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :in_progress) }
before do
lettings_log.errors.add :layear, "error"
lettings_log.errors.add :period, "error_one"
lettings_log.errors.add :base, "error_one"
end
it "returns details and user tabs" do
remove_duplicate_page_errors(lettings_log)
expect(lettings_log.errors.count).to eq(2)
expect(lettings_log.errors.map(&:message)).to match_array(%w[error_one error])
end
end
end
end end

36
spec/lib/tasks/clear_unconfirmed_emails_spec.rb

@ -0,0 +1,36 @@
require "rails_helper"
require "rake"
RSpec.describe "clear_unconfirmed_emails" do
describe ":clear_unconfirmed_emails", type: :task do
subject(:task) { Rake::Task["clear_unconfirmed_emails"] }
before do
Rake.application.rake_require("tasks/clear_unconfirmed_emails")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
context "and there are deactivated users with unconfirmed emails" do
let!(:user) { create(:user, active: false, unconfirmed_email: "some_email@example.com") }
it "clears unconfirmed_email" do
task.invoke
expect(user.reload.unconfirmed_email).to eq(nil)
end
end
context "and there are active users with unconfirmed emails" do
let!(:user) { create(:user, active: true, unconfirmed_email: "some_email@example.com") }
it "does not clear unconfirmed_email" do
task.invoke
expect(user.reload.unconfirmed_email).not_to eq(nil)
end
end
end
end
end

41
spec/lib/tasks/log_variable_definitions_spec.rb

@ -0,0 +1,41 @@
require "rails_helper"
require "rake"
RSpec.describe "log_variable_definitions" do
describe ":add_variable_definitions", type: :task do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
let(:path) { "spec/fixtures/variable_definitions" }
before do
Rake.application.rake_require("tasks/log_variable_definitions")
Rake::Task.define_task(:environment)
task.reenable
end
it "adds CsvVariableDefinition records from each file in the specified directory" do
expect { task.invoke(path) }.to change(CsvVariableDefinition, :count).by(416)
end
it "handles an empty directory without errors" do
empty_path = "spec/fixtures/empty_directory"
FileUtils.mkdir_p(empty_path)
expect { task.invoke(empty_path) }.not_to raise_error
expect(CsvVariableDefinition.count).to eq(0)
end
it "does not create duplicate records if run multiple times" do
CsvVariableDefinition.delete_all
initial_count = CsvVariableDefinition.count
task.invoke(path)
first_run_count = CsvVariableDefinition.count
task.invoke(path)
second_run_count = CsvVariableDefinition.count
expect(first_run_count).to eq(initial_count + 416)
expect(second_run_count).to eq(first_run_count)
end
end
end

2
spec/mailers/resend_invitation_mailer_spec.rb

@ -42,7 +42,7 @@ RSpec.describe ResendInvitationMailer do
it "sends an initial invitation" do it "sends an initial invitation" do
FactoryBot.create(:legacy_user, old_user_id: new_active_migrated_user.old_user_id, user: new_active_migrated_user) FactoryBot.create(:legacy_user, old_user_id: new_active_migrated_user.old_user_id, user: new_active_migrated_user)
expect(notify_client).to receive(:send_email).with(email_address: "new_active_migrated_user@example.com", template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation:).once expect(notify_client).to receive(:send_email).with(email_address: "new_active_migrated_user@example.com", template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation:).once
described_class.new.resend_invitation_email(new_active_migrated_user) described_class.new.resend_invitation_email(new_active_migrated_user)
end end
end end

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

@ -338,7 +338,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
end end
describe "#validate_equity_in_range_for_year_and_type" do describe "#validate_equity_in_range_for_year_and_type" do
let(:record) { FactoryBot.build(:sales_log, saledate:) } let(:record) { FactoryBot.build(:sales_log, saledate:, resale: nil) }
context "with a log in the 22/23 collection year" do context "with a log in the 22/23 collection year" do
let(:saledate) { Time.zone.local(2023, 1, 1) } let(:saledate) { Time.zone.local(2023, 1, 1) }
@ -373,6 +373,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
end end
it "does not add an error if it's a resale" do
record.type = 2
record.equity = 90
record.resale = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors).to be_empty
end
end end
context "with a log in 23/24 collection year" do context "with a log in 23/24 collection year" do

311
spec/requests/form_controller_spec.rb

@ -763,39 +763,162 @@ RSpec.describe FormController, type: :request do
} }
end end
before do context "when the log will not be a duplicate" do
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params: before do
end post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "re-renders the same page with errors if validation fails" do it "re-renders the same page with errors if validation fails" do
expect(response).to have_http_status(:redirect) expect(response).to have_http_status(:redirect)
end end
it "only updates answers that apply to the page being submitted" do it "only updates answers that apply to the page being submitted" do
lettings_log.reload lettings_log.reload
expect(lettings_log.age1).to eq(answer) expect(lettings_log.age1).to eq(answer)
expect(lettings_log.age2).to be nil expect(lettings_log.age2).to be nil
end
it "tracks who updated the record" do
lettings_log.reload
whodunnit_actor = lettings_log.versions.last.actor
expect(whodunnit_actor).to be_a(User)
expect(whodunnit_actor.id).to eq(user.id)
end
end end
it "tracks who updated the record" do context "when the answer makes the log a duplicate" do
lettings_log.reload context "with one other log" do
whodunnit_actor = lettings_log.versions.last.actor let(:new_duplicate) { create(:lettings_log) }
expect(whodunnit_actor).to be_a(User)
expect(whodunnit_actor.id).to eq(user.id) before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.where(id: new_duplicate.id))
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "sets a new duplicate set id on both logs" do
lettings_log.reload
new_duplicate.reload
expect(lettings_log.duplicate_set_id).not_to be_nil
expect(lettings_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
it "redirects to the duplicate logs page" do
expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}")
follow_redirect!
expect(page).to have_content("These logs are duplicates")
end
end
context "with a set of other logs" do
let(:duplicate_set_id) { 100 }
let(:new_duplicates) { create_list(:lettings_log, 2, duplicate_set_id:) }
before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.where(id: new_duplicates.pluck(:id)))
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "sets the logs duplicate set id to that of the set it is now part of" do
lettings_log.reload
expect(lettings_log.duplicate_set_id).to eql(duplicate_set_id)
new_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(duplicate_set_id)
end
end
it "redirects to the duplicate logs page" do
expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}")
follow_redirect!
expect(page).to have_content("These logs are duplicates")
end
end
context "when the log was previously in a different duplicate set" do
context "with a single other log" do
let(:old_duplicate_set_id) { 110 }
let!(:old_duplicate) { create(:lettings_log, duplicate_set_id: old_duplicate_set_id) }
let(:lettings_log) { create(:lettings_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
let(:new_duplicate) { create(:lettings_log) }
before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.where(id: new_duplicate.id))
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
lettings_log.reload
old_duplicate.reload
new_duplicate.reload
expect(old_duplicate.duplicate_set_id).to be_nil
expect(lettings_log.duplicate_set_id).not_to be_nil
expect(lettings_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
end
context "with multiple other logs" do
let(:old_duplicate_set_id) { 120 }
let!(:old_duplicates) { create_list(:lettings_log, 2, duplicate_set_id: old_duplicate_set_id) }
let(:lettings_log) { create(:lettings_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
let(:new_duplicate) { create(:lettings_log) }
before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.where(id: new_duplicate.id))
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
lettings_log.reload
new_duplicate.reload
old_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(old_duplicate_set_id)
end
expect(lettings_log.duplicate_set_id).not_to be_nil
expect(lettings_log.duplicate_set_id).not_to eql(old_duplicate_set_id)
expect(lettings_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
end
end
end end
context "and duplicate logs" do context "when the answer makes the log stop being a duplicate" do
let(:duplicate_logs) { create_list(:lettings_log, 2) } context "when the log had one duplicate" do
let(:old_duplicate_set_id) { 130 }
let!(:old_duplicate) { create(:lettings_log, duplicate_set_id: old_duplicate_set_id) }
let(:lettings_log) { create(:lettings_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
before do before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(duplicate_logs) allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.none)
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params: post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
lettings_log.reload
old_duplicate.reload
expect(old_duplicate.duplicate_set_id).to be_nil
expect(lettings_log.duplicate_set_id).to be_nil
end
end end
it "redirects to the duplicate logs page" do context "when the log had multiple duplicates" do
expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}") let(:old_duplicate_set_id) { 140 }
follow_redirect! let!(:old_duplicates) { create_list(:lettings_log, 2, duplicate_set_id: old_duplicate_set_id) }
expect(page).to have_content("These logs are duplicates") let(:lettings_log) { create(:lettings_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
before do
allow(LettingsLog).to receive(:duplicate_logs).and_return(LettingsLog.none)
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
lettings_log.reload
old_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(old_duplicate_set_id)
end
expect(lettings_log.duplicate_set_id).to be_nil
end
end end
end end
end end
@ -816,19 +939,141 @@ RSpec.describe FormController, type: :request do
}, },
} }
end end
let(:page_id) { "buyer_1_age" }
context "and duplicate logs" do context "when the answer makes the log a duplicate" do
let!(:duplicate_logs) { create_list(:sales_log, 2) } context "with one other log" do
let(:new_duplicate) { create(:sales_log) }
before do before do
allow(SalesLog).to receive(:duplicate_logs).and_return(duplicate_logs) allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.where(id: new_duplicate.id))
post "/sales-logs/#{sales_log.id}/buyer-1-age", params: post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "sets a new duplicate set id on both logs" do
sales_log.reload
new_duplicate.reload
expect(sales_log.duplicate_set_id).not_to be_nil
expect(sales_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
it "redirects to the duplicate logs page" do
expect(response).to redirect_to("/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}")
follow_redirect!
expect(page).to have_content("These logs are duplicates")
end
end end
it "redirects to the duplicate logs page" do context "with a set of other logs" do
expect(response).to redirect_to("/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}") let(:duplicate_set_id) { 100 }
follow_redirect! let(:new_duplicates) { create_list(:sales_log, 2, duplicate_set_id:) }
expect(page).to have_content("These logs are duplicates")
before do
allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.where(id: new_duplicates.pluck(:id)))
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "sets the logs duplicate set id to that of the set it is now part of" do
sales_log.reload
expect(sales_log.duplicate_set_id).to eql(duplicate_set_id)
new_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(duplicate_set_id)
end
end
it "redirects to the duplicate logs page" do
expect(response).to redirect_to("/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}")
follow_redirect!
expect(page).to have_content("These logs are duplicates")
end
end
context "when the log was previously in a different duplicate set" do
context "with a single other log" do
let(:old_duplicate_set_id) { 110 }
let!(:old_duplicate) { create(:sales_log, duplicate_set_id: old_duplicate_set_id) }
let(:sales_log) { create(:sales_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
let(:new_duplicate) { create(:sales_log) }
before do
allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.where(id: new_duplicate.id))
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
sales_log.reload
old_duplicate.reload
new_duplicate.reload
expect(old_duplicate.duplicate_set_id).to be_nil
expect(sales_log.duplicate_set_id).not_to be_nil
expect(sales_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
end
context "with multiple other logs" do
let(:old_duplicate_set_id) { 120 }
let!(:old_duplicates) { create_list(:sales_log, 2, duplicate_set_id: old_duplicate_set_id) }
let(:sales_log) { create(:sales_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
let(:new_duplicate) { create(:sales_log) }
before do
allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.where(id: new_duplicate.id))
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
sales_log.reload
new_duplicate.reload
old_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(old_duplicate_set_id)
end
expect(sales_log.duplicate_set_id).not_to be_nil
expect(sales_log.duplicate_set_id).not_to eql(old_duplicate_set_id)
expect(sales_log.duplicate_set_id).to eql(new_duplicate.duplicate_set_id)
end
end
end
end
context "when the answer makes the log stop being a duplicate" do
context "when the log had one duplicate" do
let(:old_duplicate_set_id) { 130 }
let!(:old_duplicate) { create(:sales_log, duplicate_set_id: old_duplicate_set_id) }
let(:sales_log) { create(:sales_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
before do
allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.none)
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
sales_log.reload
old_duplicate.reload
expect(old_duplicate.duplicate_set_id).to be_nil
expect(sales_log.duplicate_set_id).to be_nil
end
end
context "when the log had multiple duplicates" do
let(:old_duplicate_set_id) { 140 }
let!(:old_duplicates) { create_list(:sales_log, 2, duplicate_set_id: old_duplicate_set_id) }
let(:sales_log) { create(:sales_log, assigned_to: user, duplicate_set_id: old_duplicate_set_id) }
before do
allow(SalesLog).to receive(:duplicate_logs).and_return(SalesLog.none)
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params:
end
it "updates the relevant duplicate set ids" do
sales_log.reload
old_duplicates.each do |log|
log.reload
expect(log.duplicate_set_id).to eql(old_duplicate_set_id)
end
expect(sales_log.duplicate_set_id).to be_nil
end
end end
end end
end end

2
spec/requests/organisations_controller_spec.rb

@ -1688,7 +1688,7 @@ RSpec.describe OrganisationsController, type: :request do
end end
it "sends invitation emails" do it "sends invitation emails" do
expect(notify_client).to have_received(:send_email).with(email_address: user_to_reactivate.email, template_id: User::BETA_ONBOARDING_TEMPLATE_ID, personalisation: expected_personalisation).once expect(notify_client).to have_received(:send_email).with(email_address: user_to_reactivate.email, template_id: User::CONFIRMABLE_TEMPLATE_ID, personalisation: expected_personalisation).once
end end
end end
end end

32
spec/requests/users_controller_spec.rb

@ -434,7 +434,7 @@ RSpec.describe UsersController, type: :request do
context "when user is signed in as a data coordinator" do context "when user is signed in as a data coordinator" do
let(:user) { create(:user, :data_coordinator, email: "coordinator@example.com", organisation: create(:organisation, :without_dpc)) } let(:user) { create(:user, :data_coordinator, email: "coordinator@example.com", organisation: create(:organisation, :without_dpc)) }
let!(:other_user) { create(:user, organisation: user.organisation, name: "filter name", email: "filter@example.com") } let!(:other_user) { create(:user, organisation: user.organisation, name: "filter name", email: "filter@example.com", unconfirmed_email: "email@something.com") }
before do before do
sign_in user sign_in user
@ -885,6 +885,11 @@ RSpec.describe UsersController, type: :request do
expect { patch "/users/#{other_user.id}", headers:, params: } expect { patch "/users/#{other_user.id}", headers:, params: }
.to change { other_user.reload.active }.from(true).to(false) .to change { other_user.reload.active }.from(true).to(false)
end end
it "discards unconfirmed email" do
expect { patch "/users/#{other_user.id}", headers:, params: }
.to change { other_user.reload.unconfirmed_email }.from("email@something.com").to(nil)
end
end end
context "and tries to activate deactivated user" do context "and tries to activate deactivated user" do
@ -997,6 +1002,7 @@ RSpec.describe UsersController, type: :request do
email: "new_user@example.com", email: "new_user@example.com",
role: "data_coordinator", role: "data_coordinator",
phone: "12345678910", phone: "12345678910",
phone_extension: "1234",
}, },
} }
end end
@ -1020,12 +1026,14 @@ RSpec.describe UsersController, type: :request do
request request
end end
it "creates a new scheme for user organisation with valid params" do it "creates a new user for user organisation with valid params" do
request request
expect(User.last.name).to eq("new user") expect(User.last.name).to eq("new user")
expect(User.last.email).to eq("new_user@example.com") expect(User.last.email).to eq("new_user@example.com")
expect(User.last.role).to eq("data_coordinator") expect(User.last.role).to eq("data_coordinator")
expect(User.last.phone).to eq("12345678910")
expect(User.last.phone_extension).to eq("1234")
end end
it "redirects back to organisation users page" do it "redirects back to organisation users page" do
@ -1612,11 +1620,12 @@ RSpec.describe UsersController, type: :request do
expect(page).to have_content("Change your personal details") expect(page).to have_content("Change your personal details")
end end
it "has fields for name, email, role, dpo and key contact" do it "has fields for name, email, role, phone number and phone extension" do
expect(page).to have_field("user[name]") expect(page).to have_field("user[name]")
expect(page).to have_field("user[email]") expect(page).to have_field("user[email]")
expect(page).to have_field("user[role]") expect(page).to have_field("user[role]")
expect(page).to have_field("user[phone]") expect(page).to have_field("user[phone]")
expect(page).to have_field("user[phone_extension]")
end end
it "allows setting the role to `support`" do it "allows setting the role to `support`" do
@ -1638,10 +1647,12 @@ RSpec.describe UsersController, type: :request do
expect(page).to have_content("Change #{other_user.name}’s personal details") expect(page).to have_content("Change #{other_user.name}’s personal details")
end end
it "has fields for name, email, role, dpo and key contact" do it "has fields for name, email, role, phone number and phone extension" do
expect(page).to have_field("user[name]") expect(page).to have_field("user[name]")
expect(page).to have_field("user[email]") expect(page).to have_field("user[email]")
expect(page).to have_field("user[role]") expect(page).to have_field("user[role]")
expect(page).to have_field("user[phone]")
expect(page).to have_field("user[phone_extension]")
end end
end end
@ -1656,10 +1667,12 @@ RSpec.describe UsersController, type: :request do
expect(page).to have_content("Change #{other_user.name}’s personal details") expect(page).to have_content("Change #{other_user.name}’s personal details")
end end
it "has fields for name, email, role, dpo and key contact" do it "has fields for name, email, role, phone number and phone extension" do
expect(page).to have_field("user[name]") expect(page).to have_field("user[name]")
expect(page).to have_field("user[email]") expect(page).to have_field("user[email]")
expect(page).to have_field("user[role]") expect(page).to have_field("user[role]")
expect(page).to have_field("user[phone]")
expect(page).to have_field("user[phone_extension]")
end end
end end
@ -1989,6 +2002,7 @@ RSpec.describe UsersController, type: :request do
email:, email:,
role: "data_coordinator", role: "data_coordinator",
phone: "12345612456", phone: "12345612456",
phone_extension: "1234",
organisation_id: organisation.id, organisation_id: organisation.id,
}, },
} }
@ -2004,6 +2018,14 @@ RSpec.describe UsersController, type: :request do
expect(User.find_by(email:).organisation).to eq(organisation) expect(User.find_by(email:).organisation).to eq(organisation)
end end
it "sets expected values on the user" do
request
user = User.find_by(email:)
expect(user.name).to eq("new user")
expect(user.phone).to eq("12345612456")
expect(user.phone_extension).to eq("1234")
end
it "redirects back to users page" do it "redirects back to users page" do
request request
expect(response).to redirect_to("/users") expect(response).to redirect_to("/users")

120
spec/services/csv/lettings_log_csv_service_spec.rb

@ -1,6 +1,16 @@
require "rails_helper" require "rails_helper"
require "rake"
RSpec.describe Csv::LettingsLogCsvService do RSpec.describe Csv::LettingsLogCsvService do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
before do
Rake.application.rake_require("tasks/log_variable_definitions")
Rake::Task.define_task(:environment)
task.reenable
task.invoke("spec/fixtures/variable_definitions")
end
context "when downloading a csv" do context "when downloading a csv" do
let(:log) { create(:lettings_log) } let(:log) { create(:lettings_log) }
let(:user) { create(:user, :support, email: "s.port@jeemayle.com") } let(:user) { create(:user, :support, email: "s.port@jeemayle.com") }
@ -9,23 +19,29 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:year) { 2024 } let(:year) { 2024 }
let(:csv) { CSV.parse(service.prepare_csv(LettingsLog.where(id: logs.map(&:id)))) } let(:csv) { CSV.parse(service.prepare_csv(LettingsLog.where(id: logs.map(&:id)))) }
let(:logs) { [log] } let(:logs) { [log] }
let(:headers) { csv.first } let(:definition_line) { csv.first }
let(:attribute_line) { csv.second }
let(:content_line) { csv.third }
it "returns a string" do it "returns a string" do
result = service.prepare_csv(LettingsLog.all) result = service.prepare_csv(LettingsLog.all)
expect(result).to be_a String expect(result).to be_a String
end end
it "returns a csv with headers" do it "returns a csv with definition headers on the first line" do
expect(csv.first.first).to eq "id" expect(definition_line.first).to eq "Log ID"
end
it "returns a csv with attribute headers on the second line" do
expect(attribute_line.first).to eq "id"
end end
context "when stubbing :ordered_questions_for_year" do context "when stubbing :ordered_questions_for_year" do
let(:form_handler_mock) { instance_double(FormHandler) } let(:form_handler_mock) { instance_double(FormHandler) }
let(:lettings_form) do let(:lettings_form) do
FormFactory.new(year: 2050, type: "lettings") FormFactory.new(year: 2050, type: "lettings")
.with_sections([build(:section, :with_questions, question_ids:, questions:)]) .with_sections([build(:section, :with_questions, question_ids:, questions:)])
.build .build
end end
let(:question_ids) { [] } let(:question_ids) { [] }
let(:questions) { nil } let(:questions) { nil }
@ -50,13 +66,13 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:question_ids) { %w[prevten startdate brent rent_type] } let(:question_ids) { %w[prevten startdate brent rent_type] }
it "includes log attributes related to questions to the headers" do it "includes log attributes related to questions to the headers" do
expect(headers).to include(*question_ids.first(3)) expect(attribute_line).to include(*question_ids.first(3))
end end
it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do
expect(headers).not_to include "rent_type" expect(attribute_line).not_to include "rent_type"
expect(headers).to include(*%w[wrent renttype renttype_detail]) expect(attribute_line).to include(*%w[wrent renttype renttype_detail])
expect(headers).not_to include("rent_type_detail") expect(attribute_line).not_to include("rent_type_detail")
end end
end end
@ -70,23 +86,23 @@ RSpec.describe Csv::LettingsLogCsvService do
it "does not add the id of the checkbox question to the headers" do it "does not add the id of the checkbox question to the headers" do
question_ids = questions.map(&:id) question_ids = questions.map(&:id)
expect(headers).not_to include(*question_ids) expect(attribute_line).not_to include(*question_ids)
end end
it "adds the related log attributes from the answer options to the headers" do it "adds the related log attributes from the answer options to the headers" do
log_attributes = questions.flat_map { |q| q.answer_options.keys } log_attributes = questions.flat_map { |q| q.answer_options.keys }
expect(headers).to include(*log_attributes) expect(attribute_line).to include(*log_attributes)
end end
end end
end end
it "adds log attributes not related to questions to the headers" do it "adds log attributes not related to questions to the headers" do
expect(headers.first(5)).to eq %w[id status duplicate_set_id created_by assigned_to] expect(attribute_line.first(5)).to eq %w[id status duplicate_set_id created_by assigned_to]
end end
it "adds attributes related to associated schemes and locations to the headers" do it "adds attributes related to associated schemes and locations to the headers" do
expect(headers).to include(*%w[scheme_service_name scheme_confidential SCHTYPE scheme_registered_under_care_act]) expect(attribute_line).to include(*%w[scheme_service_name scheme_confidential SCHTYPE scheme_registered_under_care_act])
expect(headers.last(5)).to eq %w[location_units location_type_of_unit location_mobility_type location_local_authority location_startdate] expect(attribute_line.last(5)).to eq %w[location_units location_type_of_unit location_mobility_type location_local_authority location_startdate]
end end
context "when there are many logs" do context "when there are many logs" do
@ -94,7 +110,7 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:log_count) { 30 } let(:log_count) { 30 }
it "creates a CSV with the correct number of logs" do it "creates a CSV with the correct number of logs" do
expected_row_count_with_headers = log_count + 1 expected_row_count_with_headers = log_count + 2
expect(csv.size).to be expected_row_count_with_headers expect(csv.size).to be expected_row_count_with_headers
end end
end end
@ -104,32 +120,32 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) } let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) }
it "gives answer to radio questions as labels" do it "gives answer to radio questions as labels" do
relat2_column_index = csv.first.index("relat2") relat2_column_index = attribute_line.index("relat2")
relat2_value = csv.second[relat2_column_index] relat2_value = content_line[relat2_column_index]
expect(relat2_value).to eq "Partner" expect(relat2_value).to eq "Partner"
end end
it "gives answers to free input questions as the user input" do it "gives answers to free input questions as the user input" do
age1_column_index = csv.first.index("age1") age1_column_index = attribute_line.index("age1")
age1_value = csv.second[age1_column_index] age1_value = content_line[age1_column_index]
expect(age1_value).to eq 35.to_s expect(age1_value).to eq 35.to_s
end end
it "exports the code for the local authority under the heading 'la'" do it "exports the code for the local authority under the heading 'la'" do
la_column_index = csv.first.index("la") la_column_index = attribute_line.index("la")
la_value = csv.second[la_column_index] la_value = content_line[la_column_index]
expect(la_value).to eq "E09000003" expect(la_value).to eq "E09000003"
end end
it "exports the label for the local authority under the heading 'la_label'" do it "exports the label for the local authority under the heading 'la_label'" do
la_label_column_index = csv.first.index("la_label") la_label_column_index = attribute_line.index("la_label")
la_label_value = csv.second[la_label_column_index] la_label_value = content_line[la_label_column_index]
expect(la_label_value).to eq "Barnet" expect(la_label_value).to eq "Barnet"
end end
it "exports the id for under the heading 'duplicate_set_id'" do it "exports the id for under the heading 'duplicate_set_id'" do
duplicate_set_id_column_index = csv.first.index("duplicate_set_id") duplicate_set_id_column_index = attribute_line.index("duplicate_set_id")
duplicate_set_id_value = csv.second[duplicate_set_id_column_index] duplicate_set_id_value = content_line[duplicate_set_id_column_index]
expect(duplicate_set_id_value).to eq "12312" expect(duplicate_set_id_value).to eq "12312"
end end
end end
@ -139,32 +155,32 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) } let(:log) { create(:lettings_log, :setup_completed, hhmemb: 2, details_known_2: 0, relat2: "P", age1: 35, la: "E09000003", duplicate_set_id: 12_312) }
it "gives answer to radio questions as labels" do it "gives answer to radio questions as labels" do
relat2_column_index = csv.first.index("relat2") relat2_column_index = attribute_line.index("relat2")
relat2_value = csv.second[relat2_column_index] relat2_value = content_line[relat2_column_index]
expect(relat2_value).to eq "P" expect(relat2_value).to eq "P"
end end
it "gives answers to free input questions as the user input" do it "gives answers to free input questions as the user input" do
age1_column_index = csv.first.index("age1") age1_column_index = attribute_line.index("age1")
age1_value = csv.second[age1_column_index] age1_value = content_line[age1_column_index]
expect(age1_value).to eq 35.to_s expect(age1_value).to eq 35.to_s
end end
it "exports the code for the local authority under the heading 'la'" do it "exports the code for the local authority under the heading 'la'" do
la_column_index = csv.first.index("la") la_column_index = attribute_line.index("la")
la_value = csv.second[la_column_index] la_value = content_line[la_column_index]
expect(la_value).to eq "E09000003" expect(la_value).to eq "E09000003"
end end
it "exports the label for the local authority under the heading 'la_label'" do it "exports the label for the local authority under the heading 'la_label'" do
la_label_column_index = csv.first.index("la_label") la_label_column_index = attribute_line.index("la_label")
la_label_value = csv.second[la_label_column_index] la_label_value = content_line[la_label_column_index]
expect(la_label_value).to eq "Barnet" expect(la_label_value).to eq "Barnet"
end end
it "exports the duplicate log reference under the heading 'duplicate_set_id'" do it "exports the duplicate log reference under the heading 'duplicate_set_id'" do
duplicate_set_id_column_index = csv.first.index("duplicate_set_id") duplicate_set_id_column_index = attribute_line.index("duplicate_set_id")
duplicate_set_id_value = csv.second[duplicate_set_id_column_index] duplicate_set_id_value = content_line[duplicate_set_id_column_index]
expect(duplicate_set_id_value).to eq "12312" expect(duplicate_set_id_value).to eq "12312"
end end
end end
@ -173,7 +189,7 @@ RSpec.describe Csv::LettingsLogCsvService do
let(:user) { create(:user, :data_coordinator, email: "choreographer@owtluk.com") } let(:user) { create(:user, :data_coordinator, email: "choreographer@owtluk.com") }
it "does not include certain attributes in the headers" do it "does not include certain attributes in the headers" do
expect(headers).not_to include(*%w[wrent wscharge wpschrge wsupchrg wtcharge]) expect(attribute_line).not_to include(*%w[wrent wscharge wpschrge wsupchrg wtcharge])
end end
end end
@ -316,8 +332,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_24.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_24.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -330,8 +346,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -348,8 +364,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_24.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_24.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -362,8 +378,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_24.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_24.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -504,8 +520,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_23.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_23.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -518,8 +534,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -536,8 +552,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_23.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_23.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -550,8 +566,8 @@ RSpec.describe Csv::LettingsLogCsvService do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_23.csv") expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_23.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end

131
spec/services/csv/sales_log_csv_service_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Csv::SalesLogCsvService do RSpec.describe Csv::SalesLogCsvService do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
let(:form_handler_mock) { instance_double(FormHandler) } let(:form_handler_mock) { instance_double(FormHandler) }
let(:organisation) { create(:organisation) } let(:organisation) { create(:organisation) }
let(:fixed_time) { now } let(:fixed_time) { now }
@ -37,11 +39,18 @@ RSpec.describe Csv::SalesLogCsvService do
let(:service) { described_class.new(user:, export_type: "labels", year:) } let(:service) { described_class.new(user:, export_type: "labels", year:) }
let(:csv) { CSV.parse(service.prepare_csv(SalesLog.all)) } let(:csv) { CSV.parse(service.prepare_csv(SalesLog.all)) }
let(:year) { 2024 } let(:year) { 2024 }
let(:definition_line) { csv.first }
let(:attribute_line) { csv.second }
let(:content_line) { csv.third }
before do before do
Timecop.freeze(now) Timecop.freeze(now)
Singleton.__init__(FormHandler) Singleton.__init__(FormHandler)
log log
Rake.application.rake_require("tasks/log_variable_definitions")
Rake::Task.define_task(:environment)
task.reenable
task.invoke("spec/fixtures/variable_definitions")
end end
after do after do
@ -53,8 +62,12 @@ RSpec.describe Csv::SalesLogCsvService do
expect(result).to be_a String expect(result).to be_a String
end end
it "returns a csv with headers" do it "returns a csv with definition headers on first line" do
expect(csv.first.first).to eq "ID" expect(definition_line.first).to eq "Log ID"
end
it "returns a csv with attribute headers on second line" do
expect(attribute_line.first).to eq "ID"
end end
context "when stubbing :ordered_questions_for_year" do context "when stubbing :ordered_questions_for_year" do
@ -85,14 +98,14 @@ RSpec.describe Csv::SalesLogCsvService do
let(:question_ids) { %w[type age1 buy1livein exdate] } let(:question_ids) { %w[type age1 buy1livein exdate] }
it "includes log attributes related to questions to the headers" do it "includes log attributes related to questions to the headers" do
headers = csv.first attribute_line_before_2023 = csv.first
expect(headers).to include(*%w[TYPE AGE1 LIVEINBUYER1]) expect(attribute_line_before_2023).to include(*%w[TYPE AGE1 LIVEINBUYER1])
end end
it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do
headers = csv.first attribute_line_before_2023 = csv.first
expect(headers).not_to include "EXDATE" expect(attribute_line_before_2023).not_to include "EXDATE"
expect(headers.last(4)).to eq %w[LIVEINBUYER1 EXDAY EXMONTH EXYEAR] expect(attribute_line_before_2023.last(4)).to eq %w[LIVEINBUYER1 EXDAY EXMONTH EXYEAR]
end end
end end
@ -109,28 +122,27 @@ RSpec.describe Csv::SalesLogCsvService do
end end
it "does not add questions for checks, whether some other attribute is known or whether something else was asked" do it "does not add questions for checks, whether some other attribute is known or whether something else was asked" do
headers = csv.first attribute_line_before_2023 = csv.first
expect(headers).not_to include "attribute_value_check" expect(attribute_line_before_2023).not_to include "attribute_value_check"
expect(headers).not_to include "something_or_other_known" expect(attribute_line_before_2023).not_to include "something_or_other_known"
expect(headers).not_to include "whatchamacallit_asked" expect(attribute_line_before_2023).not_to include "whatchamacallit_asked"
end end
it "does not add the id of checkbox questions, but adds the related attributes of the log in the correct order" do it "does not add the id of checkbox questions, but adds the related attributes of the log in the correct order" do
headers = csv.first attribute_line_before_2023 = csv.first
expect(headers.last(4)).to eq %w[OWNERSHIP PREGYRHA PREGOTHER TYPE] expect(attribute_line_before_2023.last(4)).to eq %w[OWNERSHIP PREGYRHA PREGOTHER TYPE]
end end
end end
end end
it "includes attributes not related to questions to the headers" do it "includes attributes not related to questions to the headers" do
headers = csv.first expect(attribute_line).to include(*%w[ID STATUS CREATEDDATE UPLOADDATE])
expect(headers).to include(*%w[ID STATUS CREATEDDATE UPLOADDATE])
end end
it "returns a csv with the correct number of logs" do it "returns a csv with the correct number of logs" do
create_list(:sales_log, 15) create_list(:sales_log, 15)
log_count = SalesLog.count log_count = SalesLog.count
expected_row_count_with_headers = log_count + 1 expected_row_count_with_headers = log_count + 2
expect(csv.size).to be expected_row_count_with_headers expect(csv.size).to be expected_row_count_with_headers
end end
@ -140,36 +152,36 @@ RSpec.describe Csv::SalesLogCsvService do
let(:now) { fixed_time } let(:now) { fixed_time }
it "gives answers to radio questions as their labels" do it "gives answers to radio questions as their labels" do
national_column_index = csv.first.index("NATIONAL") national_column_index = attribute_line.index("NATIONAL")
national_value = csv.second[national_column_index] national_value = content_line[national_column_index]
expect(national_value).to eq "United Kingdom" expect(national_value).to eq "United Kingdom"
relat2_column_index = csv.first.index("RELAT2") relat2_column_index = attribute_line.index("RELAT2")
relat2_value = csv.second[relat2_column_index] relat2_value = content_line[relat2_column_index]
expect(relat2_value).to eq "Partner" expect(relat2_value).to eq "Partner"
end end
it "gives answers to free input questions as the user input" do it "gives answers to free input questions as the user input" do
age1_column_index = csv.first.index("AGE1") age1_column_index = attribute_line.index("AGE1")
age1_value = csv.second[age1_column_index] age1_value = content_line[age1_column_index]
expect(age1_value).to eq 30.to_s expect(age1_value).to eq 30.to_s
postcode_part1, postcode_part2 = log.postcode_full.split postcode_part1, postcode_part2 = log.postcode_full.split
postcode_part1_column_index = csv.first.index("PCODE1") postcode_part1_column_index = attribute_line.index("PCODE1")
postcode_part1_value = csv.second[postcode_part1_column_index] postcode_part1_value = content_line[postcode_part1_column_index]
expect(postcode_part1_value).to eq postcode_part1 expect(postcode_part1_value).to eq postcode_part1
postcode_part2_column_index = csv.first.index("PCODE2") postcode_part2_column_index = attribute_line.index("PCODE2")
postcode_part2_value = csv.second[postcode_part2_column_index] postcode_part2_value = content_line[postcode_part2_column_index]
expect(postcode_part2_value).to eq postcode_part2 expect(postcode_part2_value).to eq postcode_part2
end end
it "exports the code for the local authority under the heading 'la'" do it "exports the code for the local authority under the heading 'la'" do
la_column_index = csv.first.index("LA") la_column_index = attribute_line.index("LA")
la_value = csv.second[la_column_index] la_value = content_line[la_column_index]
expect(la_value).to eq "E09000033" expect(la_value).to eq "E09000033"
end end
it "exports the label for the local authority under the heading 'la_label'" do it "exports the label for the local authority under the heading 'la_label'" do
la_label_column_index = csv.first.index("LANAME") la_label_column_index = attribute_line.index("LANAME")
la_label_value = csv.second[la_label_column_index] la_label_value = content_line[la_label_column_index]
expect(la_label_value).to eq "Westminster" expect(la_label_value).to eq "Westminster"
end end
@ -186,8 +198,8 @@ RSpec.describe Csv::SalesLogCsvService do
expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_labels_24.csv") expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_labels_24.csv")
values_to_delete = %w[ID] values_to_delete = %w[ID]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -201,8 +213,8 @@ RSpec.describe Csv::SalesLogCsvService do
expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_labels_23.csv") expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_labels_23.csv")
values_to_delete = %w[ID] values_to_delete = %w[ID]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -214,8 +226,8 @@ RSpec.describe Csv::SalesLogCsvService do
end end
it "exports the id for under the heading 'duplicate_set_id'" do it "exports the id for under the heading 'duplicate_set_id'" do
duplicate_set_id_column_index = csv.first.index("DUPLICATESET") duplicate_set_id_column_index = attribute_line.index("DUPLICATESET")
duplicate_set_id_value = csv.second[duplicate_set_id_column_index] duplicate_set_id_value = content_line[duplicate_set_id_column_index]
expect(duplicate_set_id_value).to eq "12312" expect(duplicate_set_id_value).to eq "12312"
end end
end end
@ -228,36 +240,36 @@ RSpec.describe Csv::SalesLogCsvService do
let(:now) { fixed_time } let(:now) { fixed_time }
it "gives answers to radio questions as their codes" do it "gives answers to radio questions as their codes" do
national_column_index = csv.first.index("NATIONAL") national_column_index = attribute_line.index("NATIONAL")
national_value = csv.second[national_column_index] national_value = content_line[national_column_index]
expect(national_value).to eq 18.to_s expect(national_value).to eq 18.to_s
relat2_column_index = csv.first.index("RELAT2") relat2_column_index = attribute_line.index("RELAT2")
relat2_value = csv.second[relat2_column_index] relat2_value = content_line[relat2_column_index]
expect(relat2_value).to eq "P" expect(relat2_value).to eq "P"
end end
it "gives answers to free input questions as the user input" do it "gives answers to free input questions as the user input" do
age1_column_index = csv.first.index("AGE1") age1_column_index = attribute_line.index("AGE1")
age1_value = csv.second[age1_column_index] age1_value = content_line[age1_column_index]
expect(age1_value).to eq 30.to_s expect(age1_value).to eq 30.to_s
postcode_part1, postcode_part2 = log.postcode_full.split postcode_part1, postcode_part2 = log.postcode_full.split
postcode_part1_column_index = csv.first.index("PCODE1") postcode_part1_column_index = attribute_line.index("PCODE1")
postcode_part1_value = csv.second[postcode_part1_column_index] postcode_part1_value = content_line[postcode_part1_column_index]
expect(postcode_part1_value).to eq postcode_part1 expect(postcode_part1_value).to eq postcode_part1
postcode_part2_column_index = csv.first.index("PCODE2") postcode_part2_column_index = attribute_line.index("PCODE2")
postcode_part2_value = csv.second[postcode_part2_column_index] postcode_part2_value = content_line[postcode_part2_column_index]
expect(postcode_part2_value).to eq postcode_part2 expect(postcode_part2_value).to eq postcode_part2
end end
it "exports the code for the local authority under the heading 'la'" do it "exports the code for the local authority under the heading 'la'" do
la_column_index = csv.first.index("LA") la_column_index = attribute_line.index("LA")
la_value = csv.second[la_column_index] la_value = content_line[la_column_index]
expect(la_value).to eq "E09000033" expect(la_value).to eq "E09000033"
end end
it "exports the label for the local authority under the heading 'la_label'" do it "exports the label for the local authority under the heading 'la_label'" do
la_label_column_index = csv.first.index("LANAME") la_label_column_index = attribute_line.index("LANAME")
la_label_value = csv.second[la_label_column_index] la_label_value = content_line[la_label_column_index]
expect(la_label_value).to eq "Westminster" expect(la_label_value).to eq "Westminster"
end end
@ -270,8 +282,8 @@ RSpec.describe Csv::SalesLogCsvService do
expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_codes_24.csv") expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_codes_24.csv")
values_to_delete = %w[ID] values_to_delete = %w[ID]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -285,8 +297,8 @@ RSpec.describe Csv::SalesLogCsvService do
expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_codes_23.csv") expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_codes_23.csv")
values_to_delete = %w[ID] values_to_delete = %w[ID]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end
@ -298,8 +310,8 @@ RSpec.describe Csv::SalesLogCsvService do
end end
it "exports the id for under the heading 'duplicate_set_id'" do it "exports the id for under the heading 'duplicate_set_id'" do
duplicate_set_id_column_index = csv.first.index("DUPLICATESET") duplicate_set_id_column_index = attribute_line.index("DUPLICATESET")
duplicate_set_id_value = csv.second[duplicate_set_id_column_index] duplicate_set_id_value = content_line[duplicate_set_id_column_index]
expect(duplicate_set_id_value).to eq "12312" expect(duplicate_set_id_value).to eq "12312"
end end
end end
@ -307,10 +319,9 @@ RSpec.describe Csv::SalesLogCsvService do
context "when the user is not a support user" do context "when the user is not a support user" do
let(:user) { create(:user, email: "billyboy@eyeklaud.com") } let(:user) { create(:user, email: "billyboy@eyeklaud.com") }
let(:headers) { csv.first }
it "does not include certain attributes in the headers" do it "does not include certain attributes in the headers" do
expect(headers).not_to include(*%w[address_line1_as_entered address_line2_as_entered town_or_city_as_entered county_as_entered postcode_full_as_entered la_as_entered created_by value_value_check monthly_charges_value_check]) expect(attribute_line).not_to include(*%w[address_line1_as_entered address_line2_as_entered town_or_city_as_entered county_as_entered postcode_full_as_entered la_as_entered created_by value_value_check monthly_charges_value_check])
end end
context "and the requested form is 2024" do context "and the requested form is 2024" do
@ -329,8 +340,8 @@ RSpec.describe Csv::SalesLogCsvService do
expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv") expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv")
values_to_delete = %w[id] values_to_delete = %w[id]
values_to_delete.each do |attribute| values_to_delete.each do |attribute|
index = csv.first.index(attribute) index = attribute_line.index(attribute)
csv.second[index] = nil content_line[index] = nil
end end
expect(csv).to eq expected_content expect(csv).to eq expected_content
end end

2
spec/services/csv/scheme_csv_service_spec.rb

@ -13,12 +13,14 @@ RSpec.describe Csv::SchemeCsvService do
before do before do
Timecop.freeze(fixed_time) Timecop.freeze(fixed_time)
Singleton.__init__(FormHandler)
create(:scheme_deactivation_period, scheme:, deactivation_date: scheme.created_at + 1.year, reactivation_date: scheme.created_at + 2.years) create(:scheme_deactivation_period, scheme:, deactivation_date: scheme.created_at + 1.year, reactivation_date: scheme.created_at + 2.years)
create(:location_deactivation_period, location:, deactivation_date: location.created_at + 6.months) create(:location_deactivation_period, location:, deactivation_date: location.created_at + 6.months)
end end
after do after do
Timecop.return Timecop.return
Singleton.__init__(FormHandler)
end end
it "returns a string" do it "returns a string" do

44
spec/services/imports/variable_definitions_service_spec.rb

@ -0,0 +1,44 @@
require "rails_helper"
RSpec.describe Imports::VariableDefinitionsService, type: :service do
let(:path) { "spec/fixtures/variable_definitions" }
let(:service) { described_class.new(path:) }
describe "#initialize" do
it "initializes with the correct path and count" do
expect(service.path).to eq(path)
expect(service.count).to eq(0)
end
end
describe "#call" do
before do
allow(Dir).to receive(:glob).and_return(%w[lettings_download_23_24.csv lettings_download_24_25.csv sales_download_23_24.csv sales_download_24_25.csv])
allow(service).to receive(:process_file)
end
it "processes each file in the directory" do
service.call
%w[lettings_download_23_24.csv lettings_download_24_25.csv sales_download_23_24.csv sales_download_24_25.csv].each do |file|
expect(service).to have_received(:process_file).with(file)
end
end
end
describe "#process_file" do
let(:file) { "spec/fixtures/variable_definitions/lettings_download_23_24.csv" }
let(:csv_content) { [["id", "Log ID"], ["status", "Status of log"], ["duplicate_set_id", "ID of a set of duplicate logs"]] }
before do
allow(CSV).to receive(:foreach).and_yield(csv_content[0]).and_yield(csv_content[1]).and_yield(csv_content[2])
end
context "when no existing record" do
it "creates new records" do
expect {
service.send(:process_file, file)
}.to change(CsvVariableDefinition, :count).by(3)
end
end
end
end

6
yarn.lock

@ -4261,9 +4261,9 @@ methods@~1.1.2:
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.7: micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.7:
version "4.0.7" version "4.0.8"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
dependencies: dependencies:
braces "^3.0.3" braces "^3.0.3"
picomatch "^2.3.1" picomatch "^2.3.1"

Loading…
Cancel
Save