diff --git a/app/helpers/question_view_helper.rb b/app/helpers/question_view_helper.rb
index d40b3cd35..3ff84bc19 100644
--- a/app/helpers/question_view_helper.rb
+++ b/app/helpers/question_view_helper.rb
@@ -8,14 +8,16 @@ module QuestionViewHelper
def legend(question, page_header, conditional)
{
text: [question.question_number_string(conditional:), question.header.html_safe].compact.join(" - "),
- size: label_size(page_header, conditional),
+ size: label_size(page_header, conditional, question),
tag: label_tag(page_header, conditional),
}
end
private
- def label_size(page_header, conditional)
+ def label_size(page_header, conditional, question)
+ return if question.plain_label.present?
+
page_header.blank? && !conditional ? "l" : "m"
end
diff --git a/app/models/derived_variables/sales_log_variables.rb b/app/models/derived_variables/sales_log_variables.rb
index 525c12936..56d687f59 100644
--- a/app/models/derived_variables/sales_log_variables.rb
+++ b/app/models/derived_variables/sales_log_variables.rb
@@ -23,6 +23,15 @@ module DerivedVariables::SalesLogVariables
self.totadult = total_adult + total_elder
self.hhmemb = number_of_household_members
self.hhtype = household_type
+
+ if uprn_known&.zero?
+ self.uprn = nil
+ end
+
+ if uprn_confirmed&.zero?
+ self.uprn = nil
+ self.uprn_known = 0
+ end
end
private
diff --git a/app/models/form/page.rb b/app/models/form/page.rb
index ea57bac66..2ac5a716a 100644
--- a/app/models/form/page.rb
+++ b/app/models/form/page.rb
@@ -1,6 +1,7 @@
class Form::Page
attr_accessor :id, :header, :header_partial, :description, :questions, :depends_on, :title_text,
- :informative_text, :subsection, :hide_subsection_label, :next_unresolved_page_id
+ :informative_text, :subsection, :hide_subsection_label, :next_unresolved_page_id,
+ :skip_text
def initialize(id, hsh, subsection)
@id = id
@@ -15,6 +16,7 @@ class Form::Page
@informative_text = hsh["informative_text"]
@hide_subsection_label = hsh["hide_subsection_label"]
@next_unresolved_page_id = hsh["next_unresolved_page_id"]
+ @skip_text = hsh["skip_text"]
end
end
@@ -36,6 +38,8 @@ class Form::Page
questions.all? { |question| question.type == "interruption_screen" }
end
+ def skip_href(log = nil); end
+
private
def conditional_question_ids
diff --git a/app/models/form/question.rb b/app/models/form/question.rb
index 9ddacd68b..de77674e6 100644
--- a/app/models/form/question.rb
+++ b/app/models/form/question.rb
@@ -4,7 +4,7 @@ class Form::Question
:conditional_for, :readonly, :answer_options, :page, :check_answer_label,
:inferred_answers, :hidden_in_check_answers, :inferred_check_answers_value,
:guidance_partial, :prefix, :suffix, :requires_js, :fields_added, :derived,
- :check_answers_card_number, :unresolved_hint_text, :question_number
+ :check_answers_card_number, :unresolved_hint_text, :question_number, :plain_label
module GuidancePosition
TOP = 1
@@ -41,6 +41,7 @@ class Form::Question
@check_answers_card_number = hsh["check_answers_card_number"] || 0
@unresolved_hint_text = hsh["unresolved_hint_text"]
@question_number = hsh["question_number"]
+ @plain_label = hsh["plain_label"]
end
end
@@ -57,6 +58,8 @@ class Form::Question
inferred_answer_value(log) || answer_label
end
+ def notification_banner(_log = nil); end
+
def get_inferred_answers(log)
return [] unless inferred_answers
diff --git a/app/models/form/sales/pages/address.rb b/app/models/form/sales/pages/address.rb
new file mode 100644
index 000000000..dc66ca3fc
--- /dev/null
+++ b/app/models/form/sales/pages/address.rb
@@ -0,0 +1,21 @@
+class Form::Sales::Pages::Address < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "address"
+ @header = "What is the property's address?"
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::AddressLine1.new(nil, nil, self),
+ Form::Sales::Questions::AddressLine2.new(nil, nil, self),
+ Form::Sales::Questions::TownOrCity.new(nil, nil, self),
+ Form::Sales::Questions::County.new(nil, nil, self),
+ Form::Sales::Questions::PostcodeForFullAddress.new(nil, nil, self),
+ ]
+ end
+
+ def routed_to?(log, _current_user)
+ log.uprn_confirmed != 1 || log.uprn_known&.zero?
+ end
+end
diff --git a/app/models/form/sales/pages/uprn.rb b/app/models/form/sales/pages/uprn.rb
new file mode 100644
index 000000000..38b9a724c
--- /dev/null
+++ b/app/models/form/sales/pages/uprn.rb
@@ -0,0 +1,26 @@
+class Form::Sales::Pages::Uprn < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "uprn"
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::Uprn.new(nil, nil, self),
+ ]
+ end
+
+ def routed_to?(log, _current_user)
+ log.uprn_known == 1
+ end
+
+ def skip_text
+ "Enter address instead"
+ end
+
+ def skip_href(log = nil)
+ return unless log
+
+ "/#{log.model_name.param_key.dasherize}s/#{log.id}/address"
+ end
+end
diff --git a/app/models/form/sales/pages/uprn_confirmation.rb b/app/models/form/sales/pages/uprn_confirmation.rb
new file mode 100644
index 000000000..b78590d0d
--- /dev/null
+++ b/app/models/form/sales/pages/uprn_confirmation.rb
@@ -0,0 +1,17 @@
+class Form::Sales::Pages::UprnConfirmation < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "uprn_confirmation"
+ @header = "We found an address that might be this property"
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::UprnConfirmation.new(nil, nil, self),
+ ]
+ end
+
+ def routed_to?(log, _current_user)
+ log.uprn.present? && log.uprn_known == 1
+ end
+end
diff --git a/app/models/form/sales/pages/uprn_known.rb b/app/models/form/sales/pages/uprn_known.rb
new file mode 100644
index 000000000..e2cbfe63f
--- /dev/null
+++ b/app/models/form/sales/pages/uprn_known.rb
@@ -0,0 +1,12 @@
+class Form::Sales::Pages::UprnKnown < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "uprn_known"
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::UprnKnown.new(nil, nil, self),
+ ]
+ end
+end
diff --git a/app/models/form/sales/questions/address_line1.rb b/app/models/form/sales/questions/address_line1.rb
new file mode 100644
index 000000000..18b4f388f
--- /dev/null
+++ b/app/models/form/sales/questions/address_line1.rb
@@ -0,0 +1,35 @@
+class Form::Sales::Questions::AddressLine1 < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "address_line1"
+ @check_answer_label = "Address"
+ @header = "Address line 1"
+ @type = "text"
+ @plain_label = true
+ end
+
+ def hidden_in_check_answers?(log, _current_user = nil)
+ return true if log.uprn_known.nil?
+ return false if log.uprn_known&.zero?
+ return true if log.uprn_confirmed.nil? && log.uprn.present?
+ return true if log.uprn_known == 1 && log.uprn.blank?
+
+ log.uprn_confirmed == 1
+ end
+
+ def answer_label(log, _current_user = nil)
+ [
+ log.address_line1,
+ log.address_line2,
+ log.postcode_full,
+ log.town_or_city,
+ log.county,
+ ].select(&:present?).join("\n")
+ end
+
+ def get_extra_check_answer_value(log)
+ la = LocalAuthority.find_by(code: log.la)&.name
+
+ la.presence
+ end
+end
diff --git a/app/models/form/sales/questions/address_line2.rb b/app/models/form/sales/questions/address_line2.rb
new file mode 100644
index 000000000..0b4ff661c
--- /dev/null
+++ b/app/models/form/sales/questions/address_line2.rb
@@ -0,0 +1,13 @@
+class Form::Sales::Questions::AddressLine2 < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "address_line2"
+ @header = "Address line 2 (optional)"
+ @type = "text"
+ @plain_label = true
+ end
+
+ def hidden_in_check_answers?(_log = nil, _current_user = nil)
+ true
+ end
+end
diff --git a/app/models/form/sales/questions/county.rb b/app/models/form/sales/questions/county.rb
new file mode 100644
index 000000000..080ac809f
--- /dev/null
+++ b/app/models/form/sales/questions/county.rb
@@ -0,0 +1,13 @@
+class Form::Sales::Questions::County < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "county"
+ @header = "County (optional)"
+ @type = "text"
+ @plain_label = true
+ end
+
+ def hidden_in_check_answers?(_log = nil, _current_user = nil)
+ true
+ end
+end
diff --git a/app/models/form/sales/questions/postcode_for_full_address.rb b/app/models/form/sales/questions/postcode_for_full_address.rb
new file mode 100644
index 000000000..a1e6f8633
--- /dev/null
+++ b/app/models/form/sales/questions/postcode_for_full_address.rb
@@ -0,0 +1,25 @@
+class Form::Sales::Questions::PostcodeForFullAddress < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "postcode_full"
+ @header = "Postcode"
+ @type = "text"
+ @width = 5
+ @inferred_check_answers_value = [{
+ "condition" => {
+ "pcodenk" => 1,
+ },
+ "value" => "Not known",
+ }]
+ @inferred_answers = {
+ "la" => {
+ "is_la_inferred" => true,
+ },
+ }
+ @plain_label = true
+ end
+
+ def hidden_in_check_answers?(_log = nil, _current_user = nil)
+ true
+ end
+end
diff --git a/app/models/form/sales/questions/town_or_city.rb b/app/models/form/sales/questions/town_or_city.rb
new file mode 100644
index 000000000..9dde3aeb8
--- /dev/null
+++ b/app/models/form/sales/questions/town_or_city.rb
@@ -0,0 +1,13 @@
+class Form::Sales::Questions::TownOrCity < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "town_or_city"
+ @header = "Town or city"
+ @type = "text"
+ @plain_label = true
+ end
+
+ def hidden_in_check_answers?(_log = nil, _current_user = nil)
+ true
+ end
+end
diff --git a/app/models/form/sales/questions/uprn.rb b/app/models/form/sales/questions/uprn.rb
new file mode 100644
index 000000000..ef003bf0c
--- /dev/null
+++ b/app/models/form/sales/questions/uprn.rb
@@ -0,0 +1,34 @@
+class Form::Sales::Questions::Uprn < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "uprn"
+ @check_answer_label = "UPRN"
+ @header = "What is the property's UPRN"
+ @type = "text"
+ @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
+ @width = 10
+ end
+
+ def unanswered_error_message
+ I18n.t("validations.property.uprn.invalid")
+ end
+
+ def get_extra_check_answer_value(log)
+ value = [
+ log.address_line1,
+ log.address_line2,
+ log.town_or_city,
+ log.county,
+ log.postcode_full,
+ (LocalAuthority.find_by(code: log.uprn)&.name if log.uprn.present?),
+ ].select(&:present?)
+
+ return unless value.any?
+
+ "\n\n#{value.join("\n")}"
+ end
+
+ def hidden_in_check_answers?(log, _current_user = nil)
+ log.uprn_known != 1
+ end
+end
diff --git a/app/models/form/sales/questions/uprn_confirmation.rb b/app/models/form/sales/questions/uprn_confirmation.rb
new file mode 100644
index 000000000..38ad9c938
--- /dev/null
+++ b/app/models/form/sales/questions/uprn_confirmation.rb
@@ -0,0 +1,34 @@
+class Form::Sales::Questions::UprnConfirmation < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "uprn_confirmed"
+ @header = "Is this the property address?"
+ @type = "radio"
+ @answer_options = ANSWER_OPTIONS
+ @check_answer_label = "Is this the right address?"
+ end
+
+ ANSWER_OPTIONS = {
+ "1" => { "value" => "Yes" },
+ "0" => { "value" => "No, I want to enter the address manually" },
+ }.freeze
+
+ def notification_banner(log = nil)
+ return unless log&.uprn
+
+ {
+ title: "UPRN: #{log.uprn}",
+ heading: [
+ log.address_line1,
+ log.address_line2,
+ log.postcode_full,
+ log.town_or_city,
+ log.county,
+ ].select(&:present?).join("\n"),
+ }
+ end
+
+ def hidden_in_check_answers?(log, _current_user = nil)
+ log.uprn_known != 1 || log.uprn_confirmed.present?
+ end
+end
diff --git a/app/models/form/sales/questions/uprn_known.rb b/app/models/form/sales/questions/uprn_known.rb
new file mode 100644
index 000000000..45a944e4e
--- /dev/null
+++ b/app/models/form/sales/questions/uprn_known.rb
@@ -0,0 +1,21 @@
+class Form::Sales::Questions::UprnKnown < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "uprn_known"
+ @check_answer_label = "UPRN known?"
+ @header = "Do you know the sale UPRN?"
+ @type = "radio"
+ @answer_options = ANSWER_OPTIONS
+ @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.
+ You can continue without the UPRN, but it means we will need you to enter the address of the property."
+ end
+
+ ANSWER_OPTIONS = {
+ "1" => { "value" => "Yes" },
+ "0" => { "value" => "No" },
+ }.freeze
+
+ def unanswered_error_message
+ I18n.t("validations.property.uprn_known.invalid")
+ end
+end
diff --git a/app/models/form/sales/subsections/property_information.rb b/app/models/form/sales/subsections/property_information.rb
index a43607d7c..cca34a764 100644
--- a/app/models/form/sales/subsections/property_information.rb
+++ b/app/models/form/sales/subsections/property_information.rb
@@ -8,15 +8,36 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
def pages
@pages ||= [
+ uprn_questions,
Form::Sales::Pages::PropertyNumberOfBedrooms.new(nil, nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_bedrooms_value_check", nil, self),
Form::Sales::Pages::PropertyUnitType.new(nil, nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_property_type_value_check", nil, self),
Form::Sales::Pages::PropertyBuildingType.new(nil, nil, self),
- Form::Sales::Pages::Postcode.new(nil, nil, self),
- Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
+ postcode_and_la_questions,
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
Form::Sales::Pages::PropertyWheelchairAccessible.new(nil, nil, self),
- ]
+ ].flatten.compact
+ end
+
+ def uprn_questions
+ if form.start_date.year >= 2023
+ [
+ Form::Sales::Pages::UprnKnown.new(nil, nil, self),
+ Form::Sales::Pages::Uprn.new(nil, nil, self),
+ Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
+ Form::Sales::Pages::Address.new(nil, nil, self),
+ Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
+ ]
+ end
+ end
+
+ def postcode_and_la_questions
+ if form.start_date.year < 2023
+ [
+ Form::Sales::Pages::Postcode.new(nil, nil, self),
+ Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
+ ]
+ end
end
end
diff --git a/app/models/log.rb b/app/models/log.rb
index 0cb974d31..256db3612 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -31,6 +31,24 @@ class Log < ApplicationRecord
}
scope :created_by, ->(user) { where(created_by: user) }
+ def process_uprn_change!
+ if uprn.present?
+ service = UprnClient.new(uprn)
+ service.call
+
+ return errors.add(:uprn, service.error) if service.error.present?
+
+ presenter = UprnDataPresenter.new(service.result)
+
+ self.uprn_confirmed = nil
+ self.address_line1 = presenter.address_line1
+ self.address_line2 = presenter.address_line2
+ self.town_or_city = presenter.town_or_city
+ self.postcode_full = presenter.postcode
+ process_postcode_changes!
+ end
+ end
+
def collection_start_year
return @start_year if @start_year
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
index de1e1e2ba..c7fe68bca 100644
--- a/app/models/sales_log.rb
+++ b/app/models/sales_log.rb
@@ -31,6 +31,7 @@ class SalesLog < Log
before_validation :reset_location_fields!, unless: :postcode_known?
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
before_validation :set_derived_fields!
+ after_validation :process_uprn_change!, if: :should_process_uprn_change?
scope :filter_by_year, ->(year) { where(saledate: Time.zone.local(year.to_i, 4, 1)...Time.zone.local(year.to_i + 1, 4, 1)) }
scope :filter_by_purchaser_code, ->(purchid) { where("purchid ILIKE ?", "%#{purchid}%") }
@@ -311,4 +312,8 @@ class SalesLog < Log
field_value = public_send(field_name)
format_as_currency(field_value)
end
+
+ def should_process_uprn_change?
+ uprn_changed? && saledate && saledate.year >= 2023
+ end
end
diff --git a/app/views/form/_check_answers_summary_list.html.erb b/app/views/form/_check_answers_summary_list.html.erb
index bb9b1e56b..71fe9cd97 100644
--- a/app/views/form/_check_answers_summary_list.html.erb
+++ b/app/views/form/_check_answers_summary_list.html.erb
@@ -3,12 +3,19 @@
<% summary_list.row do |row| %>
<% row.key { get_question_label(question) } %>
<% row.value do %>
- <%= get_answer_label(question, @log) %>
+ <%= simple_format(
+ get_answer_label(question, @log),
+ wrapper_tag: "span",
+ class: "govuk-!-margin-right-4",
+ ) %>
<% extra_value = question.get_extra_check_answer_value(@log) %>
- <% if extra_value %>
- <%= extra_value %>
+ <% if extra_value && question.answer_label(lettings_log, current_user).present? %>
+ <%= simple_format(
+ extra_value,
+ wrapper_tag: "span",
+ class: "govuk-!-font-weight-regular app-!-colour-muted",
+ ) %>
<% end %>
-
<% question.get_inferred_answers(@log).each do |inferred_answer| %>
<%= inferred_answer %>
<% end %>
diff --git a/app/views/form/_numeric_output_question.html.erb b/app/views/form/_numeric_output_question.html.erb
index b96e7b53d..8892523aa 100644
--- a/app/views/form/_numeric_output_question.html.erb
+++ b/app/views/form/_numeric_output_question.html.erb
@@ -1,7 +1,7 @@
<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %>