Browse Source

Revert "CLDC-3787 Autocomplete address search (#2924)" (#2965)

This reverts commit 29a469b668.

Co-authored-by: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com>
pull/2956/head
Manny Dinssa 2 weeks ago committed by GitHub
parent
commit
f320687294
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 70
      app/controllers/address_search_controller.rb
  2. 8
      app/controllers/test_data_controller.rb
  3. 73
      app/frontend/controllers/address_search_controller.js
  4. 3
      app/frontend/controllers/index.js
  5. 15
      app/models/derived_variables/lettings_log_variables.rb
  6. 49
      app/models/derived_variables/sales_log_variables.rb
  7. 9
      app/models/form/lettings/pages/address_fallback.rb
  8. 17
      app/models/form/lettings/pages/address_search.rb
  9. 44
      app/models/form/lettings/questions/address_search.rb
  10. 1
      app/models/form/lettings/questions/postcode_for_full_address.rb
  11. 6
      app/models/form/lettings/subsections/property_information.rb
  12. 11
      app/models/form/sales/pages/address_fallback.rb
  13. 23
      app/models/form/sales/pages/address_search.rb
  14. 1
      app/models/form/sales/pages/no_address_found.rb
  15. 44
      app/models/form/sales/questions/address_search.rb
  16. 1
      app/models/form/sales/questions/postcode_for_full_address.rb
  17. 6
      app/models/form/sales/subsections/property_information.rb
  18. 18
      app/models/log.rb
  19. 7
      app/services/address_client.rb
  20. 1
      app/services/bulk_upload/lettings/year2024/row_parser.rb
  21. 1
      app/services/bulk_upload/lettings/year2025/row_parser.rb
  22. 1
      app/services/bulk_upload/sales/year2024/row_parser.rb
  23. 1
      app/services/bulk_upload/sales/year2025/row_parser.rb
  24. 22
      app/services/csv/lettings_log_csv_service.rb
  25. 14
      app/services/csv/sales_log_csv_service.rb
  26. 8
      app/services/uprn_data_presenter.rb
  27. 24
      app/views/form/_address_search_question.html.erb
  28. 5
      app/views/form/_select_question.html.erb
  29. 3
      app/views/form/guidance/_address_fallback.html.erb
  30. 7
      app/views/form/guidance/_address_search.html.erb
  31. 7
      config/locales/forms/2024/lettings/guidance.en.yml
  32. 7
      config/locales/forms/2024/lettings/property_information.en.yml
  33. 7
      config/locales/forms/2024/sales/guidance.en.yml
  34. 7
      config/locales/forms/2024/sales/property_information.en.yml
  35. 7
      config/locales/forms/2025/lettings/guidance.en.yml
  36. 45
      config/locales/forms/2025/lettings/property_information.en.yml
  37. 7
      config/locales/forms/2025/sales/guidance.en.yml
  38. 45
      config/locales/forms/2025/sales/property_information.en.yml
  39. 14
      config/locales/validations/sales/property_information.en.yml
  40. 4
      config/routes.rb
  41. 6
      db/migrate/20250219122817_add_manual_address_entry_selected_to_logs.rb
  42. 4
      db/schema.rb
  43. 9
      spec/factories/lettings_log.rb
  44. 10
      spec/factories/sales_log.rb
  45. 45
      spec/features/form/address_search_spec.rb
  46. 60
      spec/features/form/form_navigation_spec.rb
  47. 375
      spec/features/lettings_log_spec.rb
  48. 375
      spec/features/sales_log_spec.rb
  49. 2
      spec/fixtures/files/sales_logs_csv_export_codes_24.csv
  50. 2
      spec/fixtures/files/sales_logs_csv_export_labels_24.csv
  51. 2
      spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv
  52. 4
      spec/models/bulk_upload_spec.rb
  53. 9
      spec/models/form/lettings/pages/address_fallback_spec.rb
  54. 42
      spec/models/form/lettings/pages/address_search_spec.rb
  55. 68
      spec/models/form/lettings/questions/address_search_spec.rb
  56. 8
      spec/models/form/lettings/questions/uprn_selection_spec.rb
  57. 4
      spec/models/form/lettings/questions/uprn_spec.rb
  58. 12
      spec/models/form/lettings/subsections/property_information_spec.rb
  59. 9
      spec/models/form/sales/pages/address_fallback_spec.rb
  60. 42
      spec/models/form/sales/pages/address_search_spec.rb
  61. 4
      spec/models/form/sales/pages/uprn_confirmation_spec.rb
  62. 68
      spec/models/form/sales/questions/address_search_spec.rb
  63. 8
      spec/models/form/sales/questions/uprn_selection_spec.rb
  64. 12
      spec/models/form/sales/subsections/property_information_spec.rb
  65. 7
      spec/models/sales_log_spec.rb
  66. 4
      spec/models/validations/sales/property_validations_spec.rb
  67. 2
      spec/request_helper.rb
  68. 148
      spec/requests/address_search_controller_spec.rb
  69. 10
      spec/requests/duplicate_logs_controller_spec.rb
  70. 8
      spec/services/csv/sales_log_csv_service_spec.rb
  71. 2
      spec/services/exports/lettings_log_export_service_spec.rb
  72. 5
      spec/shared/shared_examples_for_derived_fields.rb
  73. 2
      spec/shared/shared_log_examples.rb

70
app/controllers/address_search_controller.rb

@ -1,70 +0,0 @@
class AddressSearchController < ApplicationController
before_action :authenticate_user!
before_action :set_log, only: %i[manual_input search_input]
def index
query = params[:query]
if query.match?(/\A\d+\z/) && query.length > 5
# Query is all numbers and greater than 5 digits, assume it's a UPRN
service = UprnClient.new(query)
service.call
if service.error.present?
render json: { error: service.error }, status: :not_found
else
presenter = UprnDataPresenter.new(service.result)
render json: [{ text: presenter.address, value: presenter.uprn }]
end
elsif query.match?(/[a-zA-Z]/)
# Query contains letters, assume it's an address
service = AddressClient.new(query, { minmatch: 0.2 })
service.call
if service.error.present?
render json: { error: service.error }, status: :not_found
else
results = service.result.map do |result|
presenter = AddressDataPresenter.new(result)
{ text: presenter.address, value: presenter.uprn }
end
render json: results
end
else
# Query is ambiguous, use both APIs and merge results
address_service = AddressClient.new(query, { minmatch: 0.2 })
uprn_service = UprnClient.new(query)
address_service.call
uprn_service.call
results = ([uprn_service.result] || []) + (address_service.result || [])
if address_service.error.present? && uprn_service.error.present?
render json: { error: "Address and UPRN are not recognised." }, status: :not_found
else
formatted_results = results.map do |result|
presenter = AddressDataPresenter.new(result)
{ text: presenter.address, value: presenter.uprn }
end
render json: formatted_results
end
end
end
def manual_input
@log.update!(manual_address_entry_selected: true)
redirect_to polymorphic_url([@log, :address])
end
def search_input
@log.update!(manual_address_entry_selected: false)
redirect_to polymorphic_url([@log, :address_search])
end
private
def set_log
@log = current_user.send("#{params[:log_type]}s").find(params[:log_id])
end
end

8
app/controllers/test_data_controller.rb

@ -4,14 +4,14 @@ class TestDataController < ApplicationController
def create_test_lettings_log def create_test_lettings_log
return render_not_found unless FeatureToggle.create_test_logs_enabled? return render_not_found unless FeatureToggle.create_test_logs_enabled?
log = FactoryBot.create(:lettings_log, :completed, assigned_to: current_user, ppostcode_full: "SW1A 1AA", manual_address_entry_selected: false) log = FactoryBot.create(:lettings_log, :completed, assigned_to: current_user, ppostcode_full: "SW1A 1AA")
redirect_to lettings_log_path(log) redirect_to lettings_log_path(log)
end end
def create_setup_test_lettings_log def create_setup_test_lettings_log
return render_not_found unless FeatureToggle.create_test_logs_enabled? return render_not_found unless FeatureToggle.create_test_logs_enabled?
log = FactoryBot.create(:lettings_log, :setup_completed, assigned_to: current_user, manual_address_entry_selected: false) log = FactoryBot.create(:lettings_log, :setup_completed, assigned_to: current_user)
redirect_to lettings_log_path(log) redirect_to lettings_log_path(log)
end end
@ -40,14 +40,14 @@ class TestDataController < ApplicationController
def create_test_sales_log def create_test_sales_log
return render_not_found unless FeatureToggle.create_test_logs_enabled? return render_not_found unless FeatureToggle.create_test_logs_enabled?
log = FactoryBot.create(:sales_log, :completed, assigned_to: current_user, manual_address_entry_selected: false) log = FactoryBot.create(:sales_log, :completed, assigned_to: current_user)
redirect_to sales_log_path(log) redirect_to sales_log_path(log)
end end
def create_setup_test_sales_log def create_setup_test_sales_log
return render_not_found unless FeatureToggle.create_test_logs_enabled? return render_not_found unless FeatureToggle.create_test_logs_enabled?
log = FactoryBot.create(:sales_log, :shared_ownership_setup_complete, assigned_to: current_user, manual_address_entry_selected: false) log = FactoryBot.create(:sales_log, :shared_ownership_setup_complete, assigned_to: current_user)
redirect_to sales_log_path(log) redirect_to sales_log_path(log)
end end

73
app/frontend/controllers/address_search_controller.js

@ -1,73 +0,0 @@
import { Controller } from '@hotwired/stimulus'
import accessibleAutocomplete from 'accessible-autocomplete'
import 'accessible-autocomplete/dist/accessible-autocomplete.min.css'
const options = []
const fetchOptions = async (query, searchUrl) => {
if (query.length < 2) {
throw new Error('Query must be at least 2 characters long.')
}
try {
const response = await fetch(`${searchUrl}?query=${encodeURIComponent(query.trim())}`)
return await response.json()
} catch (error) {
return error
}
}
const fetchAndPopulateSearchResults = async (query, populateResults, searchUrl, populateOptions, selectEl) => {
if (/\S/.test(query)) {
try {
const results = await fetchOptions(query, searchUrl)
if (results.length === 0) {
populateOptions([], selectEl)
populateResults([])
} else {
populateOptions(results, selectEl)
populateResults(Object.values(results).map((o) => `${o.text} (${o.value})`))
}
} catch (error) {
populateOptions([], selectEl)
populateResults([])
}
}
}
const populateOptions = (results, selectEl) => {
selectEl.innerHTML = ''
results.forEach((result) => {
const option = document.createElement('option')
option.value = result.value
option.innerHTML = `${result.text} (${result.value})`
selectEl.appendChild(option)
options.push(option)
})
}
export default class extends Controller {
connect () {
const searchUrl = JSON.parse(this.element.dataset.info).search_url
const selectEl = this.element
accessibleAutocomplete.enhanceSelectElement({
defaultValue: '',
selectElement: selectEl,
minLength: 2,
source: (query, populateResults) => {
fetchAndPopulateSearchResults(query, populateResults, searchUrl, populateOptions, selectEl)
},
autoselect: true,
showNoOptionsFound: true,
placeholder: 'Start typing to search',
templates: { suggestion: (value) => value },
onConfirm: (val) => {
const selectedResult = Array.from(selectEl.options).find(option => option.text === val)
if (selectedResult) {
selectedResult.selected = true
}
}
})
}
}

3
app/frontend/controllers/index.js

@ -19,8 +19,6 @@ import FilterLayoutController from './filter_layout_controller.js'
import TabsController from './tabs_controller.js' import TabsController from './tabs_controller.js'
import AddressSearchController from './address_search_controller.js'
application.register('accessible-autocomplete', AccessibleAutocompleteController) application.register('accessible-autocomplete', AccessibleAutocompleteController)
application.register('conditional-filter', ConditionalFilterController) application.register('conditional-filter', ConditionalFilterController)
application.register('conditional-question', ConditionalQuestionController) application.register('conditional-question', ConditionalQuestionController)
@ -29,4 +27,3 @@ application.register('numeric-question', NumericQuestionController)
application.register('filter-layout', FilterLayoutController) application.register('filter-layout', FilterLayoutController)
application.register('search', SearchController) application.register('search', SearchController)
application.register('tabs', TabsController) application.register('tabs', TabsController)
application.register('address-search', AddressSearchController)

15
app/models/derived_variables/lettings_log_variables.rb

@ -113,21 +113,6 @@ module DerivedVariables::LettingsLogVariables
self.previous_la_known = nil if is_renewal? self.previous_la_known = nil if is_renewal?
end end
if form.start_year_2024_or_later?
if manual_address_entry_selected
self.uprn_known = 0
self.uprn_selection = nil
self.uprn_confirmed = nil
else
self.uprn_confirmed = 1 if uprn.present?
self.uprn_known = 1 if uprn.present?
reset_address_fields! if uprn.blank?
if uprn_changed?
self.uprn_selection = uprn
end
end
end
if is_renewal? if is_renewal?
self.underoccupation_benefitcap = 2 if collection_start_year == 2021 self.underoccupation_benefitcap = 2 if collection_start_year == 2021
self.voiddate = startdate self.voiddate = startdate

49
app/models/derived_variables/sales_log_variables.rb

@ -55,29 +55,27 @@ module DerivedVariables::SalesLogVariables
if uprn_known&.zero? if uprn_known&.zero?
self.uprn = nil self.uprn = nil
if uprn_known_was == 1 if uprn_known_was == 1
reset_address_fields! self.address_line1 = nil
self.address_line2 = nil
self.town_or_city = nil
self.county = nil
self.pcodenk = nil
self.postcode_full = nil
self.la = nil
end end
end end
if uprn_known == 1 && uprn_confirmed&.zero? if uprn_known == 1 && uprn_confirmed&.zero?
reset_address_fields! self.uprn = nil
self.uprn_known = 0
self.uprn_confirmed = nil
end
if form.start_year_2024_or_later?
if manual_address_entry_selected
self.uprn_known = 0 self.uprn_known = 0
self.uprn_selection = nil
self.uprn_confirmed = nil self.uprn_confirmed = nil
else self.address_line1 = nil
self.uprn_confirmed = 1 if uprn.present? self.address_line2 = nil
self.uprn_known = 1 if uprn.present? self.town_or_city = nil
reset_address_fields! if uprn.blank? self.county = nil
if uprn_changed? self.pcodenk = nil
self.uprn_selection = uprn self.postcode_full = nil
end self.la = nil
end
end end
if form.start_year_2025_or_later? && is_bedsit? if form.start_year_2025_or_later? && is_bedsit?
@ -250,21 +248,4 @@ private
def prevten_was_social_housing? def prevten_was_social_housing?
[1, 2].include?(prevten) || [1, 2].include?(prevtenbuy2) [1, 2].include?(prevten) || [1, 2].include?(prevtenbuy2)
end end
def reset_address_fields!
self.uprn = nil
self.uprn_known = nil
self.address_line1 = nil
self.address_line2 = nil
self.town_or_city = nil
self.county = nil
self.pcode1 = nil
self.pcode2 = nil
self.pcodenk = nil
self.address_line1_input = nil
self.postcode_full_input = nil
self.postcode_full = nil
self.is_la_inferred = nil
self.la = nil
end
end end

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

@ -3,7 +3,14 @@ class Form::Lettings::Pages::AddressFallback < ::Form::Page
super super
@id = "address" @id = "address"
@copy_key = "lettings.property_information.address" @copy_key = "lettings.property_information.address"
@depends_on = [{ "is_supported_housing?" => false, "manual_address_entry_selected" => true }] @depends_on = [
{ "is_supported_housing?" => false, "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => nil, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_known" => 0, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "address_options_present?" => false },
]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max] @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end end

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

@ -1,17 +0,0 @@
class Form::Lettings::Pages::AddressSearch < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address_search"
@copy_key = "sales.property_information.address_search"
@depends_on = [{ "is_supported_housing?" => false, "manual_address_entry_selected" => false }]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
def questions
@questions ||= [
Form::Lettings::Questions::AddressSearch.new(nil, nil, self),
]
end
QUESTION_NUMBER_FROM_YEAR = { 2024 => 12, 2025 => 16 }.freeze
end

44
app/models/form/lettings/questions/address_search.rb

@ -1,44 +0,0 @@
class Form::Lettings::Questions::AddressSearch < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn"
@type = "address_search"
@copy_key = "lettings.property_information.address_search"
@plain_label = true
@bottom_guidance_partial = "address_search"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@hide_question_number_on_page = true
end
def answer_options(log = nil, _user = nil)
return {} unless ActiveRecord::Base.connected?
return {} unless log&.address_options&.any?
log.address_options.each_with_object({}) do |option, hash|
hash[option[:uprn]] = { "value" => "#{option[:address]} (#{option[:uprn]})" }
end
end
def get_extra_check_answer_value(log)
return unless log.uprn_known == 1
value = [
log.address_line1,
log.address_line2,
log.town_or_city,
log.county,
log.postcode_full,
(LocalAuthority.find_by(code: log.la)&.name if log.la.present?),
].select(&:present?)
return unless value.any?
"\n\n#{value.join("\n")}"
end
def displayed_answer_options(log, user = nil)
answer_options(log, user).transform_values { |value| value["value"] } || {}
end
QUESTION_NUMBER_FROM_YEAR = { 2024 => 12, 2025 => 16 }.freeze
end

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

@ -20,7 +20,6 @@ class Form::Lettings::Questions::PostcodeForFullAddress < ::Form::Question
@disable_clearing_if_not_routed_or_dynamic_answer_options = true @disable_clearing_if_not_routed_or_dynamic_answer_options = true
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max] @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@hide_question_number_on_page = true @hide_question_number_on_page = true
@bottom_guidance_partial = "address_fallback"
end end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 12, 2024 => 13, 2025 => 17 }.freeze QUESTION_NUMBER_FROM_YEAR = { 2023 => 12, 2024 => 13, 2025 => 17 }.freeze

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

@ -32,7 +32,11 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions def uprn_questions
if form.start_year_2024_or_later? if form.start_year_2024_or_later?
[ [
Form::Lettings::Pages::AddressSearch.new(nil, nil, self), Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),
Form::Lettings::Pages::AddressMatcher.new(nil, nil, self),
Form::Lettings::Pages::NoAddressFound.new(nil, nil, self), # soft validation
Form::Lettings::Pages::UprnSelection.new(nil, nil, self),
Form::Lettings::Pages::AddressFallback.new(nil, nil, self), Form::Lettings::Pages::AddressFallback.new(nil, nil, self),
] ]
else else

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

@ -3,7 +3,14 @@ class Form::Sales::Pages::AddressFallback < ::Form::Page
super super
@id = "address" @id = "address"
@copy_key = "sales.property_information.address" @copy_key = "sales.property_information.address"
@depends_on = [{ "manual_address_entry_selected" => true }] @depends_on = [
{ "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => nil, "address_options_present?" => false },
{ "uprn_known" => 0, "address_options_present?" => false },
{ "uprn_confirmed" => 0, "address_options_present?" => false },
]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max] @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end end
@ -17,5 +24,5 @@ class Form::Sales::Pages::AddressFallback < ::Form::Page
] ]
end end
QUESTION_NUMBER_FROM_YEAR = { 2024 => 16, 2025 => 14 }.freeze QUESTION_NUMBER_FROM_YEAR = { 2024 => 16, 2025 => 16 }.freeze
end end

23
app/models/form/sales/pages/address_search.rb

@ -1,23 +0,0 @@
class Form::Sales::Pages::AddressSearch < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "address_search"
@copy_key = "sales.property_information.address_search"
@depends_on = [{ "manual_address_entry_selected" => false }]
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
def questions
@questions ||= [
Form::Sales::Questions::AddressSearch.new(nil, nil, self),
]
end
def skip_href(log = nil)
return unless log
"/#{log.log_type.dasherize}s/#{log.id}/property-number-of-bedrooms"
end
QUESTION_NUMBER_FROM_YEAR = { 2024 => 15, 2025 => 13 }.freeze
end

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

@ -16,6 +16,7 @@ class Form::Sales::Pages::NoAddressFound < ::Form::Page
{ "uprn_known" => nil, "address_options_present?" => false }, { "uprn_known" => nil, "address_options_present?" => false },
{ "uprn_known" => 0, "address_options_present?" => false }, { "uprn_known" => 0, "address_options_present?" => false },
{ "uprn_confirmed" => 0, "address_options_present?" => false }, { "uprn_confirmed" => 0, "address_options_present?" => false },
] ]
end end

44
app/models/form/sales/questions/address_search.rb

@ -1,44 +0,0 @@
class Form::Sales::Questions::AddressSearch < ::Form::Question
def initialize(id, hsh, page)
super
@id = "uprn"
@type = "address_search"
@copy_key = "sales.property_information.address_search"
@plain_label = true
@bottom_guidance_partial = "address_search"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@hide_question_number_on_page = true
end
def answer_options(log = nil, _user = nil)
return {} unless ActiveRecord::Base.connected?
return {} unless log&.address_options&.any?
log.address_options.each_with_object({}) do |option, hash|
hash[option[:uprn]] = { "value" => "#{option[:address]} (#{option[:uprn]})" }
end
end
def get_extra_check_answer_value(log)
return unless log.uprn_known == 1
value = [
log.address_line1,
log.address_line2,
log.town_or_city,
log.county,
log.postcode_full,
(LocalAuthority.find_by(code: log.la)&.name if log.la.present?),
].select(&:present?)
return unless value.any?
"\n\n#{value.join("\n")}"
end
def displayed_answer_options(log, user = nil)
answer_options(log, user).transform_values { |value| value["value"] } || {}
end
QUESTION_NUMBER_FROM_YEAR = { 2024 => 15, 2025 => 13 }.freeze
end

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

@ -20,7 +20,6 @@ class Form::Sales::Questions::PostcodeForFullAddress < ::Form::Question
@disable_clearing_if_not_routed_or_dynamic_answer_options = true @disable_clearing_if_not_routed_or_dynamic_answer_options = true
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max] @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@hide_question_number_on_page = true @hide_question_number_on_page = true
@bottom_guidance_partial = "address_fallback"
end end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze

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

@ -24,7 +24,11 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions def uprn_questions
if form.start_year_2024_or_later? if form.start_year_2024_or_later?
[ [
Form::Sales::Pages::AddressSearch.new(nil, nil, self), Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::AddressMatcher.new(nil, nil, self),
Form::Sales::Pages::NoAddressFound.new(nil, nil, self),
Form::Sales::Pages::UprnSelection.new(nil, nil, self),
Form::Sales::Pages::AddressFallback.new(nil, nil, self), Form::Sales::Pages::AddressFallback.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self), Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil), Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),

18
app/models/log.rb

@ -75,7 +75,8 @@ class Log < ApplicationRecord
presenter = UprnDataPresenter.new(service.result) presenter = UprnDataPresenter.new(service.result)
self.uprn_known = 1 self.uprn_known = 1
self.uprn_selection = uprn self.uprn_confirmed = nil unless skip_update_uprn_confirmed
self.uprn_selection = nil
self.address_line1 = presenter.address_line1 self.address_line1 = presenter.address_line1
self.address_line2 = presenter.address_line2 self.address_line2 = presenter.address_line2
self.town_or_city = presenter.town_or_city self.town_or_city = presenter.town_or_city
@ -125,27 +126,16 @@ class Log < ApplicationRecord
end end
def address_options def address_options
if uprn.present?
service = UprnClient.new(uprn)
service.call
if service.result.blank? || service.error.present?
@address_options = []
return @address_options
end
presenter = UprnDataPresenter.new(service.result)
@address_options = [{ address: presenter.address, uprn: presenter.uprn }]
else
return @address_options if @address_options && @last_searched_address_string == address_string return @address_options if @address_options && @last_searched_address_string == address_string
return if address_string.blank?
if [address_line1_input, postcode_full_input].all?(&:present?)
@last_searched_address_string = address_string @last_searched_address_string = address_string
service = AddressClient.new(address_string) service = AddressClient.new(address_string)
service.call service.call
if service.result.blank? || service.error.present? if service.result.blank? || service.error.present?
@address_options = [] @address_options = []
return @address_options return @answer_options
end end
address_opts = [] address_opts = []

7
app/services/address_client.rb

@ -7,9 +7,8 @@ class AddressClient
ADDRESS = "api.os.uk".freeze ADDRESS = "api.os.uk".freeze
PATH = "/search/places/v1/find".freeze PATH = "/search/places/v1/find".freeze
def initialize(address, options = {}) def initialize(address)
@address = address @address = address
@options = options
end end
def call def call
@ -44,8 +43,8 @@ private
params = { params = {
query: address, query: address,
key: ENV["OS_DATA_KEY"], key: ENV["OS_DATA_KEY"],
maxresults: @options[:maxresults] || 10, maxresults: 10,
minmatch: @options[:minmatch] || 0.4, minmatch: 0.4,
} }
uri.query = URI.encode_www_form(params) uri.query = URI.encode_www_form(params)
uri.to_s uri.to_s

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

@ -1353,7 +1353,6 @@ private
attributes["address_line1_input"] = address_line1_input attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_16.blank? attributes["select_best_address_match"] = true if field_16.blank?
attributes["manual_address_entry_selected"] = field_16.blank?
end end
attributes attributes

1
app/services/bulk_upload/lettings/year2025/row_parser.rb

@ -1348,7 +1348,6 @@ private
attributes["address_line1_input"] = address_line1_input attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_18.blank? attributes["select_best_address_match"] = true if field_18.blank?
attributes["manual_address_entry_selected"] = field_18.blank?
end end
attributes attributes

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

@ -986,7 +986,6 @@ private
attributes["address_line1_input"] = address_line1_input attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_22.blank? attributes["select_best_address_match"] = true if field_22.blank?
attributes["manual_address_entry_selected"] = field_22.blank?
attributes["ethnic_group2"] = infer_buyer2_ethnic_group_from_ethnic attributes["ethnic_group2"] = infer_buyer2_ethnic_group_from_ethnic
attributes["ethnicbuy2"] = field_40 attributes["ethnicbuy2"] = field_40

1
app/services/bulk_upload/sales/year2025/row_parser.rb

@ -961,7 +961,6 @@ private
attributes["address_line1_input"] = address_line1_input attributes["address_line1_input"] = address_line1_input
attributes["postcode_full_input"] = postcode_full attributes["postcode_full_input"] = postcode_full
attributes["select_best_address_match"] = true if field_16.blank? attributes["select_best_address_match"] = true if field_16.blank?
attributes["manual_address_entry_selected"] = field_16.blank?
attributes["ethnic_group2"] = infer_buyer2_ethnic_group_from_ethnic attributes["ethnic_group2"] = infer_buyer2_ethnic_group_from_ethnic
attributes["ethnicbuy2"] = field_37 attributes["ethnicbuy2"] = field_37

22
app/services/csv/lettings_log_csv_service.rb

@ -208,11 +208,6 @@ module Csv
3 => "Intermediate Rent", 3 => "Intermediate Rent",
}.freeze }.freeze
UPRN_KNOWN_LABELS = {
0 => "No",
1 => "Yes",
}.freeze
LABELS = { LABELS = {
"lettype" => LETTYPE_LABELS, "lettype" => LETTYPE_LABELS,
"irproduct" => IRPRODUCT_LABELS, "irproduct" => IRPRODUCT_LABELS,
@ -220,7 +215,6 @@ module Csv
"newprop" => NEWPROP_LABELS, "newprop" => NEWPROP_LABELS,
"incref" => INCREF_LABELS, "incref" => INCREF_LABELS,
"renttype" => RENTTYPE_LABELS, "renttype" => RENTTYPE_LABELS,
"uprn_known" => UPRN_KNOWN_LABELS,
}.freeze }.freeze
CONVENTIONAL_YES_NO_ATTRIBUTES = %w[illness_type_1 illness_type_2 illness_type_3 illness_type_4 illness_type_5 illness_type_6 illness_type_7 illness_type_8 illness_type_9 illness_type_10 refused cbl cap chr accessible_register letting_allocation_none housingneeds_a housingneeds_b housingneeds_c housingneeds_d housingneeds_e housingneeds_f housingneeds_g housingneeds_h has_benefits nocharge postcode_known].freeze CONVENTIONAL_YES_NO_ATTRIBUTES = %w[illness_type_1 illness_type_2 illness_type_3 illness_type_4 illness_type_5 illness_type_6 illness_type_7 illness_type_8 illness_type_9 illness_type_10 refused cbl cap chr accessible_register letting_allocation_none housingneeds_a housingneeds_b housingneeds_c housingneeds_d housingneeds_e housingneeds_f housingneeds_g housingneeds_h has_benefits nocharge postcode_known].freeze
@ -255,18 +249,6 @@ module Csv
"letting_allocation_unknown" => %w[letting_allocation_none], "letting_allocation_unknown" => %w[letting_allocation_none],
}.freeze }.freeze
ATTRIBUTE_MAPPINGS_2024 = {
"uprn" => %w[uprn_known uprn],
}.freeze
def attribute_mappings
if @year >= 2024
ATTRIBUTE_MAPPINGS.merge(ATTRIBUTE_MAPPINGS_2024)
else
ATTRIBUTE_MAPPINGS
end
end
ORDERED_ADDRESS_FIELDS = %w[uprn address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la uprn_known uprn_selection address_search_value_check address_line1_input postcode_full_input address_line1_as_entered address_line2_as_entered town_or_city_as_entered county_as_entered postcode_full_as_entered la_as_entered].freeze ORDERED_ADDRESS_FIELDS = %w[uprn address_line1 address_line2 town_or_city county postcode_full is_la_inferred la_label la uprn_known uprn_selection address_search_value_check address_line1_input postcode_full_input address_line1_as_entered address_line2_as_entered town_or_city_as_entered county_as_entered postcode_full_as_entered la_as_entered].freeze
SUPPORT_ONLY_ATTRIBUTES = %w[postcode_known is_la_inferred totchild totelder totadult net_income_known previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 wrent wscharge wpschrge wsupchrg wtcharge wtshortfall old_form_id old_id tshortfall_known hhtype la prevloc updated_by_id uprn_confirmed address_line1_input postcode_full_input uprn_selection 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].freeze SUPPORT_ONLY_ATTRIBUTES = %w[postcode_known is_la_inferred totchild totelder totadult net_income_known previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 wrent wscharge wpschrge wsupchrg wtcharge wtshortfall old_form_id old_id tshortfall_known hhtype la prevloc updated_by_id uprn_confirmed address_line1_input postcode_full_input uprn_selection 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].freeze
@ -297,10 +279,10 @@ module Csv
ordered_questions.flat_map do |question| ordered_questions.flat_map do |question|
if question.type == "checkbox" if question.type == "checkbox"
question.answer_options.keys.reject { |key| key == "divider" }.map { |key| question.answer_options.keys.reject { |key| key == "divider" }.map { |key|
attribute_mappings.fetch(key, key) ATTRIBUTE_MAPPINGS.fetch(key, key)
}.flatten }.flatten
else else
attribute_mappings.fetch(question.id, question.id) ATTRIBUTE_MAPPINGS.fetch(question.id, question.id)
end end
end end
end end

14
app/services/csv/sales_log_csv_service.rb

@ -152,15 +152,6 @@ module Csv
"uprn_confirmed" => "UPRNCONFIRMED", "uprn_confirmed" => "UPRNCONFIRMED",
}.freeze }.freeze
UPRN_CONFIRMED_LABELS = {
0 => "No",
1 => "Yes",
}.freeze
LABELS = {
"uprn_confirmed" => UPRN_CONFIRMED_LABELS,
}.freeze
def formatted_attribute_headers def formatted_attribute_headers
return @attributes unless @user.support? return @attributes unless @user.support?
@ -217,9 +208,6 @@ module Csv
unless @user.support? && @year >= 2024 unless @user.support? && @year >= 2024
mappings["postcode_full"] = %w[pcode1 pcode2] mappings["postcode_full"] = %w[pcode1 pcode2]
end end
if @year >= 2024
mappings["uprn"] = %w[uprn uprn_confirmed address_line1_input postcode_full_input uprn_selection]
end
mappings mappings
end end
@ -292,8 +280,6 @@ module Csv
end end
def get_label(value, attribute, log) def get_label(value, attribute, log)
return LABELS[attribute][value] if LABELS.key?(attribute)
log.form log.form
.get_question(attribute, log) .get_question(attribute, log)
&.label_from_value(value) &.label_from_value(value)

8
app/services/uprn_data_presenter.rb

@ -55,12 +55,4 @@ class UprnDataPresenter
def result_from_lpi? def result_from_lpi?
data["LPI_KEY"].present? data["LPI_KEY"].present?
end end
def uprn
data["UPRN"]
end
def address
data["ADDRESS"]
end
end end

24
app/views/form/_address_search_question.html.erb

@ -1,24 +0,0 @@
<% selected = @log.public_send(question.id) || "" %>
<% answers = question.displayed_answer_options(@log, current_user).map { |key, value| OpenStruct.new(id: key, name: select_option_name(value), resource: value) } %>
<%= render partial: "form/guidance/#{question.top_guidance_partial}" if question.top_guidance? %>
<%= f.govuk_select(question.id.to_sym,
label: legend(question, page_header, conditional),
"data-controller": "address-search",
"data-info": { search_url: address_search_url }.to_json,
caption: caption(caption_text, page_header, conditional),
hint: { text: question.hint_text&.html_safe }) do %>
<% if answers.any? %>
<% answers.each do |answer| %>
<option value="<%= answer.id %>"
data-synonyms="<%= answer_option_synonyms(answer.resource) %>"
data-append="<%= answer_option_append(answer.resource) %>"
data-hint="<%= answer_option_hint(answer.resource) %>"
<%= question.answer_selected?(@log, answer) ? "selected" : "" %>><%= answer.name || answer.resource %></option>
<% end %>
<% else %>
<option value="" disabled>Javascript is disabled. Please enter the address manually.</option>
<% end %>
<% end %>
<%= render partial: "form/guidance/#{question.bottom_guidance_partial}" if question.bottom_guidance? %>

5
app/views/form/_select_question.html.erb

@ -1,3 +1,4 @@
<% selected = @log.public_send(question.id) || "" %> <% selected = @log.public_send(question.id) || "" %>
<% answers = question.displayed_answer_options(@log, current_user).map { |key, value| OpenStruct.new(id: key, name: select_option_name(value), resource: value) } %> <% answers = question.displayed_answer_options(@log, current_user).map { |key, value| OpenStruct.new(id: key, name: select_option_name(value), resource: value) } %>
<%= render partial: "form/guidance/#{question.top_guidance_partial}" if question.top_guidance? %> <%= render partial: "form/guidance/#{question.top_guidance_partial}" if question.top_guidance? %>
@ -7,7 +8,6 @@
"data-controller": "accessible-autocomplete", "data-controller": "accessible-autocomplete",
caption: caption(caption_text, page_header, conditional), caption: caption(caption_text, page_header, conditional),
hint: { text: question.hint_text&.html_safe }) do %> hint: { text: question.hint_text&.html_safe }) do %>
<% if answers.any? %>
<% answers.each do |answer| %> <% answers.each do |answer| %>
<option value="<%= answer.id %>" <option value="<%= answer.id %>"
data-synonyms="<%= answer_option_synonyms(answer.resource) %>" data-synonyms="<%= answer_option_synonyms(answer.resource) %>"
@ -15,9 +15,6 @@
data-hint="<%= answer_option_hint(answer.resource) %>" data-hint="<%= answer_option_hint(answer.resource) %>"
<%= question.answer_selected?(@log, answer) ? "selected" : "" %>><%= answer.name || answer.resource %></option> <%= question.answer_selected?(@log, answer) ? "selected" : "" %>><%= answer.name || answer.resource %></option>
<% end %> <% end %>
<% else %>
<option value="" disabled></option>
<% end %>
<% end %> <% end %>
<%= render partial: "form/guidance/#{question.bottom_guidance_partial}" if question.bottom_guidance? %> <%= render partial: "form/guidance/#{question.bottom_guidance_partial}" if question.bottom_guidance? %>

3
app/views/form/guidance/_address_fallback.html.erb

@ -1,3 +0,0 @@
<div class="govuk-button-group">
<%= govuk_link_to "Clear address and search instead", address_search_input_path(@log.log_type, @log.id), class: "govuk-button govuk-button--secondary" %>
</div>

7
app/views/form/guidance/_address_search.html.erb

@ -1,7 +0,0 @@
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.#{@log.form.type}.guidance.address_search.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.#{@log.form.type}.guidance.address_search.content").html_safe %>
<% end %>
<div class="govuk-button-group">
<%= govuk_link_to "Enter the address manually instead", address_manual_input_path(@log.log_type, @log.id), class: "govuk-button govuk-button--secondary" %>
</div>

7
config/locales/forms/2024/lettings/guidance.en.yml

@ -61,10 +61,3 @@ en:
<li>child benefit</li> <li>child benefit</li>
<li>council tax support</li> <li>council tax support</li>
</ul>" </ul>"
address_search:
title: "Can’t find the address you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Some properties may not be available yet e.g. new builds; you might need to enter them manually instead</li>
<li>For UPRN (Unique Property Reference Number), please enter the full value exactly</li>
</ul>"

7
config/locales/forms/2024/lettings/property_information.en.yml

@ -50,13 +50,6 @@ en:
hint_text: "" hint_text: ""
question_text: "Select the correct address" question_text: "Select the correct address"
address_search:
page_header: "What is the property's address?"
check_answer_label: "Address"
check_answer_prompt: "Enter address or UPRN"
hint_text: "For example, '1 Victoria Road' or '10010457355'"
question_text: "Enter address or UPRN"
address: address:
page_header: "What is the property's address?" page_header: "What is the property's address?"
address_line1: address_line1:

7
config/locales/forms/2024/sales/guidance.en.yml

@ -44,10 +44,3 @@ en:
privacy_notice_buyer: privacy_notice_buyer:
content: "Make sure the buyer has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation." content: "Make sure the buyer has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice" privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
address_search:
title: "Can’t find the address you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Some properties may not be available yet e.g. new builds; you might need to enter them manually instead</li>
<li>For UPRN (Unique Property Reference Number), please enter the full value exactly</li>
</ul>"

7
config/locales/forms/2024/sales/property_information.en.yml

@ -43,13 +43,6 @@ en:
hint_text: "" hint_text: ""
question_text: "Select the correct address" question_text: "Select the correct address"
address_search:
page_header: "What is the property's address?"
check_answer_label: "Address"
check_answer_prompt: "Enter address or UPRN"
hint_text: "For example, '1 Victoria Road' or '10010457355'"
question_text: "Enter address or UPRN"
address: address:
page_header: "What is the property's address?" page_header: "What is the property's address?"
address_line1: address_line1:

7
config/locales/forms/2025/lettings/guidance.en.yml

@ -61,10 +61,3 @@ en:
<li>child benefit</li> <li>child benefit</li>
<li>council tax support</li> <li>council tax support</li>
</ul>" </ul>"
address_search:
title: "Can’t find the address you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Some properties may not be available yet e.g. new builds; you might need to enter them manually instead</li>
<li>For UPRN (Unique Property Reference Number), please enter the full value exactly</li>
</ul>"

45
config/locales/forms/2025/lettings/property_information.en.yml

@ -10,12 +10,45 @@ en:
hint_text: "" hint_text: ""
question_text: "Is this the first time the property has been let as social housing?" question_text: "Is this the first time the property has been let as social housing?"
address_search: uprn:
page_header: "What is the property's address?" page_header: ""
check_answer_label: "Address" uprn_known:
check_answer_prompt: "Enter address or UPRN" check_answer_label: "UPRN known"
hint_text: "For example, '1 Victoria Road' or '10010457355'" check_answer_prompt: "Enter UPRN if known"
question_text: "Enter address or UPRN" hint_text: "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and various industries across the UK. An example UPRN is 10010457355.<br><br>The UPRN may not be the same as the property reference assigned by your organisation.<br><br>If you don’t know the UPRN you can enter the address of the property instead on the next screen."
question_text: "Do you know the property's UPRN?"
uprn:
check_answer_label: "UPRN"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the property's UPRN?"
uprn_confirmed:
page_header: "We found an address that might be this property"
check_answer_label: "Is this the right address?"
check_answer_prompt: "Tell us if this is the right address"
hint_text: ""
question_text: "Is this the property address?"
address_matcher:
page_header: "Find an address"
address_line1_input:
check_answer_label: "Find address"
check_answer_prompt: "Try find address"
hint_text: ""
question_text: "Address line 1"
postcode_full_input:
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Postcode"
uprn_selection:
page_header: "We found an address that might be this property"
check_answer_label: "Select correct address"
check_answer_prompt: "Select correct address"
hint_text: ""
question_text: "Select the correct address"
address: address:
page_header: "What is the property's address?" page_header: "What is the property's address?"

7
config/locales/forms/2025/sales/guidance.en.yml

@ -44,10 +44,3 @@ en:
privacy_notice_buyer: privacy_notice_buyer:
content: "Make sure the buyer has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation." content: "Make sure the buyer has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice" privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
address_search:
title: "Can’t find the address you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Some properties may not be available yet e.g. new builds; you might need to enter them manually instead</li>
<li>For UPRN (Unique Property Reference Number), please enter the full value exactly</li>
</ul>"

45
config/locales/forms/2025/sales/property_information.en.yml

@ -3,12 +3,45 @@ en:
2025: 2025:
sales: sales:
property_information: property_information:
address_search: uprn:
page_header: "What is the property's address?" page_header: ""
check_answer_label: "Address" uprn_known:
check_answer_prompt: "Enter address or UPRN" check_answer_label: "UPRN known"
hint_text: "For example, '1 Victoria Road' or '10010457355'" check_answer_prompt: "Enter UPRN if known"
question_text: "Enter address or UPRN" hint_text: "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and various industries across the UK. An example UPRN is 10010457355.<br><br>The UPRN may not be the same as the property reference assigned by your organisation.<br><br>If you don’t know the UPRN you can enter the address of the property instead on the next screen."
question_text: "Do you know the property's UPRN?"
uprn:
check_answer_label: "UPRN"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the property's UPRN?"
uprn_confirmed:
page_header: "We found an address that might be this property"
check_answer_label: "Is this the right address?"
check_answer_prompt: "Tell us if this is the right address"
hint_text: ""
question_text: "Is this the property address?"
address_matcher:
page_header: "Find an address"
address_line1_input:
check_answer_label: "Find address"
check_answer_prompt: "Try find address"
hint_text: ""
question_text: "Address line 1"
postcode_full_input:
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Postcode"
uprn_selection:
page_header: "We found an address that might be this property"
check_answer_label: "Select correct address"
check_answer_prompt: "Select correct address"
hint_text: ""
question_text: "Select the correct address"
address: address:
page_header: "What is the property's address?" page_header: "What is the property's address?"

14
config/locales/validations/sales/property_information.en.yml

@ -7,7 +7,7 @@ en:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
invalid: "Enter a postcode in the correct format, for example AA1 1AA." invalid: "Enter a postcode in the correct format, for example AA1 1AA."
not_in_england: "It looks like you have entered a postcode outside of England. Only create logs for sales in England." not_in_england: "It looks like you have entered a postcode outside of England - only submit Lettings forms for Lettings that occur in England"
ppostcode_full: ppostcode_full:
postcode_must_match_previous: postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
@ -21,7 +21,7 @@ en:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
invalid: "UPRN must be 12 digits or less." invalid: "UPRN must be 12 digits or less."
not_in_england: "It looks like you have entered an address outside of England. Only create logs for sales in England." not_in_england: "It looks like you have an entered a postcode outside of England. Only create logs for lettings in England."
beds: beds:
bedsits_have_max_one_bedroom: "Number of bedrooms must be 1 if the property is a bedsit." bedsits_have_max_one_bedroom: "Number of bedrooms must be 1 if the property is a bedsit."
proptype: proptype:
@ -29,11 +29,11 @@ en:
uprn_known: uprn_known:
invalid: "You must answer UPRN known?" invalid: "You must answer UPRN known?"
la: la:
not_in_england: "It looks like you have entered an address outside of England. Only create logs for sales in England." not_in_england: "It looks like you have entered an address outside of England. Only create logs for lettings in England."
uprn_confirmation: uprn_confirmation:
not_in_england: "It looks like you have entered an address outside of England. Only create logs for sales in England." not_in_england: "It looks like you have entered an address outside of England. Only create logs for lettings in England."
uprn_selection: uprn_selection:
not_in_england: "It looks like you have entered an address outside of England. Only create logs for sales in England." not_in_england: "It looks like you have entered an address outside of England. Only create logs for lettings in England."
saledate: saledate:
postcode_not_in_england: "It looks like you have entered a postcode outside of England. Only create logs for sales in England." postcode_not_in_england: "It looks like you have an entered a postcode outside of England. Only create logs for lettings in England."
address_not_in_england: "It looks like you have entered an address outside of England. Only create logs for sales in England." address_not_in_england: "It looks like you have entered an address outside of England. Only create logs for lettings in England."

4
config/routes.rb

@ -39,10 +39,6 @@ Rails.application.routes.draw do
get "/data-sharing-agreement", to: "content#data_sharing_agreement" get "/data-sharing-agreement", to: "content#data_sharing_agreement"
get "/service-moved", to: "maintenance#service_moved" get "/service-moved", to: "maintenance#service_moved"
get "/service-unavailable", to: "maintenance#service_unavailable" get "/service-unavailable", to: "maintenance#service_unavailable"
get "/address-search", to: "address_search#index"
get "/address-search/current", to: "address_search#current"
get "/address-search/manual-input/:log_type/:log_id", to: "address_search#manual_input", as: "address_manual_input"
get "/address-search/search-input/:log_type/:log_id", to: "address_search#search_input", as: "address_search_input"
get "collection-resources", to: "collection_resources#index" get "collection-resources", to: "collection_resources#index"
get "/collection-resources/:log_type/:year/:resource_type/download", to: "collection_resources#download_mandatory_collection_resource", as: :download_mandatory_collection_resource get "/collection-resources/:log_type/:year/:resource_type/download", to: "collection_resources#download_mandatory_collection_resource", as: :download_mandatory_collection_resource

6
db/migrate/20250219122817_add_manual_address_entry_selected_to_logs.rb

@ -1,6 +0,0 @@
class AddManualAddressEntrySelectedToLogs < ActiveRecord::Migration[7.2]
def change
add_column :sales_logs, :manual_address_entry_selected, :boolean, default: false
add_column :lettings_logs, :manual_address_entry_selected, :boolean, default: false
end
end

4
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.2].define(version: 2025_02_19_122817) do ActiveRecord::Schema[7.2].define(version: 2025_01_10_150609) 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"
@ -373,7 +373,6 @@ ActiveRecord::Schema[7.2].define(version: 2025_02_19_122817) do
t.integer "partner_under_16_value_check" t.integer "partner_under_16_value_check"
t.integer "multiple_partners_value_check" t.integer "multiple_partners_value_check"
t.bigint "created_by_id" t.bigint "created_by_id"
t.boolean "manual_address_entry_selected", default: false
t.index ["assigned_to_id"], name: "index_lettings_logs_on_assigned_to_id" t.index ["assigned_to_id"], name: "index_lettings_logs_on_assigned_to_id"
t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id" t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id"
@ -770,7 +769,6 @@ ActiveRecord::Schema[7.2].define(version: 2025_02_19_122817) do
t.decimal "mrentprestaircasing", precision: 10, scale: 2 t.decimal "mrentprestaircasing", precision: 10, scale: 2
t.datetime "lasttransaction" t.datetime "lasttransaction"
t.datetime "initialpurchase" t.datetime "initialpurchase"
t.boolean "manual_address_entry_selected", default: false
t.index ["assigned_to_id"], name: "index_sales_logs_on_assigned_to_id" t.index ["assigned_to_id"], name: "index_sales_logs_on_assigned_to_id"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"

9
spec/factories/lettings_log.rb

@ -6,7 +6,6 @@ FactoryBot.define do
managing_organisation { assigned_to.organisation } managing_organisation { assigned_to.organisation }
created_at { Time.zone.today } created_at { Time.zone.today }
updated_at { Time.zone.today } updated_at { Time.zone.today }
manual_address_entry_selected { true }
before(:create) do |log, _evaluator| before(:create) do |log, _evaluator|
if log.period && !log.managing_organisation.organisation_rent_periods.exists?(rent_period: log.period) if log.period && !log.managing_organisation.organisation_rent_periods.exists?(rent_period: log.period)
@ -167,11 +166,13 @@ FactoryBot.define do
town_or_city { Faker::Address.city } town_or_city { Faker::Address.city }
ppcodenk { 1 } ppcodenk { 1 }
tshortfall_known { 1 } tshortfall_known { 1 }
after(:build) do |log, evaluator| after(:build) do |log, _evaluator|
if log.startdate >= Time.zone.local(2024, 4, 1) if log.startdate >= Time.zone.local(2024, 4, 1)
log.address_line1_input = log.address_line1
log.postcode_full_input = log.postcode_full
log.nationality_all_group = 826 log.nationality_all_group = 826
log.uprn = evaluator.uprn || "10033558653" log.uprn = "10033558653"
log.uprn_selection = evaluator.uprn_selection || "10033558653" log.uprn_selection = 1
end end
end end
end end

10
spec/factories/sales_log.rb

@ -8,8 +8,6 @@ FactoryBot.define do
managing_organisation { assigned_to.organisation } managing_organisation { assigned_to.organisation }
created_at { Time.zone.now } created_at { Time.zone.now }
updated_at { Time.zone.now } updated_at { Time.zone.now }
manual_address_entry_selected { true }
trait :in_progress do trait :in_progress do
purchid { "PC123" } purchid { "PC123" }
ownershipsch { 2 } ownershipsch { 2 }
@ -168,12 +166,14 @@ FactoryBot.define do
nationalbuy2 { 13 } nationalbuy2 { 13 }
buy2living { 3 } buy2living { 3 }
proplen_asked { 1 } proplen_asked { 1 }
after(:build) do |log, evaluator| after(:build) do |log, _evaluator|
if log.saledate >= Time.zone.local(2024, 4, 1) if log.saledate >= Time.zone.local(2024, 4, 1)
log.address_line1_input = log.address_line1
log.postcode_full_input = log.postcode_full
log.nationality_all_group = 826 log.nationality_all_group = 826
log.nationality_all_buyer2_group = 826 log.nationality_all_buyer2_group = 826
log.uprn = evaluator.uprn || "10033558653" log.uprn = "10033558653"
log.uprn_selection = evaluator.uprn_selection || "10033558653" log.uprn_selection = 1
end end
if log.saledate >= Time.zone.local(2025, 4, 1) if log.saledate >= Time.zone.local(2025, 4, 1)
log.relat2 = "X" if log.relat2 == "C" log.relat2 = "X" if log.relat2 == "C"

45
spec/features/form/address_search_spec.rb

@ -1,45 +0,0 @@
require "rails_helper"
require_relative "helpers"
RSpec.describe "Address Search" do
include Helpers
let(:user) { FactoryBot.create(:user) }
let(:sales_log) do
FactoryBot.create(
:sales_log,
:shared_ownership_setup_complete,
assigned_to: user,
manual_address_entry_selected: false,
)
end
before do
sign_in user
end
context "when using address search feature" do
before do
visit("/sales-logs/#{sales_log.id}/address-search")
end
it "allows searching by a UPRN", js: true do
find("#sales-log-uprn-field").click.native.send_keys("1", "0", "0", "3", "3", "5", "4", "4", "6", "1", "4", :down)
expect(find("#sales-log-uprn-field").value).to eq("10033544614")
end
it "allows searching by address", js: true do
find("#sales-log-uprn-field").click.native.send_keys("S", "W", "1", "5", :down, :enter)
expect(find("#sales-log-uprn-field").value).to eq("SW15")
end
it "displays the placeholder text", js: true do
expect(find("#sales-log-uprn-field")["placeholder"]).to eq("Start typing to search")
end
it "displays correct bottom guidance text" do
find("span.govuk-details__summary-text", text: "Can’t find the address you’re looking for?").click
expect(page).to have_content("Some properties may not be available yet e.g. new builds; you might need to enter them manually instead")
expect(page).to have_content("For UPRN (Unique Property Reference Number), please enter the full value exactly")
end
end
end

60
spec/features/form/form_navigation_spec.rb

@ -186,4 +186,64 @@ RSpec.describe "Form Navigation" do
expect(page).to have_current_path("/lettings-logs/#{id}/duplicate-logs?original_log_id=#{id}") expect(page).to have_current_path("/lettings-logs/#{id}/duplicate-logs?original_log_id=#{id}")
end end
end end
describe "searching for an address" do
let(:now) { Time.zone.local(2024, 5, 1) }
context "with a lettings log" do
let(:lettings_log) { create(:lettings_log, :setup_completed, startdate: Time.zone.local(2024, 5, 5), assigned_to: user) }
before do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: { results: [{ DPA: { MATCH: 0.9, BUILDING_NAME: "result address line 1", POST_TOWN: "result town or city", POSTCODE: "AA1 1AA", UPRN: "12345" } }] }.to_json, headers: {})
end
it "allows searching for an address" do
visit("lettings-logs/#{id}/address-matcher")
fill_in("lettings-log-address-line1-input-field", with: "address")
fill_in("lettings-log-postcode-full-input-field", with: "A1 1AA")
click_button(text: "Search")
expect(page).to have_current_path("/lettings-logs/#{id}/uprn-selection")
end
it "allows searching for an address from check your answers page" do
visit("lettings-logs/#{id}/address-matcher?referrer=check_answers")
fill_in("lettings-log-address-line1-input-field", with: "address")
fill_in("lettings-log-postcode-full-input-field", with: "A1 1AA")
click_button(text: "Search")
expect(page).to have_current_path("/lettings-logs/#{id}/uprn-selection?referrer=check_answers&unanswered_pages=property_local_authority")
choose("lettings-log-uprn-selection-12345-field", allow_label_click: true)
click_button(text: "Save changes")
expect(page).to have_current_path("/lettings-logs/#{id}/property-information/check-answers")
end
end
context "with a sales log" do
let(:sales_log) { create(:sales_log, :outright_sale_setup_complete, saledate: Time.zone.local(2024, 5, 5), assigned_to: user) }
before do
stub_request(:get, /api\.os\.uk/)
.to_return(status: 200, body: { results: [{ DPA: { MATCH: 0.9, BUILDING_NAME: "result address line 1", POST_TOWN: "result town or city", POSTCODE: "AA1 1AA", UPRN: "12345" } }] }.to_json, headers: {})
end
it "allows searching for an address" do
visit("sales-logs/#{sales_log.id}/address-matcher")
fill_in("sales-log-address-line1-input-field", with: "address")
fill_in("sales-log-postcode-full-input-field", with: "A1 1AA")
click_button(text: "Search")
expect(page).to have_current_path("/sales-logs/#{sales_log.id}/uprn-selection")
end
it "allows searching for an address from check your answers page" do
visit("sales-logs/#{sales_log.id}/address-matcher?referrer=check_answers")
fill_in("sales-log-address-line1-input-field", with: "address")
fill_in("sales-log-postcode-full-input-field", with: "A1 1AA")
click_button(text: "Search")
expect(page).to have_current_path("/sales-logs/#{sales_log.id}/uprn-selection?referrer=check_answers&unanswered_pages=property_local_authority")
choose("sales-log-uprn-selection-12345-field", allow_label_click: true)
click_button(text: "Save changes")
expect(page).to have_current_path("/sales-logs/#{sales_log.id}/property-information/check-answers")
end
end
end
end end

375
spec/features/lettings_log_spec.rb

@ -729,5 +729,380 @@ RSpec.describe "Lettings Log Features" do
expect(duplicate_log.duplicate_set_id).to be_nil expect(duplicate_log.duplicate_set_id).to be_nil
end end
end end
context "when filling out address fields" do
let(:lettings_log) { create(:lettings_log, :setup_completed, assigned_to: user) }
before do
body = {
results: [
{
DPA: {
"POSTCODE": "AA1 1AA",
"POST_TOWN": "Bristol",
"ORGANISATION_NAME": "Some place",
},
},
],
}.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key=OS_DATA_KEY&uprn=111")
.to_return(status: 200, body:, headers: {})
body = { results: [{ DPA: { UPRN: "111" } }] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?query=Address+line+1%2C+AA1+1AA&key=OS_DATA_KEY&maxresults=10&minmatch=0.4")
.to_return(status: 200, body:, headers: {})
WebMock.stub_request(:get, "https://api.postcodes.io/postcodes/AA11AA")
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"postcode\":\"AA1 1AA\",\"admin_district\":\"Westminster\",\"codes\":{\"admin_district\":\"E09000033\"}}}", headers: {})
WebMock.stub_request(:get, "https://api.postcodes.io/postcodes/AA12AA")
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"postcode\":\"AA1 2AA\",\"admin_district\":\"Wigan\",\"codes\":{\"admin_district\":\"E08000010\"}}}", headers: {})
body = { results: [] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?query=Address+line+1%2C+AA1+1AB&key=OS_DATA_KEY&maxresults=10&minmatch=0.4")
.to_return(status: 200, body:, headers: {})
visit("/lettings-logs/#{lettings_log.id}/uprn")
end
context "and uprn is known and answered" do
before do
choose "Yes"
fill_in("lettings_log[uprn]", with: "111")
click_button("Save and continue")
end
context "and uprn is confirmed" do
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(1) # yes
expect(lettings_log.uprn).to eq("111")
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Some Place")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq("Bristol")
expect(lettings_log.address_line1_input).to eq(nil)
expect(lettings_log.postcode_full_input).to eq(nil)
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
choose "Yes"
click_button("Save and continue")
lettings_log.reload
expect(lettings_log.uprn_known).to eq(1) # yes
expect(lettings_log.uprn).to eq("111")
expect(lettings_log.uprn_confirmed).to eq(1) # yes
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Some Place")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq("Bristol")
expect(lettings_log.address_line1_input).to eq(nil)
expect(lettings_log.postcode_full_input).to eq(nil)
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
end
context "and changes to uprn not known" do
it "sets correct address fields" do
visit("/lettings-logs/#{lettings_log.id}/uprn")
choose "No"
click_button("Save and continue")
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq(nil)
expect(lettings_log.postcode_full_input).to eq(nil)
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
end
end
context "and uprn is not confirmed" do
before do
choose "No, I want to search for the address instead"
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq(nil)
expect(lettings_log.postcode_full_input).to eq(nil)
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
end
end
context "and uprn is not known" do
before do
choose "No"
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq(nil)
expect(lettings_log.postcode_full_input).to eq(nil)
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
context "and the address is not found" do
it "sets correct address fields" do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AB")
click_button("Search")
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AB")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq(nil)
click_button("Confirm and continue")
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AB")
expect(lettings_log.address_search_value_check).to eq(0)
expect(lettings_log.la).to eq(nil)
end
end
context "and address is found, re-searched and not found" do
before do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
visit("/lettings-logs/#{lettings_log.id}/address-matcher")
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AB")
click_button("Search")
end
it "routes to the correct page" do
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/no-address-found")
end
end
context "and the user selects 'address_not_listed'" do
before do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq("uprn_not_listed")
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Address line 1")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AA")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
end
context "and the user enters a new address manually" do
context "without changing a valid postcode" do
before do
fill_in("lettings_log[town_or_city]", with: "Town")
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq("uprn_not_listed")
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Address line 1")
expect(lettings_log.address_line2).to eq("")
expect(lettings_log.town_or_city).to eq("Town")
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AA")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
end
end
context "with changing the postcode" do
before do
fill_in("lettings_log[town_or_city]", with: "Town")
fill_in("lettings_log[postcode_full]", with: "AA12AA")
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq("uprn_not_listed")
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 2AA")
expect(lettings_log.address_line1).to eq("Address line 1")
expect(lettings_log.address_line2).to eq("")
expect(lettings_log.town_or_city).to eq("Town")
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AA")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E08000010")
end
end
end
end
context "and the user selects 'address_not_listed' when partial postcode is entered" do
before do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(0) # no
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq("uprn_not_listed")
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq("Address line 1")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
end
context "and the user selects 'address_not_listed' and then changes their mind and selects an address" do
before do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
visit("/lettings-logs/#{lettings_log.id}/uprn-selection")
choose("lettings-log-uprn-selection-111-field", allow_label_click: true)
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(1)
expect(lettings_log.uprn).to eq("111")
expect(lettings_log.uprn_confirmed).to eq(1)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Some Place")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq("Bristol")
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AA")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
end
end
context "and possible addresses found and selected" do
before do
fill_in("lettings_log[address_line1_input]", with: "Address line 1")
fill_in("lettings_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose("lettings-log-uprn-selection-111-field", allow_label_click: true)
click_button("Save and continue")
end
it "sets correct address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(1)
expect(lettings_log.uprn).to eq("111")
expect(lettings_log.uprn_confirmed).to eq(1)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("AA1 1AA")
expect(lettings_log.address_line1).to eq("Some Place")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq("Bristol")
expect(lettings_log.address_line1_input).to eq("Address line 1")
expect(lettings_log.postcode_full_input).to eq("AA1 1AA")
expect(lettings_log.address_search_value_check).to eq(nil)
expect(lettings_log.la).to eq("E09000033")
end
end
end
end
end end
end end

375
spec/features/sales_log_spec.rb

@ -334,6 +334,381 @@ RSpec.describe "Sales Log Features" do
expect(page).to have_current_path("/sales-logs/bulk-uploads") expect(page).to have_current_path("/sales-logs/bulk-uploads")
end end
end end
context "when filling out address fields" do
let(:sales_log) { create(:sales_log, :shared_ownership_setup_complete, assigned_to: user) }
before do
body = {
results: [
{
DPA: {
"POSTCODE": "AA1 1AA",
"POST_TOWN": "Bristol",
"ORGANISATION_NAME": "Some place",
},
},
],
}.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key=OS_DATA_KEY&uprn=111")
.to_return(status: 200, body:, headers: {})
body = { results: [{ DPA: { UPRN: "111" } }] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?query=Address+line+1%2C+AA1+1AA&key=OS_DATA_KEY&maxresults=10&minmatch=0.4")
.to_return(status: 200, body:, headers: {})
WebMock.stub_request(:get, "https://api.postcodes.io/postcodes/AA11AA")
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"postcode\":\"AA1 1AA\",\"admin_district\":\"Westminster\",\"codes\":{\"admin_district\":\"E09000033\"}}}", headers: {})
WebMock.stub_request(:get, "https://api.postcodes.io/postcodes/AA12AA")
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"postcode\":\"AA1 2AA\",\"admin_district\":\"Wigan\",\"codes\":{\"admin_district\":\"E08000010\"}}}", headers: {})
body = { results: [] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?query=Address+line+1%2C+AA1+1AB&key=OS_DATA_KEY&maxresults=10&minmatch=0.4")
.to_return(status: 200, body:, headers: {})
visit("/sales-logs/#{sales_log.id}/uprn")
end
context "and uprn is known and answered" do
before do
choose "Yes"
fill_in("sales_log[uprn]", with: "111")
click_button("Save and continue")
end
context "and uprn is confirmed" do
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(1) # yes
expect(sales_log.uprn).to eq("111")
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Some Place")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq("Bristol")
expect(sales_log.address_line1_input).to eq(nil)
expect(sales_log.postcode_full_input).to eq(nil)
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
choose "Yes"
click_button("Save and continue")
sales_log.reload
expect(sales_log.uprn_known).to eq(1) # yes
expect(sales_log.uprn).to eq("111")
expect(sales_log.uprn_confirmed).to eq(1) # yes
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Some Place")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq("Bristol")
expect(sales_log.address_line1_input).to eq(nil)
expect(sales_log.postcode_full_input).to eq(nil)
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
end
context "and changes to uprn not known" do
it "sets correct address fields" do
visit("/sales-logs/#{sales_log.id}/uprn")
choose "No"
click_button("Save and continue")
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq(nil)
expect(sales_log.postcode_full_input).to eq(nil)
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq(nil)
end
end
end
context "and uprn is not confirmed" do
before do
choose "No, I want to search for the address instead"
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq(nil)
expect(sales_log.postcode_full_input).to eq(nil)
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq(nil)
end
end
end
context "and uprn is not known" do
before do
choose "No"
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq(nil)
expect(sales_log.postcode_full_input).to eq(nil)
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq(nil)
end
context "and the address is not found" do
it "sets correct address fields" do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AB")
click_button("Search")
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AB")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq(nil)
click_button("Confirm and continue")
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AB")
expect(sales_log.address_search_value_check).to eq(0)
expect(sales_log.la).to eq(nil)
end
end
context "and address is found, re-searched and not found" do
before do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
visit("/sales-logs/#{sales_log.id}/address-matcher")
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AB")
click_button("Search")
end
it "routes to the correct page" do
expect(page).to have_current_path("/sales-logs/#{sales_log.id}/no-address-found")
end
end
context "and the user selects 'address_not_listed'" do
before do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq("uprn_not_listed")
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Address line 1")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
end
context "and the user enters a new address manually" do
context "without changing a valid postcode" do
before do
fill_in("sales_log[town_or_city]", with: "Town")
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq("uprn_not_listed")
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Address line 1")
expect(sales_log.address_line2).to eq("")
expect(sales_log.town_or_city).to eq("Town")
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
end
end
context "with changing the postcode" do
before do
fill_in("sales_log[town_or_city]", with: "Town")
fill_in("sales_log[postcode_full]", with: "AA12AA")
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq("uprn_not_listed")
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 2AA")
expect(sales_log.address_line1).to eq("Address line 1")
expect(sales_log.address_line2).to eq("")
expect(sales_log.town_or_city).to eq("Town")
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E08000010")
end
end
end
end
context "and the user selects 'address_not_listed' when partial postcode is given" do
before do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "1AA")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(0) # no
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq("uprn_not_listed")
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq("Address line 1")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq(nil)
end
end
context "and the user selects 'address_not_listed' and then changes their mind and selects an address" do
before do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose "The address is not listed, I want to enter the address manually"
click_button("Save and continue")
visit("/sales-logs/#{sales_log.id}/uprn-selection")
choose("sales-log-uprn-selection-111-field", allow_label_click: true)
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(1)
expect(sales_log.uprn).to eq("111")
expect(sales_log.uprn_confirmed).to eq(1)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Some Place")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq("Bristol")
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
end
end
context "and possible addresses found and selected" do
before do
fill_in("sales_log[address_line1_input]", with: "Address line 1")
fill_in("sales_log[postcode_full_input]", with: "AA1 1AA")
click_button("Search")
choose("sales-log-uprn-selection-111-field", allow_label_click: true)
click_button("Save and continue")
end
it "sets correct address fields" do
sales_log.reload
expect(sales_log.uprn_known).to eq(1)
expect(sales_log.uprn).to eq("111")
expect(sales_log.uprn_confirmed).to eq(1)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("AA1 1AA")
expect(sales_log.address_line1).to eq("Some Place")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq("Bristol")
expect(sales_log.address_line1_input).to eq("Address line 1")
expect(sales_log.postcode_full_input).to eq("AA1 1AA")
expect(sales_log.address_search_value_check).to eq(nil)
expect(sales_log.la).to eq("E09000033")
end
end
end
end
end end
context "when a log becomes a duplicate" do context "when a log becomes a duplicate" do

2
spec/fixtures/files/sales_logs_csv_export_codes_24.csv vendored

File diff suppressed because one or more lines are too long

2
spec/fixtures/files/sales_logs_csv_export_labels_24.csv vendored

File diff suppressed because one or more lines are too long

2
spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv vendored

File diff suppressed because one or more lines are too long

4
spec/models/bulk_upload_spec.rb

@ -24,7 +24,7 @@ RSpec.describe BulkUpload, type: :model do
let(:log) { build(:lettings_log, startdate: Time.zone.local(2025, 4, 2), bulk_upload:) } let(:log) { build(:lettings_log, startdate: Time.zone.local(2025, 4, 2), bulk_upload:) }
it "has the correct number of value checks to be set as confirmed" do it "has the correct number of value checks to be set as confirmed" do
expect(bulk_upload.fields_to_confirm(log)).to match_array %w[rent_value_check void_date_value_check major_repairs_date_value_check pregnancy_value_check retirement_value_check referral_value_check net_income_value_check scharge_value_check pscharge_value_check supcharg_value_check multiple_partners_value_check partner_under_16_value_check reasonother_value_check] expect(bulk_upload.fields_to_confirm(log)).to match_array %w[rent_value_check void_date_value_check major_repairs_date_value_check pregnancy_value_check retirement_value_check referral_value_check net_income_value_check scharge_value_check pscharge_value_check supcharg_value_check address_search_value_check multiple_partners_value_check partner_under_16_value_check reasonother_value_check]
end end
end end
@ -32,7 +32,7 @@ RSpec.describe BulkUpload, type: :model do
let(:log) { build(:sales_log, :saledate_today, bulk_upload:) } let(:log) { build(:sales_log, :saledate_today, bulk_upload:) }
it "has the correct number of value checks to be set as confirmed" do it "has the correct number of value checks to be set as confirmed" do
expect(bulk_upload.fields_to_confirm(log)).to match_array %w[value_value_check monthly_charges_value_check percentage_discount_value_check income1_value_check income2_value_check combined_income_value_check retirement_value_check old_persons_shared_ownership_value_check buyer_livein_value_check student_not_child_value_check wheel_value_check mortgage_value_check savings_value_check deposit_value_check staircase_bought_value_check stairowned_value_check hodate_check shared_ownership_deposit_value_check extrabor_value_check grant_value_check discounted_sale_value_check deposit_and_mortgage_value_check multiple_partners_value_check partner_under_16_value_check] expect(bulk_upload.fields_to_confirm(log)).to match_array %w[value_value_check monthly_charges_value_check percentage_discount_value_check income1_value_check income2_value_check combined_income_value_check retirement_value_check old_persons_shared_ownership_value_check buyer_livein_value_check student_not_child_value_check wheel_value_check mortgage_value_check savings_value_check deposit_value_check staircase_bought_value_check stairowned_value_check hodate_check shared_ownership_deposit_value_check extrabor_value_check grant_value_check discounted_sale_value_check deposit_and_mortgage_value_check address_search_value_check multiple_partners_value_check partner_under_16_value_check]
end end
end end
end end

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

@ -24,6 +24,13 @@ RSpec.describe Form::Lettings::Pages::AddressFallback, type: :model do
end end
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to eq([{ "manual_address_entry_selected" => true, "is_supported_housing?" => false }]) expect(page.depends_on).to eq([
{ "is_supported_housing?" => false, "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "is_supported_housing?" => false, "uprn_known" => nil, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_known" => 0, "address_options_present?" => false },
{ "is_supported_housing?" => false, "uprn_confirmed" => 0, "address_options_present?" => false },
])
end end
end end

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

@ -1,42 +0,0 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::AddressSearch, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
let(:start_date) { Time.utc(2024, 4, 1) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[uprn])
end
it "has the correct id" do
expect(page.id).to eq("address_search")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "is_supported_housing?" => false, "manual_address_entry_selected" => false }])
end
it "has the correct question number" do
expect(page.question_number).to eq(12)
end
context "with 2025/26 form" do
let(:start_date) { Time.utc(2025, 4, 1) }
it "has the correct question number" do
expect(page.question_number).to eq(16)
end
end
end

68
spec/models/form/lettings/questions/address_search_spec.rb

@ -1,68 +0,0 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::AddressSearch, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date:))) }
let(:start_date) { Time.utc(2024, 4, 1) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("uprn")
end
it "has the correct type" do
expect(question.type).to eq("address_search")
end
it "has the correct question number" do
expect(question.question_number).to eq(12)
end
context "with 2025/26 form" do
let(:start_date) { Time.utc(2025, 4, 1) }
it "has the correct question number" do
expect(question.question_number).to eq(16)
end
end
describe "get_extra_check_answer_value" do
context "when address is not present" do
let(:log) { build(:lettings_log, manual_address_entry_selected: false) }
it "returns nil" do
expect(question.get_extra_check_answer_value(log)).to be_nil
end
end
context "when address search is present" do
let(:log) do
build(
:lettings_log,
:completed,
address_line1: "19, Charlton Gardens",
town_or_city: "Bristol",
postcode_full: "BS10 6LU",
la: "E06000023",
uprn_known: 1,
uprn: 107,
uprn_confirmed: 1,
)
end
context "when uprn known" do
it "returns formatted value" do
expect(question.get_extra_check_answer_value(log)).to eq(
"\n\n19, Charlton Gardens\nBristol\nBS10 6LU\nBristol, City of",
)
end
end
end
end
end

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

@ -90,10 +90,9 @@ RSpec.describe Form::Lettings::Questions::UprnSelection, type: :model do
context "when the log has address line 1 input only" do context "when the log has address line 1 input only" do
before do before do
allow(address_client_instance).to receive(:result).and_return(nil)
log.address_line1_input = "Address line 1" log.address_line1_input = "Address line 1"
log.postcode_full_input = nil log.postcode_full_input = nil
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do
@ -103,10 +102,9 @@ RSpec.describe Form::Lettings::Questions::UprnSelection, type: :model do
context "when the log has postcode input only" do context "when the log has postcode input only" do
before do before do
allow(address_client_instance).to receive(:result).and_return(nil)
log.address_line1_input = nil log.address_line1_input = nil
log.postcode_full_input = "A1 1AA" log.postcode_full_input = "A1 1AA"
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do
@ -118,7 +116,7 @@ RSpec.describe Form::Lettings::Questions::UprnSelection, type: :model do
before do before do
log.address_line1_input = "Address line 1" log.address_line1_input = "Address line 1"
log.postcode_full_input = "A1 1AA" log.postcode_full_input = "A1 1AA"
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do

4
spec/models/form/lettings/questions/uprn_spec.rb

@ -52,14 +52,12 @@ RSpec.describe Form::Lettings::Questions::Uprn, type: :model do
la: "E09000003", la: "E09000003",
uprn_known:, uprn_known:,
uprn:, uprn:,
manual_address_entry_selected:,
) )
end end
context "when uprn known nil" do context "when uprn known nil" do
let(:uprn_known) { nil } let(:uprn_known) { nil }
let(:uprn) { nil } let(:uprn) { nil }
let(:manual_address_entry_selected) { true }
it "returns formatted value" do it "returns formatted value" do
expect(question.get_extra_check_answer_value(log)).to be_nil expect(question.get_extra_check_answer_value(log)).to be_nil
@ -69,7 +67,6 @@ RSpec.describe Form::Lettings::Questions::Uprn, type: :model do
context "when uprn known" do context "when uprn known" do
let(:uprn_known) { 1 } let(:uprn_known) { 1 }
let(:uprn) { 1 } let(:uprn) { 1 }
let(:manual_address_entry_selected) { false }
it "returns formatted value" do it "returns formatted value" do
expect(question.get_extra_check_answer_value(log)).to eq( expect(question.get_extra_check_answer_value(log)).to eq(
@ -81,7 +78,6 @@ RSpec.describe Form::Lettings::Questions::Uprn, type: :model do
context "when uprn not known" do context "when uprn not known" do
let(:uprn_known) { 0 } let(:uprn_known) { 0 }
let(:uprn) { nil } let(:uprn) { nil }
let(:manual_address_entry_selected) { true }
it "returns formatted value" do it "returns formatted value" do
expect(question.get_extra_check_answer_value(log)).to be_nil expect(question.get_extra_check_answer_value(log)).to be_nil

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

@ -64,7 +64,11 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do
it "has correct pages" do it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq( expect(property_information.pages.map(&:id)).to eq(
%w[ %w[
address_search uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address address
property_local_authority property_local_authority
local_authority_rent_value_check local_authority_rent_value_check
@ -97,7 +101,11 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do
it "has correct pages" do it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq( expect(property_information.pages.map(&:id)).to eq(
%w[ %w[
address_search uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address address
property_local_authority property_local_authority
local_authority_rent_value_check local_authority_rent_value_check

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

@ -24,6 +24,13 @@ RSpec.describe Form::Sales::Pages::AddressFallback, type: :model do
end end
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to eq([{ "manual_address_entry_selected" => true }]) expect(page.depends_on).to eq([
{ "uprn_known" => nil, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_confirmed" => 0, "uprn_selection" => "uprn_not_listed" },
{ "uprn_known" => nil, "address_options_present?" => false },
{ "uprn_known" => 0, "address_options_present?" => false },
{ "uprn_confirmed" => 0, "address_options_present?" => false },
])
end end
end end

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

@ -1,42 +0,0 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::AddressSearch, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
let(:start_date) { Time.utc(2024, 4, 1) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[uprn])
end
it "has the correct id" do
expect(page.id).to eq("address_search")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "manual_address_entry_selected" => false }])
end
it "has the correct question number" do
expect(page.question_number).to eq(15)
end
context "with 2025/26 form" do
let(:start_date) { Time.utc(2025, 4, 1) }
it "has the correct question number" do
expect(page.question_number).to eq(13)
end
end
end

4
spec/models/form/sales/pages/uprn_confirmation_spec.rb

@ -7,10 +7,6 @@ RSpec.describe Form::Sales::Pages::UprnConfirmation, type: :model do
let(:page_definition) { nil } let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) } let(:subsection) { instance_double(Form::Subsection) }
before do
allow(subsection).to receive(:form).and_return(instance_double(Form, start_year_2024_or_later?: false))
end
it "has correct subsection" do it "has correct subsection" do
expect(page.subsection).to eq(subsection) expect(page.subsection).to eq(subsection)
end end

68
spec/models/form/sales/questions/address_search_spec.rb

@ -1,68 +0,0 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::AddressSearch, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date:))) }
let(:start_date) { Time.utc(2024, 4, 1) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("uprn")
end
it "has the correct type" do
expect(question.type).to eq("address_search")
end
it "has the correct question number" do
expect(question.question_number).to eq(15)
end
context "with 2025/26 form" do
let(:start_date) { Time.utc(2025, 4, 1) }
it "has the correct question number" do
expect(question.question_number).to eq(13)
end
end
describe "get_extra_check_answer_value" do
context "when address is not present" do
let(:log) { build(:sales_log, manual_address_entry_selected: false) }
it "returns nil" do
expect(question.get_extra_check_answer_value(log)).to be_nil
end
end
context "when address search is present" do
let(:log) do
build(
:sales_log,
:completed,
address_line1: "19, Charlton Gardens",
town_or_city: "Bristol",
postcode_full: "BS10 6LU",
la: "E06000023",
uprn_known: 1,
uprn: 107,
uprn_confirmed: 1,
)
end
context "when uprn known" do
it "returns formatted value" do
expect(question.get_extra_check_answer_value(log)).to eq(
"\n\n19, Charlton Gardens\nBristol\nBS10 6LU\nBristol, City of",
)
end
end
end
end
end

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

@ -90,10 +90,9 @@ RSpec.describe Form::Sales::Questions::UprnSelection, type: :model do
context "when the log has address line 1 input only" do context "when the log has address line 1 input only" do
before do before do
allow(address_client_instance).to receive(:result).and_return(nil)
log.address_line1_input = "Address line 1" log.address_line1_input = "Address line 1"
log.postcode_full_input = nil log.postcode_full_input = nil
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do
@ -103,10 +102,9 @@ RSpec.describe Form::Sales::Questions::UprnSelection, type: :model do
context "when the log has postcode input only" do context "when the log has postcode input only" do
before do before do
allow(address_client_instance).to receive(:result).and_return(nil)
log.address_line1_input = nil log.address_line1_input = nil
log.postcode_full_input = "A1 1AA" log.postcode_full_input = "A1 1AA"
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do
@ -118,7 +116,7 @@ RSpec.describe Form::Sales::Questions::UprnSelection, type: :model do
before do before do
log.address_line1_input = "Address line 1" log.address_line1_input = "Address line 1"
log.postcode_full_input = "A1 1AA" log.postcode_full_input = "A1 1AA"
log.save!(validate: false) log.save!(valudate: false)
end end
it "has the correct input_playback" do it "has the correct input_playback" do

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

@ -55,7 +55,11 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
it "has correct pages" do it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq( expect(property_information.pages.map(&:id)).to eq(
%w[ %w[
address_search uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address address
property_local_authority property_local_authority
local_authority_buyer_1_income_max_value_check local_authority_buyer_1_income_max_value_check
@ -85,7 +89,11 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
it "has correct pages" do it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq( expect(property_information.pages.map(&:id)).to eq(
%w[ %w[
address_search uprn
uprn_confirmation
address_matcher
no_address_found
uprn_selection
address address
property_local_authority property_local_authority
local_authority_buyer_1_income_max_value_check local_authority_buyer_1_income_max_value_check

7
spec/models/sales_log_spec.rb

@ -566,7 +566,6 @@ RSpec.describe SalesLog, type: :model do
ppostcode_full: nil, ppostcode_full: nil,
prevloc: nil, prevloc: nil,
saledate: Time.zone.local(2024, 5, 2), saledate: Time.zone.local(2024, 5, 2),
manual_address_entry_selected: true,
}) })
end end
@ -618,7 +617,7 @@ RSpec.describe SalesLog, type: :model do
end end
let(:address_sales_log_25_26) do let(:address_sales_log_25_26) do
create(:sales_log, :shared_ownership_setup_complete, postcode_full: "CA10 1AA", saledate: Time.zone.local(2025, 5, 2), manual_address_entry_selected: true) create(:sales_log, :shared_ownership_setup_complete, postcode_full: "CA10 1AA", saledate: Time.zone.local(2025, 5, 2))
end end
before do before do
@ -673,11 +672,11 @@ RSpec.describe SalesLog, type: :model do
context "when saving address with LAs that have changed E-codes" do context "when saving address with LAs that have changed E-codes" do
context "when address inferred from uprn - we still get LA from postcode" do context "when address inferred from uprn - we still get LA from postcode" do
let(:address_sales_log_24_25) do let(:address_sales_log_24_25) do
create(:sales_log, :shared_ownership_setup_complete, manual_address_entry_selected: false, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2024, 5, 2)) create(:sales_log, :shared_ownership_setup_complete, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2024, 5, 2))
end end
let(:address_sales_log_25_26) do let(:address_sales_log_25_26) do
create(:sales_log, :shared_ownership_setup_complete, manual_address_entry_selected: false, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2025, 5, 2)) create(:sales_log, :shared_ownership_setup_complete, uprn_known: 1, uprn: 1, saledate: Time.zone.local(2025, 5, 2))
end end
before do before do

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

@ -136,9 +136,9 @@ RSpec.describe Validations::Sales::PropertyValidations do
context "when within the limit and only numeric" do context "when within the limit and only numeric" do
let(:record) { build(:sales_log, uprn: "123456789012") } let(:record) { build(:sales_log, uprn: "123456789012") }
it "does not add an invalid UPRN error" do it "does not add an error" do
property_validator.validate_uprn(record) property_validator.validate_uprn(record)
expect(record.errors.added?(:uprn, I18n.t("validations.sales.property_information.uprn.invalid"))).to be false expect(record.errors).not_to be_present
end end
end end
end end

2
spec/request_helper.rb

@ -20,7 +20,7 @@ module RequestHelper
body = { results: [{ DPA: { UPRN: "10033558653" } }] }.to_json body = { results: [{ DPA: { UPRN: "10033558653" } }] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?key&maxresults=10&minmatch=0.4&query=Address%20line%201,%20SW1A%201AA") WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/find?key&maxresults=10&minmatch=0.4&query=Address%20line%201,%20SW1A%201AA")
.to_return(status: 200, body:, headers: {}) .to_return(status: 200, body:, headers: {})
body = { results: [{ DPA: { "POSTCODE": "SW1A 1AA", "POST_TOWN": "London", "PO_BOX_NUMBER": "The Mall, City Of Westminster" } }] }.to_json body = { results: [{ DPA: { "POSTCODE": "SW1A 1AA", "POST_TOWN": "London" } }] }.to_json
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key&uprn=1") WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key&uprn=1")
.to_return(status: 200, body:, headers: {}) .to_return(status: 200, body:, headers: {})
WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key&uprn=10033558653") WebMock.stub_request(:get, "https://api.os.uk/search/places/v1/uprn?dataset=DPA,LPI&key&uprn=10033558653")

148
spec/requests/address_search_controller_spec.rb

@ -1,148 +0,0 @@
require "rails_helper"
RSpec.describe AddressSearchController, type: :request do
let(:user) { create(:user) }
before do
sign_in user
end
describe "#manual input" do
context "when no address data is given and user chooses to enter address manually" do
let(:sales_log) { create(:sales_log, :shared_ownership_setup_complete, manual_address_entry_selected: false, assigned_to: user) }
it "correctly sets address fields" do
sales_log.reload
expect(sales_log.manual_address_entry_selected).to eq(false)
expect(sales_log.uprn_known).to eq(nil)
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.la).to eq(nil)
get "/address-search/manual-input/sales_log/#{sales_log.id}"
sales_log.reload
expect(sales_log.manual_address_entry_selected).to eq(true)
expect(sales_log.uprn_known).to eq(0)
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.la).to eq(nil)
end
end
context "when choosing to manually input an address for a log that has an address searched value" do
let(:lettings_log) { create(:lettings_log, :completed, manual_address_entry_selected: false, assigned_to: user) }
it "correctly sets address fields" do
lettings_log.reload
expect(lettings_log.uprn_known).to eq(1)
expect(lettings_log.uprn).to eq("10033558653")
expect(lettings_log.uprn_confirmed).to eq(1)
expect(lettings_log.uprn_selection).to eq("10033558653")
expect(lettings_log.postcode_known).to eq(1)
expect(lettings_log.postcode_full).to eq("SW1A 1AA")
expect(lettings_log.address_line1).to eq("The Mall, City Of Westminster")
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq("London")
expect(lettings_log.la).to eq("E09000033")
get "/address-search/manual-input/lettings_log/#{lettings_log.id}"
lettings_log.reload
expect(lettings_log.manual_address_entry_selected).to eq(true)
expect(lettings_log.uprn_known).to eq(0)
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
end
end
describe "#search input" do
context "when no address is entered manually and choosing to search instead" do
let(:lettings_log) { create(:lettings_log, :setup_completed, manual_address_entry_selected: true, assigned_to: user) }
it "correctly sets address fields" do
lettings_log.reload
expect(lettings_log.manual_address_entry_selected).to eq(true)
expect(lettings_log.uprn_known).to eq(0)
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.la).to eq(nil)
get "/address-search/search-input/lettings_log/#{lettings_log.id}"
lettings_log.reload
expect(lettings_log.manual_address_entry_selected).to eq(false)
expect(lettings_log.uprn_known).to eq(nil)
expect(lettings_log.uprn).to eq(nil)
expect(lettings_log.uprn_confirmed).to eq(nil)
expect(lettings_log.uprn_selection).to eq(nil)
expect(lettings_log.postcode_known).to eq(nil)
expect(lettings_log.postcode_full).to eq(nil)
expect(lettings_log.address_line1).to eq(nil)
expect(lettings_log.address_line2).to eq(nil)
expect(lettings_log.town_or_city).to eq(nil)
expect(lettings_log.la).to eq(nil)
end
end
context "when choosing to search for an address for a log that has an address searched value" do
let(:sales_log) { create(:sales_log, :completed, manual_address_entry_selected: true, town_or_city: "Test Town", assigned_to: user) }
it "correctly sets address fields" do
sales_log.reload
expect(sales_log.manual_address_entry_selected).to eq(true)
expect(sales_log.uprn_known).to eq(0)
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(0)
expect(sales_log.postcode_full).to eq("SW1A 1AA")
expect(sales_log.address_line1).to eq("Address line 1")
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq("Test Town")
expect(sales_log.la).to eq("E09000033")
get "/address-search/search-input/sales_log/#{sales_log.id}"
sales_log.reload
expect(sales_log.manual_address_entry_selected).to eq(false)
expect(sales_log.uprn_known).to eq(nil)
expect(sales_log.uprn).to eq(nil)
expect(sales_log.uprn_confirmed).to eq(nil)
expect(sales_log.uprn_selection).to eq(nil)
expect(sales_log.pcodenk).to eq(nil)
expect(sales_log.postcode_full).to eq(nil)
expect(sales_log.address_line1).to eq(nil)
expect(sales_log.address_line2).to eq(nil)
expect(sales_log.town_or_city).to eq(nil)
expect(sales_log.la).to eq(nil)
end
end
end
end

10
spec/requests/duplicate_logs_controller_spec.rb

@ -77,8 +77,8 @@ RSpec.describe DuplicateLogsController, type: :request do
end end
it "displays check your answers for each log with correct questions where UPRN is given" do it "displays check your answers for each log with correct questions where UPRN is given" do
lettings_log.update!(uprn: "123", uprn_known: 1, uprn_confirmed: 1, manual_address_entry_selected: false) lettings_log.update!(uprn: "123", uprn_known: 1, uprn_confirmed: 1)
duplicate_logs[0].update!(uprn: "123", uprn_known: 1, uprn_confirmed: 1, manual_address_entry_selected: false) duplicate_logs[0].update!(uprn: "123", uprn_known: 1, uprn_confirmed: 1)
get "/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}" get "/lettings-logs/#{lettings_log.id}/duplicate-logs?original_log_id=#{lettings_log.id}"
expect(page).to have_content("Q5 - Tenancy start date", count: 3) expect(page).to have_content("Q5 - Tenancy start date", count: 3)
@ -186,9 +186,9 @@ RSpec.describe DuplicateLogsController, type: :request do
end end
it "displays check your answers for each log with correct questions when UPRN is given" do it "displays check your answers for each log with correct questions when UPRN is given" do
sales_log.update!(uprn: "123", uprn_known: 1, manual_address_entry_selected: false) sales_log.update!(uprn: "123", uprn_known: 1)
duplicate_logs[0].update!(uprn: "123", uprn_known: 1, manual_address_entry_selected: false) duplicate_logs[0].update!(uprn: "123", uprn_known: 1)
duplicate_logs[1].update!(uprn: "123", uprn_known: 1, manual_address_entry_selected: false) duplicate_logs[1].update!(uprn: "123", uprn_known: 1)
get "/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}" get "/sales-logs/#{sales_log.id}/duplicate-logs?original_log_id=#{sales_log.id}"
expect(page).to have_content("Q1 - Sale completion date", count: 3) expect(page).to have_content("Q1 - Sale completion date", count: 3)

8
spec/services/csv/sales_log_csv_service_spec.rb

@ -199,7 +199,7 @@ RSpec.describe Csv::SalesLogCsvService do
let(:fixed_time) { Time.zone.local(2024, 5, 1) } let(:fixed_time) { Time.zone.local(2024, 5, 1) }
before do before do
log.update!(nationality_all: 36, manual_address_entry_selected: false, uprn: "1", uprn_known: 1) log.update!(nationality_all: 36)
end end
it "exports the CSV with the 2024 ordering and all values correct" do it "exports the CSV with the 2024 ordering and all values correct" do
@ -286,10 +286,6 @@ RSpec.describe Csv::SalesLogCsvService do
let(:fixed_time) { Time.zone.local(2024, 5, 1) } let(:fixed_time) { Time.zone.local(2024, 5, 1) }
let(:year) { 2024 } let(:year) { 2024 }
before do
log.update!(manual_address_entry_selected: false, uprn: "1", uprn_known: 1)
end
it "exports the CSV with all values correct" do it "exports the CSV with all values correct" 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]
@ -342,7 +338,7 @@ RSpec.describe Csv::SalesLogCsvService do
let(:fixed_time) { Time.zone.local(2024, 5, 1) } let(:fixed_time) { Time.zone.local(2024, 5, 1) }
before do before do
log.update!(nationality_all: 36, manual_address_entry_selected: false, uprn: "1", uprn_known: 1) log.update!(nationality_all: 36)
end end
context "and exporting with labels" do context "and exporting with labels" do

2
spec/services/exports/lettings_log_export_service_spec.rb

@ -431,7 +431,7 @@ RSpec.describe Exports::LettingsLogExportService do
end end
context "and one lettings log is available for export" do context "and one lettings log is available for export" do
let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", ppostcode_full: "A1 1AA", nationality_all_group: 13, propcode: "123", postcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2024, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, creation_method: 2, bulk_upload_id: 1, address_line1_as_entered: "address line 1 as entered", address_line2_as_entered: "address line 2 as entered", town_or_city_as_entered: "town or city as entered", county_as_entered: "county as entered", postcode_full_as_entered: "AB1 2CD", la_as_entered: "la as entered", manual_address_entry_selected: false, uprn: "1", uprn_known: 1) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", ppostcode_full: "A1 1AA", nationality_all_group: 13, propcode: "123", postcode_full: "SE2 6RT", tenancycode: "BZ737", startdate: Time.zone.local(2024, 4, 2, 10, 36, 49), voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, creation_method: 2, bulk_upload_id: 1, address_line1_as_entered: "address line 1 as entered", address_line2_as_entered: "address line 2 as entered", town_or_city_as_entered: "town or city as entered", county_as_entered: "county as entered", postcode_full_as_entered: "AB1 2CD", la_as_entered: "la as entered") }
let(:expected_zip_filename) { "core_2024_2025_apr_mar_f0001_inc0001.zip" } let(:expected_zip_filename) { "core_2024_2025_apr_mar_f0001_inc0001.zip" }
let(:expected_data_filename) { "core_2024_2025_apr_mar_f0001_inc0001_pt001.xml" } let(:expected_data_filename) { "core_2024_2025_apr_mar_f0001_inc0001_pt001.xml" }
let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_24_25.xml", "r:UTF-8") } let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_24_25.xml", "r:UTF-8") }

5
spec/shared/shared_examples_for_derived_fields.rb

@ -25,14 +25,11 @@ RSpec.shared_examples "shared examples for derived fields" do |log_type|
end end
it "does not affect older logs with uprn_confirmed == 0" do it "does not affect older logs with uprn_confirmed == 0" do
Timecop.freeze(Time.zone.local(2023, 4, 1)) do
log = FactoryBot.build(log_type, uprn_known: 0, uprn: nil, uprn_confirmed: 0) log = FactoryBot.build(log_type, uprn_known: 0, uprn: nil, uprn_confirmed: 0)
allow(log.form).to receive(:start_year_2024_or_later?).and_return(false)
expect { log.set_derived_fields! }.to not_change(log, :uprn_known) expect { log.set_derived_fields! }.to not_change(log, :uprn_known)
.and not_change(log, :uprn) .and not_change(log, :uprn)
.and not_change(log, :uprn_confirmed) .and not_change(log, :uprn_confirmed)
end end
Timecop.return
end
end end
end end

2
spec/shared/shared_log_examples.rb

@ -81,6 +81,7 @@ RSpec.shared_examples "shared log examples" do |log_type|
expect { log.process_uprn_change! }.to change(log, :address_line1).from(nil).to("0, Building Name, Thoroughfare") expect { log.process_uprn_change! }.to change(log, :address_line1).from(nil).to("0, Building Name, Thoroughfare")
.and change(log, :town_or_city).from(nil).to("Posttown") .and change(log, :town_or_city).from(nil).to("Posttown")
.and change(log, :postcode_full).from(nil).to("POSTCODE") .and change(log, :postcode_full).from(nil).to("POSTCODE")
.and change(log, :uprn_confirmed).from(1).to(nil)
.and change(log, :county).from("county").to(nil) .and change(log, :county).from("county").to(nil)
end end
end end
@ -155,6 +156,7 @@ RSpec.shared_examples "shared log examples" do |log_type|
.and change(log, :uprn_confirmed).from(nil).to(1) .and change(log, :uprn_confirmed).from(nil).to(1)
.and change(log, :uprn).from(nil).to("UPRN") .and change(log, :uprn).from(nil).to("UPRN")
.and change(log, :uprn_known).from(nil).to(1) .and change(log, :uprn_known).from(nil).to(1)
.and change(log, :uprn_selection).from("UPRN").to(nil)
.and change(log, :county).from("county").to(nil) .and change(log, :county).from("county").to(nil)
end end
end end

Loading…
Cancel
Save