diff --git a/app/components/check_answers_summary_list_card_component.html.erb b/app/components/check_answers_summary_list_card_component.html.erb
index 31c3bffac..4be77aff0 100644
--- a/app/components/check_answers_summary_list_card_component.html.erb
+++ b/app/components/check_answers_summary_list_card_component.html.erb
@@ -36,7 +36,7 @@
<% if @log.collection_period_open? %>
<% row.action(
text: question.action_text(log),
- href: question.action_href(log, question.page.id),
+ href: action_href(log, question.page.id),
visually_hidden_text: question.check_answer_label.to_s.downcase,
) %>
<% end %>
diff --git a/app/components/check_answers_summary_list_card_component.rb b/app/components/check_answers_summary_list_card_component.rb
index 62469e324..c9409462a 100644
--- a/app/components/check_answers_summary_list_card_component.rb
+++ b/app/components/check_answers_summary_list_card_component.rb
@@ -28,6 +28,10 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
"Person #{question.check_answers_card_number}"
end
+ def action_href(log, page_id, referrer = "check_answers")
+ send("#{log.model_name.param_key}_#{page_id}_path", log, referrer:)
+ end
+
private
def unanswered_value
diff --git a/app/controllers/form_controller.rb b/app/controllers/form_controller.rb
index dbc5ba490..5bd151181 100644
--- a/app/controllers/form_controller.rb
+++ b/app/controllers/form_controller.rb
@@ -11,6 +11,7 @@ class FormController < ApplicationController
mandatory_questions_with_no_response = mandatory_questions_with_no_response(responses_for_page)
if mandatory_questions_with_no_response.empty? && @log.update(responses_for_page.merge(updated_by: current_user))
+ flash[:notice] = "You have successfully updated #{@page.questions.map(&:check_answer_label).first.downcase}" if previous_interruption_screen_page_id.present?
redirect_to(successful_redirect_path)
else
mandatory_questions_with_no_response.map do |question|
@@ -45,11 +46,16 @@ class FormController < ApplicationController
end
def show_page
+ if request.params["referrer"] == "interruption_screen"
+ @interruption_page_id = URI.parse(request.headers["HTTP_REFERER"]).path.split("/").last.underscore
+ @interruption_page_referrer_type = referrer_from_query
+ end
+
if @log
page_id = request.path.split("/")[-1].underscore
@page = form.get_page(page_id)
@subsection = form.subsection_for_page(@page)
- if @page.routed_to?(@log, current_user)
+ if @page.routed_to?(@log, current_user) || is_referrer_type?("interruption_screen")
render "form/page"
else
redirect_to @log.lettings? ? lettings_log_path(@log) : sales_log_path(@log)
@@ -115,13 +121,33 @@ private
end
end
- def is_referrer_check_answers?
- referrer = request.headers["HTTP_REFERER"].presence || ""
- referrer.present? && CGI.parse(referrer.split("?")[-1]).present? && CGI.parse(referrer.split("?")[-1])["referrer"][0] == "check_answers"
+ def is_referrer_type?(referrer_type)
+ referrer_from_query == referrer_type
+ end
+
+ def referrer_from_query
+ referrer = request.headers["HTTP_REFERER"]
+ return unless referrer
+
+ query_params = URI.parse(referrer).query
+ return unless query_params
+
+ parsed_params = CGI.parse(query_params)
+ return unless parsed_params["referrer"]
+
+ parsed_params["referrer"][0]
+ end
+
+ def previous_interruption_screen_page_id
+ params[@log.model_name.param_key]["interruption_page_id"]
+ end
+
+ def previous_interruption_screen_referrer
+ params[@log.model_name.param_key]["interruption_page_referrer_type"].presence
end
def successful_redirect_path
- if is_referrer_check_answers?
+ if is_referrer_type?("check_answers")
next_page_id = form.next_page_id(@page, @log, current_user)
next_page = form.get_page(next_page_id)
previous_page = form.previous_page_id(@page, @log, current_user)
@@ -132,6 +158,10 @@ private
return send("#{@log.model_name.param_key}_#{form.subsection_for_page(@page).id}_check_answers_path", @log)
end
end
+ if previous_interruption_screen_page_id.present?
+ return send("#{@log.class.name.underscore}_#{previous_interruption_screen_page_id}_path", @log, { referrer: previous_interruption_screen_referrer }.compact)
+ end
+
redirect_path = form.next_page_redirect_path(@page, @log, current_user)
send(redirect_path, @log)
end
diff --git a/app/controllers/lettings_logs_controller.rb b/app/controllers/lettings_logs_controller.rb
index c97f5f45d..169ff42e3 100644
--- a/app/controllers/lettings_logs_controller.rb
+++ b/app/controllers/lettings_logs_controller.rb
@@ -7,11 +7,6 @@ class LettingsLogsController < LogsController
before_action :extract_bulk_upload_from_session_filters, only: [:index]
before_action :redirect_if_bulk_upload_resolved, only: [:index]
- def authenticate_scope!
- codes_only_export = codes_only_export?(params)
- head :unauthorized and return unless current_user.support? || !codes_only_export
- end
-
def index
respond_to do |format|
format.html do
@@ -86,19 +81,13 @@ class LettingsLogsController < LogsController
def download_csv
unpaginated_filtered_logs = filtered_logs(current_user.lettings_logs, search_term, @session_filters)
- codes_only = codes_only_export?(params)
-
- render "download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: email_csv_lettings_logs_path, codes_only: }
- end
- def codes_only_export?(params)
- params.require(:codes_only) == "true"
+ render "download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: email_csv_lettings_logs_path, codes_only: codes_only_export? }
end
def email_csv
all_orgs = params["organisation_select"] == "all"
- codes_only_export = params.require(:codes_only) == "true"
- EmailCsvJob.perform_later(current_user, search_term, @session_filters, all_orgs, nil, codes_only_export)
+ EmailCsvJob.perform_later(current_user, search_term, @session_filters, all_orgs, nil, codes_only_export?)
redirect_to csv_confirmation_lettings_logs_path
end
@@ -124,6 +113,10 @@ class LettingsLogsController < LogsController
private
+ def authenticate_scope!
+ head :unauthorized and return if codes_only_export? && !current_user.support?
+ end
+
def redirect_if_bulk_upload_resolved
if @bulk_upload && @bulk_upload.lettings_logs.in_progress.count.zero?
redirect_to resume_bulk_upload_lettings_result_path(@bulk_upload)
diff --git a/app/controllers/logs_controller.rb b/app/controllers/logs_controller.rb
index 603608241..12156d5aa 100644
--- a/app/controllers/logs_controller.rb
+++ b/app/controllers/logs_controller.rb
@@ -28,6 +28,10 @@ private
end
end
+ def codes_only_export?
+ params.require(:codes_only) == "true"
+ end
+
def post_create_redirect_url
raise "implement in sub class"
end
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index 17959e264..da7b9ae75 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -8,6 +8,7 @@ class MergeRequestsController < ApplicationController
confirm_telephone_number
new_organisation_name
new_organisation_address
+ new_organisation_telephone_number
merge_date
]
before_action :authenticate_user!
@@ -17,6 +18,7 @@ class MergeRequestsController < ApplicationController
def confirm_telephone_number; end
def new_organisation_name; end
def new_organisation_address; end
+ def new_organisation_telephone_number; end
def merge_date; end
def create
@@ -79,6 +81,8 @@ private
merge_date_merge_request_path(@merge_request)
when "new_organisation_name"
new_organisation_address_merge_request_path(@merge_request)
+ when "new_organisation_address"
+ new_organisation_telephone_number_merge_request_path(@merge_request)
end
end
@@ -108,6 +112,9 @@ private
:telephone_number_correct,
:new_telephone_number,
:new_organisation_name,
+ :new_organisation_address_line1,
+ :new_organisation_address_line2,
+ :new_organisation_postcode,
)
if merge_params[:requesting_organisation_id].present? && (current_user.data_coordinator? || current_user.data_provider?)
diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb
index 70943063f..b430136ae 100644
--- a/app/controllers/organisations_controller.rb
+++ b/app/controllers/organisations_controller.rb
@@ -6,8 +6,8 @@ class OrganisationsController < ApplicationController
before_action :authenticate_user!
before_action :find_resource, except: %i[index new create]
before_action :authenticate_scope!, except: [:index]
- before_action -> { session_filters(specific_org: true) }, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }, only: %i[lettings_logs sales_logs email_csv download_csv]
- before_action :set_session_filters, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }, only: %i[lettings_logs sales_logs email_csv download_csv]
+ before_action -> { session_filters(specific_org: true) }, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }, only: %i[lettings_logs sales_logs email_lettings_csv download_lettings_csv email_sales_csv download_sales_csv]
+ before_action :set_session_filters, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }, only: %i[lettings_logs sales_logs email_lettings_csv download_lettings_csv email_sales_csv download_sales_csv]
def index
redirect_to organisation_path(current_user.organisation) unless current_user.support?
@@ -99,23 +99,23 @@ class OrganisationsController < ApplicationController
@pagy, @logs = pagy(unpaginated_filtered_logs)
@searched = search_term.presence
@total_count = organisation_logs.size
+ @log_type = :lettings
render "logs", layout: "application"
end
end
end
- def download_csv
+ def download_lettings_csv
organisation_logs = LettingsLog.visible.where(owning_organisation_id: @organisation.id)
unpaginated_filtered_logs = filtered_logs(organisation_logs, search_term, @session_filters)
codes_only = params.require(:codes_only) == "true"
- render "logs/download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: logs_email_csv_organisation_path, codes_only: }
+ render "logs/download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: lettings_logs_email_csv_organisation_path, codes_only: }
end
- def email_csv
- codes_only_export = params.require(:codes_only) == "true"
- EmailCsvJob.perform_later(current_user, search_term, @session_filters, false, @organisation, codes_only_export)
- redirect_to logs_csv_confirmation_organisation_path
+ def email_lettings_csv
+ EmailCsvJob.perform_later(current_user, search_term, @session_filters, false, @organisation, codes_only_export?)
+ redirect_to lettings_logs_csv_confirmation_organisation_path
end
def sales_logs
@@ -128,6 +128,7 @@ class OrganisationsController < ApplicationController
@pagy, @logs = pagy(unpaginated_filtered_logs)
@searched = search_term.presence
@total_count = organisation_logs.size
+ @log_type = :sales
render "logs", layout: "application"
end
@@ -137,6 +138,19 @@ class OrganisationsController < ApplicationController
end
end
+ def download_sales_csv
+ organisation_logs = SalesLog.visible.where(owning_organisation_id: @organisation.id)
+ unpaginated_filtered_logs = filtered_logs(organisation_logs, search_term, @session_filters)
+ codes_only = params.require(:codes_only) == "true"
+
+ render "logs/download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: sales_logs_email_csv_organisation_path, codes_only: }
+ end
+
+ def email_sales_csv
+ EmailCsvJob.perform_later(current_user, search_term, @session_filters, false, @organisation, codes_only_export?, "sales")
+ redirect_to sales_logs_csv_confirmation_organisation_path
+ end
+
def merge_request
@merge_request = MergeRequest.new
end
@@ -147,12 +161,16 @@ private
params.require(:organisation).permit(:name, :address_line1, :address_line2, :postcode, :phone, :holds_own_stock, :provider_type, :housing_registration_no)
end
+ def codes_only_export?
+ params.require(:codes_only) == "true"
+ end
+
def search_term
params["search"]
end
def authenticate_scope!
- if %w[create new lettings_logs download_csv email_csv].include? action_name
+ if %w[create new lettings_logs sales_logs download_lettings_csv email_lettings_csv email_sales_csv download_sales_csv].include? action_name
head :unauthorized and return unless current_user.support?
elsif current_user.organisation != @organisation && !current_user.support?
render_not_found
diff --git a/app/controllers/sales_logs_controller.rb b/app/controllers/sales_logs_controller.rb
index 155f606ab..5e9777a3c 100644
--- a/app/controllers/sales_logs_controller.rb
+++ b/app/controllers/sales_logs_controller.rb
@@ -1,6 +1,7 @@
class SalesLogsController < LogsController
before_action :session_filters, if: :current_user, only: %i[index email_csv download_csv]
before_action :set_session_filters, if: :current_user, only: %i[index email_csv download_csv]
+ before_action :authenticate_scope!, only: %i[download_csv email_csv]
def create
super { SalesLog.new(log_params) }
@@ -36,6 +37,20 @@ class SalesLogsController < LogsController
end
end
+ def download_csv
+ unpaginated_filtered_logs = filtered_logs(current_user.sales_logs, search_term, @session_filters)
+
+ render "download_csv", locals: { search_term:, count: unpaginated_filtered_logs.size, post_path: email_csv_sales_logs_path, codes_only: codes_only_export? }
+ end
+
+ def email_csv
+ all_orgs = params["organisation_select"] == "all"
+ EmailCsvJob.perform_later(current_user, search_term, @session_filters, all_orgs, nil, codes_only_export?, "sales")
+ redirect_to csv_confirmation_sales_logs_path
+ end
+
+ def csv_confirmation; end
+
def post_create_redirect_url(log)
sales_log_url(log)
end
@@ -43,4 +58,10 @@ class SalesLogsController < LogsController
def permitted_log_params
params.require(:sales_log).permit(SalesLog.editable_fields)
end
+
+private
+
+ def authenticate_scope!
+ head :unauthorized and return if codes_only_export? && !current_user.support?
+ end
end
diff --git a/app/helpers/form_page_helper.rb b/app/helpers/form_page_helper.rb
new file mode 100644
index 000000000..e12d7fbb7
--- /dev/null
+++ b/app/helpers/form_page_helper.rb
@@ -0,0 +1,5 @@
+module FormPageHelper
+ def action_href(log, page_id, referrer = "check_answers")
+ send("#{log.model_name.param_key}_#{page_id}_path", log, referrer:)
+ end
+end
diff --git a/app/helpers/interruption_screen_helper.rb b/app/helpers/interruption_screen_helper.rb
index 939f70bb2..fc75f6f59 100644
--- a/app/helpers/interruption_screen_helper.rb
+++ b/app/helpers/interruption_screen_helper.rb
@@ -29,6 +29,10 @@ module InterruptionScreenHelper
I18n.t(title_text["translation"], **translation_params).to_s
end
+ def soft_validation_affected_questions(question, log)
+ question.page.interruption_screen_question_ids.map { |question_id| log.form.get_question(question_id, log) }.compact
+ end
+
private
def get_value_from_argument(log, argument)
diff --git a/app/helpers/logs_helper.rb b/app/helpers/logs_helper.rb
index 0e988fda9..ca6fa838f 100644
--- a/app/helpers/logs_helper.rb
+++ b/app/helpers/logs_helper.rb
@@ -1,10 +1,8 @@
module LogsHelper
def log_type_for_controller(controller)
- case controller.class.to_s
- when "LettingsLogsController"
- "lettings"
- when "SalesLogsController"
- "sales"
+ case controller.class.name
+ when "LettingsLogsController" then "lettings"
+ when "SalesLogsController" then "sales"
else
raise "Log type not found for #{controller.class}"
end
@@ -12,10 +10,8 @@ module LogsHelper
def bulk_upload_path_for_controller(controller, id:)
case log_type_for_controller(controller)
- when "lettings"
- bulk_upload_lettings_log_path(id:)
- when "sales"
- bulk_upload_sales_log_path(id:)
+ when "lettings" then bulk_upload_lettings_log_path(id:)
+ when "sales" then bulk_upload_sales_log_path(id:)
end
end
@@ -26,16 +22,29 @@ module LogsHelper
def search_label_for_controller(controller)
case log_type_for_controller(controller)
- when "lettings"
- "Search by log ID, tenant code, property reference or postcode"
- when "sales"
- "Search by log ID, purchaser code or postcode"
+ when "lettings" then "Search by log ID, tenant code, property reference or postcode"
+ when "sales" then "Search by log ID, purchaser code or postcode"
end
end
- def csv_download_url_for_controller(controller_type:, search:, codes_only:)
- case log_type_for_controller(controller_type)
+ def csv_download_url_for_controller(controller:, search:, codes_only:)
+ case log_type_for_controller(controller)
when "lettings" then csv_download_lettings_logs_path(search:, codes_only:)
+ when "sales" then csv_download_sales_logs_path(search:, codes_only:)
+ end
+ end
+
+ def logs_path_for_controller(controller)
+ case log_type_for_controller(controller)
+ when "lettings" then lettings_logs_path
+ when "sales" then sales_logs_path
+ end
+ end
+
+ def csv_download_url_by_log_type(log_type, organisation, search:, codes_only:)
+ case log_type
+ when :lettings then lettings_logs_csv_download_organisation_path(organisation, search:, codes_only:)
+ when :sales then sales_logs_csv_download_organisation_path(organisation, search:, codes_only:)
end
end
diff --git a/app/jobs/email_csv_job.rb b/app/jobs/email_csv_job.rb
index f313c87b8..63acdbaaa 100644
--- a/app/jobs/email_csv_job.rb
+++ b/app/jobs/email_csv_job.rb
@@ -5,14 +5,23 @@ class EmailCsvJob < ApplicationJob
EXPIRATION_TIME = 3.hours.to_i
- def perform(user, search_term = nil, filters = {}, all_orgs = false, organisation = nil, codes_only_export = false) # rubocop:disable Style/OptionalBooleanParameter - sidekiq can't serialise named params
- unfiltered_logs = organisation.present? && user.support? ? LettingsLog.visible.where(owning_organisation_id: organisation.id) : user.lettings_logs.visible
- filtered_logs = FilterService.filter_logs(unfiltered_logs, search_term, filters, all_orgs, user)
+ def perform(user, search_term = nil, filters = {}, all_orgs = false, organisation = nil, codes_only_export = false, log_type = "lettings") # rubocop:disable Style/OptionalBooleanParameter - sidekiq can't serialise named params
+ case log_type
+ when "lettings"
+ unfiltered_logs = organisation.present? && user.support? ? LettingsLog.visible.where(owning_organisation_id: organisation.id) : user.lettings_logs.visible
+ filtered_logs = FilterService.filter_logs(unfiltered_logs, search_term, filters, all_orgs, user)
+ csv_string = filtered_logs.to_csv(user, codes_only_export:)
+ when "sales"
+ unfiltered_logs = organisation.present? && user.support? ? SalesLog.visible.where(owning_organisation_id: organisation.id) : user.sales_logs.visible
+ filtered_logs = FilterService.filter_logs(unfiltered_logs, search_term, filters, all_orgs, user)
+ export_type = codes_only_export ? "codes" : "labels"
+ csv_string = Csv::SalesLogCsvService.new(export_type:).prepare_csv(filtered_logs)
+ end
- filename = organisation.present? ? "logs-#{organisation.name}-#{Time.zone.now}.csv" : "logs-#{Time.zone.now}.csv"
+ filename = "#{[log_type, 'logs', organisation&.name, Time.zone.now].compact.join('-')}.csv"
storage_service = Storage::S3Service.new(Configuration::EnvConfigurationService.new, ENV["CSV_DOWNLOAD_PAAS_INSTANCE"])
- storage_service.write_file(filename, BYTE_ORDER_MARK + filtered_logs.to_csv(user, codes_only_export:))
+ storage_service.write_file(filename, BYTE_ORDER_MARK + csv_string)
url = storage_service.get_presigned_url(filename, EXPIRATION_TIME)
diff --git a/app/models/derived_variables/lettings_log_variables.rb b/app/models/derived_variables/lettings_log_variables.rb
index aae49422d..937dd7c2e 100644
--- a/app/models/derived_variables/lettings_log_variables.rb
+++ b/app/models/derived_variables/lettings_log_variables.rb
@@ -1,4 +1,6 @@
module DerivedVariables::LettingsLogVariables
+ include DerivedVariables::SharedLogic
+
# renttype and unitletas values are different for intermediate rent (3 for renttype and 4 for unitletas)
RENT_TYPE_MAPPING = {
0 => 1, # "Social Rent" => "Social Rent"
@@ -35,10 +37,12 @@ module DerivedVariables::LettingsLogVariables
end
def set_derived_fields!
+ clear_inapplicable_derived_values!
+ set_encoded_derived_values!(DEPENDENCIES)
+
if rsnvac.present?
self.newprop = has_first_let_vacancy_reason? ? 1 : 2
end
- self.incref = 1 if net_income_refused?
self.renttype = RENT_TYPE_MAPPING[rent_type]
self.lettype = get_lettype
self.totchild = get_totchild
@@ -69,15 +73,9 @@ module DerivedVariables::LettingsLogVariables
self.nocharge = household_charge&.zero? ? 1 : 0
if is_renewal?
self.underoccupation_benefitcap = 2 if collection_start_year == 2021
- self.referral = 1
- self.waityear = 2
- self.offered = 0
self.voiddate = startdate
- self.first_time_property_let_as_social_housing = 0
- self.rsnvac = 14
self.unitletas = form.start_date.year >= 2023 ? UNITLETAS_MAPPING_23_24[rent_type] : UNITLETAS_MAPPING[rent_type]
if is_general_needs?
- # fixed term
self.prevten = 32 if managing_organisation&.provider_type == "PRP"
self.prevten = 30 if managing_organisation&.provider_type == "LA"
end
@@ -109,6 +107,49 @@ module DerivedVariables::LettingsLogVariables
private
+ DEPENDENCIES = [
+ {
+ conditions: {
+ renewal: 1,
+ },
+ derived_values: {
+ referral: 1,
+ waityear: 2,
+ offered: 0,
+ rsnvac: 14,
+ first_time_property_let_as_social_housing: 0,
+ },
+ },
+ {
+ conditions: {
+ net_income_known: 2,
+ },
+ derived_values: {
+ incref: 1,
+ },
+ },
+ ].freeze
+
+ def clear_inapplicable_derived_values!
+ reset_invalidated_derived_values!(DEPENDENCIES)
+ if (startdate_changed? || renewal_changed?) && (renewal_was == 1 && startdate_was&.between?(Time.zone.local(2021, 4, 1), Time.zone.local(2022, 3, 31)))
+ self.underoccupation_benefitcap = nil
+ end
+ if renewal_changed? && renewal_was == 1
+ self.voiddate = nil
+ self.unitletas = nil
+ end
+ if %w[PRP LA].include?(managing_organisation&.provider_type) &&
+ (needstype_changed? || renewal_changed?) &&
+ needstype_was == 1 && renewal_was == 1
+ self.prevten = nil
+ end
+ if needstype_changed? && needstype_was == 2
+ self.wchair = nil
+ self.location_id = nil
+ end
+ end
+
def get_totelder
ages = [age1, age2, age3, age4, age5, age6, age7, age8]
ages.count { |x| !x.nil? && x >= 60 }
diff --git a/app/models/derived_variables/sales_log_variables.rb b/app/models/derived_variables/sales_log_variables.rb
index 9151a72f5..308a62bb8 100644
--- a/app/models/derived_variables/sales_log_variables.rb
+++ b/app/models/derived_variables/sales_log_variables.rb
@@ -1,6 +1,8 @@
module DerivedVariables::SalesLogVariables
+ include DerivedVariables::SharedLogic
+
def set_derived_fields!
- reset_invalidated_derived_values!
+ reset_invalidated_derived_values!(DEPENDENCIES)
self.ethnic = 17 if ethnic_refused?
self.mscharge = nil if no_monthly_leasehold_charges?
@@ -15,7 +17,8 @@ module DerivedVariables::SalesLogVariables
self.hoyear = hodate.year
end
self.deposit = value if outright_sale? && mortgage_not_used?
- self.pcode1, self.pcode2 = postcode_full.split(" ") if postcode_full.present?
+ self.pcode1, self.pcode2 = postcode_full.split if postcode_full.present?
+ self.ppostc1, self.ppostc2 = ppostcode_full.split if ppostcode_full.present?
self.totchild = total_child
self.totadult = total_adult + total_elder
self.hhmemb = number_of_household_members
@@ -30,7 +33,7 @@ module DerivedVariables::SalesLogVariables
self.uprn_known = 0
end
- set_encoded_derived_values!
+ set_encoded_derived_values!(DEPENDENCIES)
end
private
@@ -73,30 +76,6 @@ private
},
].freeze
- def reset_invalidated_derived_values!
- DEPENDENCIES.each do |dependency|
- any_conditions_changed = dependency[:conditions].any? { |attribute, _value| send("#{attribute}_changed?") }
- next unless any_conditions_changed
-
- previously_in_derived_state = dependency[:conditions].all? { |attribute, value| send("#{attribute}_was") == value }
- next unless previously_in_derived_state
-
- dependency[:derived_values].each do |derived_attribute, _derived_value|
- Rails.logger.debug("Cleared derived #{derived_attribute} value")
- send("#{derived_attribute}=", nil)
- end
- end
- end
-
- def set_encoded_derived_values!
- DEPENDENCIES.each do |dependency|
- derivation_applies = dependency[:conditions].all? { |attribute, value| send(attribute) == value }
- if derivation_applies
- dependency[:derived_values].each { |attribute, value| send("#{attribute}=", value) }
- end
- end
- end
-
def number_of_household_members
return unless hholdcount.present? && jointpur.present?
diff --git a/app/models/derived_variables/shared_logic.rb b/app/models/derived_variables/shared_logic.rb
new file mode 100644
index 000000000..c326cb8c9
--- /dev/null
+++ b/app/models/derived_variables/shared_logic.rb
@@ -0,0 +1,27 @@
+module DerivedVariables::SharedLogic
+private
+
+ def reset_invalidated_derived_values!(dependencies)
+ dependencies.each do |dependency|
+ any_conditions_changed = dependency[:conditions].any? { |attribute, _value| send("#{attribute}_changed?") }
+ next unless any_conditions_changed
+
+ previously_in_derived_state = dependency[:conditions].all? { |attribute, value| send("#{attribute}_was") == value }
+ next unless previously_in_derived_state
+
+ dependency[:derived_values].each do |derived_attribute, _derived_value|
+ Rails.logger.debug("Cleared derived #{derived_attribute} value")
+ send("#{derived_attribute}=", nil)
+ end
+ end
+ end
+
+ def set_encoded_derived_values!(dependencies)
+ dependencies.each do |dependency|
+ derivation_applies = dependency[:conditions].all? { |attribute, value| send(attribute) == value }
+ if derivation_applies
+ dependency[:derived_values].each { |attribute, value| send("#{attribute}=", value) }
+ end
+ end
+ end
+end
diff --git a/app/models/form/lettings/pages/care_home_charges_value_check.rb b/app/models/form/lettings/pages/care_home_charges_value_check.rb
index 32468e364..2cf253bf6 100644
--- a/app/models/form/lettings/pages/care_home_charges_value_check.rb
+++ b/app/models/form/lettings/pages/care_home_charges_value_check.rb
@@ -12,4 +12,8 @@ class Form::Lettings::Pages::CareHomeChargesValueCheck < ::Form::Page
def questions
@questions ||= [Form::Lettings::Questions::CareHomeChargesValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[chcharge is_carehome]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_age_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_age_value_check.rb
index b143023ca..a7046e88b 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_age_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_age_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadAgeValu
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check.rb
index fa85ee7cb..b4915a92b 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadHhmembV
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_value_check.rb
index 7eeca3bbd..291fb92b6 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_lead_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadValueCh
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_age_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_age_value_check.rb
index 29109f7ba..419bcc81b 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_age_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_age_value_check.rb
@@ -33,4 +33,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdPersonAgeVa
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_value_check.rb
index b0084d723..75b1b0d35 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_person_value_check.rb
@@ -33,4 +33,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdPersonValue
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_value_check.rb b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_value_check.rb
index 9a4d93de1..9355c24e7 100644
--- a/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_value_check.rb
+++ b/app/models/form/lettings/pages/females_in_soft_age_range_in_pregnant_household_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdValueCheck
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8 age1 age2 age3 age4 age5 age6 age7 age8]
+ end
end
diff --git a/app/models/form/lettings/pages/lead_tenant_over_retirement_value_check.rb b/app/models/form/lettings/pages/lead_tenant_over_retirement_value_check.rb
index 6990bf71e..ca6183f3c 100644
--- a/app/models/form/lettings/pages/lead_tenant_over_retirement_value_check.rb
+++ b/app/models/form/lettings/pages/lead_tenant_over_retirement_value_check.rb
@@ -27,6 +27,10 @@ class Form::Lettings::Pages::LeadTenantOverRetirementValueCheck < ::Form::Page
end
def questions
- @questions ||= [Form::Lettings::Questions::RetirementValueCheck.new(nil, nil, self)]
+ @questions ||= [Form::Lettings::Questions::RetirementValueCheck.new(nil, nil, self, person_index: 1)]
+ end
+
+ def interruption_screen_question_ids
+ %w[ecstat1 sex1 age1]
end
end
diff --git a/app/models/form/lettings/pages/lead_tenant_under_retirement_value_check.rb b/app/models/form/lettings/pages/lead_tenant_under_retirement_value_check.rb
index 34da02205..b7ab02900 100644
--- a/app/models/form/lettings/pages/lead_tenant_under_retirement_value_check.rb
+++ b/app/models/form/lettings/pages/lead_tenant_under_retirement_value_check.rb
@@ -7,26 +7,20 @@ class Form::Lettings::Pages::LeadTenantUnderRetirementValueCheck < ::Form::Page
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_1",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- }
- @informative_text = {
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- { "key" => "plural_gender_for_person_1", "label" => false, "i18n_template" => "gender" },
- {
- "key" => "retirement_age_for_person_1",
- "label" => false,
+ "key" => "age1",
+ "label" => true,
"i18n_template" => "age",
},
],
}
+ @informative_text = {}
end
def questions
- @questions ||= [Form::Lettings::Questions::NoRetirementValueCheck.new(nil, nil, self)]
+ @questions ||= [Form::Lettings::Questions::NoRetirementValueCheck.new(nil, nil, self, person_index: 1)]
+ end
+
+ def interruption_screen_question_ids
+ %w[ecstat1 age1]
end
end
diff --git a/app/models/form/lettings/pages/max_rent_value_check.rb b/app/models/form/lettings/pages/max_rent_value_check.rb
index 956e07f44..dcda23c43 100644
--- a/app/models/form/lettings/pages/max_rent_value_check.rb
+++ b/app/models/form/lettings/pages/max_rent_value_check.rb
@@ -28,4 +28,8 @@ class Form::Lettings::Pages::MaxRentValueCheck < ::Form::Page
def questions
@questions ||= [Form::Lettings::Questions::RentValueCheck.new(nil, nil, self, check_answers_card_number: @check_answers_card_number)]
end
+
+ def interruption_screen_question_ids
+ %w[brent startdate la beds rent_type needstype]
+ end
end
diff --git a/app/models/form/lettings/pages/min_rent_value_check.rb b/app/models/form/lettings/pages/min_rent_value_check.rb
index 86b53951c..245158a08 100644
--- a/app/models/form/lettings/pages/min_rent_value_check.rb
+++ b/app/models/form/lettings/pages/min_rent_value_check.rb
@@ -24,4 +24,8 @@ class Form::Lettings::Pages::MinRentValueCheck < ::Form::Page
def questions
@questions ||= [Form::Lettings::Questions::RentValueCheck.new(nil, nil, self, check_answers_card_number: @check_answers_card_number)]
end
+
+ def interruption_screen_question_ids
+ %w[brent startdate la beds rent_type needstype]
+ end
end
diff --git a/app/models/form/lettings/pages/net_income_value_check.rb b/app/models/form/lettings/pages/net_income_value_check.rb
index 0569b86e9..f5ffd78c1 100644
--- a/app/models/form/lettings/pages/net_income_value_check.rb
+++ b/app/models/form/lettings/pages/net_income_value_check.rb
@@ -3,14 +3,13 @@ class Form::Lettings::Pages::NetIncomeValueCheck < ::Form::Page
super
@id = "net_income_value_check"
@depends_on = [{ "net_income_soft_validation_triggered?" => true }]
- @title_text = { "translation" => "soft_validations.net_income.title_text" }
- @informative_text = {
- "translation" => "soft_validations.net_income.hint_text",
+ @title_text = {
+ "translation" => "soft_validations.net_income.title_text",
"arguments" => [
{
- "key" => "field_formatted_as_currency",
- "arguments_for_key" => "ecstat1",
- "i18n_template" => "ecstat1",
+ "key" => "incfreq",
+ "label" => true,
+ "i18n_template" => "incfreq",
},
{
"key" => "field_formatted_as_currency",
@@ -19,9 +18,24 @@ class Form::Lettings::Pages::NetIncomeValueCheck < ::Form::Page
},
],
}
+
+ @informative_text = {
+ "translation" => "soft_validations.net_income.hint_text",
+ "arguments" => [
+ {
+ "key" => "net_income_higher_or_lower_text",
+ "label" => false,
+ "i18n_template" => "net_income_higher_or_lower_text",
+ },
+ ],
+ }
end
def questions
@questions ||= [Form::Lettings::Questions::NetIncomeValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[incfreq earnings ecstat1]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_lead_age_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_lead_age_value_check.rb
index d837ac0cb..570a1bc5a 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_lead_age_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_lead_age_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadAgeValueCheck < ::For
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_lead_hhmemb_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_lead_hhmemb_value_check.rb
index 806153074..ea90bd6ff 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_lead_hhmemb_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_lead_hhmemb_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadHhmembValueCheck < ::
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_lead_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_lead_value_check.rb
index 44217e7fa..4d0fc0c2c 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_lead_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_lead_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadValueCheck < ::Form::
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_person_age_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_person_age_value_check.rb
index be833d9dc..a58c9bc60 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_person_age_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_person_age_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdPersonAgeValueCheck < ::F
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_person_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_person_value_check.rb
index e81e5b339..ede6e61b4 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_person_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_person_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdPersonValueCheck < ::Form
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/no_females_pregnant_household_value_check.rb b/app/models/form/lettings/pages/no_females_pregnant_household_value_check.rb
index 2438ef0b9..23aaec180 100644
--- a/app/models/form/lettings/pages/no_females_pregnant_household_value_check.rb
+++ b/app/models/form/lettings/pages/no_females_pregnant_household_value_check.rb
@@ -16,4 +16,8 @@ class Form::Lettings::Pages::NoFemalesPregnantHouseholdValueCheck < ::Form::Page
def questions
@questions ||= [Form::Lettings::Questions::PregnancyValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[preg_occ sex1 sex2 sex3 sex4 sex5 sex6 sex7 sex8]
+ end
end
diff --git a/app/models/form/lettings/pages/person_over_retirement_value_check.rb b/app/models/form/lettings/pages/person_over_retirement_value_check.rb
index 3de5246e6..b13a52ed5 100644
--- a/app/models/form/lettings/pages/person_over_retirement_value_check.rb
+++ b/app/models/form/lettings/pages/person_over_retirement_value_check.rb
@@ -28,9 +28,14 @@ class Form::Lettings::Pages::PersonOverRetirementValueCheck < ::Form::Page
},
],
}
+ @person_index = person_index
end
def questions
- @questions ||= [Form::Lettings::Questions::RetirementValueCheck.new(nil, nil, self)]
+ @questions ||= [Form::Lettings::Questions::RetirementValueCheck.new(nil, nil, self, person_index: @person_index)]
+ end
+
+ def interruption_screen_question_ids
+ ["ecstat#{@person_index}", "sex#{@person_index}", "age#{@person_index}"]
end
end
diff --git a/app/models/form/lettings/pages/person_under_retirement_value_check.rb b/app/models/form/lettings/pages/person_under_retirement_value_check.rb
index a1b9253fd..9f7540f56 100644
--- a/app/models/form/lettings/pages/person_under_retirement_value_check.rb
+++ b/app/models/form/lettings/pages/person_under_retirement_value_check.rb
@@ -7,30 +7,21 @@ class Form::Lettings::Pages::PersonUnderRetirementValueCheck < ::Form::Page
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_#{person_index}",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- }
- @informative_text = {
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_#{person_index}",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_#{person_index}",
- "label" => false,
+ "key" => "age#{person_index}",
+ "label" => true,
"i18n_template" => "age",
},
],
}
+ @informative_text = {}
+ @person_index = person_index
end
def questions
- @questions ||= [Form::Lettings::Questions::NoRetirementValueCheck.new(nil, nil, self)]
+ @questions ||= [Form::Lettings::Questions::NoRetirementValueCheck.new(nil, nil, self, person_index: @person_index)]
+ end
+
+ def interruption_screen_question_ids
+ ["ecstat#{@person_index}", "age#{@person_index}"]
end
end
diff --git a/app/models/form/lettings/pages/property_major_repairs_value_check.rb b/app/models/form/lettings/pages/property_major_repairs_value_check.rb
index 21e2b2b51..08672aff6 100644
--- a/app/models/form/lettings/pages/property_major_repairs_value_check.rb
+++ b/app/models/form/lettings/pages/property_major_repairs_value_check.rb
@@ -4,10 +4,17 @@ class Form::Lettings::Pages::PropertyMajorRepairsValueCheck < ::Form::Page
@id = "property_major_repairs_value_check"
@depends_on = [{ "major_repairs_date_in_soft_range?" => true }]
@title_text = { "translation" => "soft_validations.major_repairs_date.title_text" }
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.major_repairs_date.hint_text",
+ "arguments" => [],
+ }
end
def questions
@questions ||= [Form::Lettings::Questions::MajorRepairsDateValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[mrcdate startdate]
+ end
end
diff --git a/app/models/form/lettings/pages/void_date_value_check.rb b/app/models/form/lettings/pages/void_date_value_check.rb
index d717b38fe..6ebd3a175 100644
--- a/app/models/form/lettings/pages/void_date_value_check.rb
+++ b/app/models/form/lettings/pages/void_date_value_check.rb
@@ -4,10 +4,17 @@ class Form::Lettings::Pages::VoidDateValueCheck < ::Form::Page
@id = "void_date_value_check"
@depends_on = [{ "voiddate_in_soft_range?" => true }]
@title_text = { "translation" => "soft_validations.void_date.title_text" }
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.void_date.hint_text",
+ "arguments" => [],
+ }
end
def questions
@questions ||= [Form::Lettings::Questions::VoidDateValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[voiddate startdate]
+ end
end
diff --git a/app/models/form/lettings/questions/no_retirement_value_check.rb b/app/models/form/lettings/questions/no_retirement_value_check.rb
index 43fe68e10..0e2033c61 100644
--- a/app/models/form/lettings/questions/no_retirement_value_check.rb
+++ b/app/models/form/lettings/questions/no_retirement_value_check.rb
@@ -1,11 +1,11 @@
class Form::Lettings::Questions::NoRetirementValueCheck < ::Form::Question
- def initialize(id, hsh, page)
- super
+ def initialize(id, hsh, page, person_index:)
+ super(id, hsh, page)
@id = "retirement_value_check"
@check_answer_label = "Retirement confirmation"
@header = "Are you sure this person is retired?"
@type = "interruption_screen"
- @check_answers_card_number = 8
+ @check_answers_card_number = person_index
@answer_options = ANSWER_OPTIONS
@hidden_in_check_answers = {
"depends_on" => [
diff --git a/app/models/form/lettings/questions/retirement_value_check.rb b/app/models/form/lettings/questions/retirement_value_check.rb
index 784693616..63a286d61 100644
--- a/app/models/form/lettings/questions/retirement_value_check.rb
+++ b/app/models/form/lettings/questions/retirement_value_check.rb
@@ -1,11 +1,11 @@
class Form::Lettings::Questions::RetirementValueCheck < ::Form::Question
- def initialize(id, hsh, page)
- super
+ def initialize(id, hsh, page, person_index:)
+ super(id, hsh, page)
@id = "retirement_value_check"
@check_answer_label = "Retirement confirmation"
@header = "Are you sure this person isn’t retired?"
@type = "interruption_screen"
- @check_answers_card_number = 8
+ @check_answers_card_number = person_index
@answer_options = ANSWER_OPTIONS
@hidden_in_check_answers = {
"depends_on" => [
diff --git a/app/models/form/page.rb b/app/models/form/page.rb
index 2ac5a716a..498c69d7b 100644
--- a/app/models/form/page.rb
+++ b/app/models/form/page.rb
@@ -1,7 +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,
- :skip_text
+ :skip_text, :interruption_screen_question_ids
def initialize(id, hsh, subsection)
@id = id
@@ -17,6 +17,7 @@ class Form::Page
@hide_subsection_label = hsh["hide_subsection_label"]
@next_unresolved_page_id = hsh["next_unresolved_page_id"]
@skip_text = hsh["skip_text"]
+ @interruption_screen_question_ids = hsh["interruption_screen_question_ids"] || []
end
end
diff --git a/app/models/form/question.rb b/app/models/form/question.rb
index d4b7c9d76..82d3a09b5 100644
--- a/app/models/form/question.rb
+++ b/app/models/form/question.rb
@@ -120,10 +120,6 @@ class Form::Question
end
end
- def action_href(log, page_id)
- "/#{log.model_name.param_key.dasherize}s/#{log.id}/#{page_id.to_s.dasherize}?referrer=check_answers"
- end
-
def unanswered?(log)
return answer_options.keys.none? { |key| value_is_yes?(log[key]) } if type == "checkbox"
diff --git a/app/models/form/sales/pages/about_price_value_check.rb b/app/models/form/sales/pages/about_price_value_check.rb
index 94df02243..3ab7520aa 100644
--- a/app/models/form/sales/pages/about_price_value_check.rb
+++ b/app/models/form/sales/pages/about_price_value_check.rb
@@ -25,8 +25,8 @@ class Form::Sales::Pages::AboutPriceValueCheck < ::Form::Page
"i18n_template" => "soft_min_or_soft_max",
},
{
- "key" => "purchase_price_min_or_max_text",
- "i18n_template" => "min_or_max",
+ "key" => "purchase_price_higher_or_lower_text",
+ "i18n_template" => "higher_or_lower",
},
],
}
@@ -37,4 +37,8 @@ class Form::Sales::Pages::AboutPriceValueCheck < ::Form::Page
Form::Sales::Questions::AboutPriceValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[value beds la]
+ end
end
diff --git a/app/models/form/sales/pages/buyer1_income_value_check.rb b/app/models/form/sales/pages/buyer1_income_value_check.rb
index 48d8f5fff..4394258e6 100644
--- a/app/models/form/sales/pages/buyer1_income_value_check.rb
+++ b/app/models/form/sales/pages/buyer1_income_value_check.rb
@@ -7,7 +7,7 @@ class Form::Sales::Pages::Buyer1IncomeValueCheck < ::Form::Page
},
]
@title_text = {
- "translation" => "soft_validations.income.under_soft_min_for_economic_status",
+ "translation" => "soft_validations.income.under_soft_min_for_economic_status.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@@ -21,7 +21,10 @@ class Form::Sales::Pages::Buyer1IncomeValueCheck < ::Form::Page
},
],
}
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.income.under_soft_min_for_economic_status.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -29,4 +32,8 @@ class Form::Sales::Pages::Buyer1IncomeValueCheck < ::Form::Page
Form::Sales::Questions::Buyer1IncomeValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[ecstat1 income1]
+ end
end
diff --git a/app/models/form/sales/pages/buyer2_income_value_check.rb b/app/models/form/sales/pages/buyer2_income_value_check.rb
index 598c4c7a6..a3f7c2541 100644
--- a/app/models/form/sales/pages/buyer2_income_value_check.rb
+++ b/app/models/form/sales/pages/buyer2_income_value_check.rb
@@ -10,7 +10,7 @@ class Form::Sales::Pages::Buyer2IncomeValueCheck < ::Form::Page
},
]
@title_text = {
- "translation" => "soft_validations.income.under_soft_min_for_economic_status",
+ "translation" => "soft_validations.income.under_soft_min_for_economic_status.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@@ -24,7 +24,10 @@ class Form::Sales::Pages::Buyer2IncomeValueCheck < ::Form::Page
},
],
}
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.income.under_soft_min_for_economic_status.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -32,4 +35,8 @@ class Form::Sales::Pages::Buyer2IncomeValueCheck < ::Form::Page
Form::Sales::Questions::Buyer2IncomeValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[ecstat2 income2]
+ end
end
diff --git a/app/models/form/sales/pages/buyer_live_in_value_check.rb b/app/models/form/sales/pages/buyer_live_in_value_check.rb
index 067ba96ca..99080ae77 100644
--- a/app/models/form/sales/pages/buyer_live_in_value_check.rb
+++ b/app/models/form/sales/pages/buyer_live_in_value_check.rb
@@ -10,7 +10,10 @@ class Form::Sales::Pages::BuyerLiveInValueCheck < Form::Sales::Pages::Person
"translation" => "soft_validations.buyer#{person_index}_livein_wrong_for_ownership_type.title_text",
"arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
}
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.buyer#{person_index}_livein_wrong_for_ownership_type.hint_text",
+ "arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
+ }
end
def questions
@@ -18,4 +21,8 @@ class Form::Sales::Pages::BuyerLiveInValueCheck < Form::Sales::Pages::Person
Form::Sales::Questions::BuyerLiveInValueCheck.new(nil, nil, self, person_index: @person_index),
]
end
+
+ def interruption_screen_question_ids
+ ["ownershipsch", "buy#{@person_index}livein"]
+ end
end
diff --git a/app/models/form/sales/pages/deposit_and_mortgage_value_check.rb b/app/models/form/sales/pages/deposit_and_mortgage_value_check.rb
index 338889030..95e9c9dd7 100644
--- a/app/models/form/sales/pages/deposit_and_mortgage_value_check.rb
+++ b/app/models/form/sales/pages/deposit_and_mortgage_value_check.rb
@@ -14,4 +14,8 @@ class Form::Sales::Pages::DepositAndMortgageValueCheck < ::Form::Page
Form::Sales::Questions::DepositAndMortgageValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[mortgage deposit value discount]
+ end
end
diff --git a/app/models/form/sales/pages/deposit_value_check.rb b/app/models/form/sales/pages/deposit_value_check.rb
index 8fa76ce1a..b31b2cecb 100644
--- a/app/models/form/sales/pages/deposit_value_check.rb
+++ b/app/models/form/sales/pages/deposit_value_check.rb
@@ -6,7 +6,25 @@ class Form::Sales::Pages::DepositValueCheck < ::Form::Page
"deposit_over_soft_max?" => true,
},
]
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.deposit.hint_text",
+ "arguments" => [],
+ }
+ @title_text = {
+ "translation" => "soft_validations.deposit.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "deposit",
+ "i18n_template" => "deposit",
+ },
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "savings",
+ "i18n_template" => "savings",
+ },
+ ],
+ }
end
def questions
@@ -14,4 +32,8 @@ class Form::Sales::Pages::DepositValueCheck < ::Form::Page
Form::Sales::Questions::DepositValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[savings deposit]
+ end
end
diff --git a/app/models/form/sales/pages/discounted_sale_value_check.rb b/app/models/form/sales/pages/discounted_sale_value_check.rb
index 3c1b010f2..dcb820e49 100644
--- a/app/models/form/sales/pages/discounted_sale_value_check.rb
+++ b/app/models/form/sales/pages/discounted_sale_value_check.rb
@@ -35,4 +35,8 @@ class Form::Sales::Pages::DiscountedSaleValueCheck < ::Form::Page
Form::Sales::Questions::DiscountedSaleValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[value deposit ownershipsch mortgage mortgageused discount grant type]
+ end
end
diff --git a/app/models/form/sales/pages/extra_borrowing_value_check.rb b/app/models/form/sales/pages/extra_borrowing_value_check.rb
index 5fff74db2..b3cf0b2db 100644
--- a/app/models/form/sales/pages/extra_borrowing_value_check.rb
+++ b/app/models/form/sales/pages/extra_borrowing_value_check.rb
@@ -7,9 +7,19 @@ class Form::Sales::Pages::ExtraBorrowingValueCheck < Form::Page
},
]
@title_text = {
- "translation" => "soft_validations.extra_borrowing.title",
+ "translation" => "soft_validations.extra_borrowing.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "mortgage_and_deposit_total",
+ "i18n_template" => "mortgage_and_deposit_total",
+ },
+ ],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.extra_borrowing.hint_text",
+ "arguments" => [],
}
- @informative_text = {}
end
def questions
@@ -17,4 +27,8 @@ class Form::Sales::Pages::ExtraBorrowingValueCheck < Form::Page
Form::Sales::Questions::ExtraBorrowingValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[extrabor mortgage deposit value discount]
+ end
end
diff --git a/app/models/form/sales/pages/grant_value_check.rb b/app/models/form/sales/pages/grant_value_check.rb
index a739a1654..6b53d74ee 100644
--- a/app/models/form/sales/pages/grant_value_check.rb
+++ b/app/models/form/sales/pages/grant_value_check.rb
@@ -7,7 +7,20 @@ class Form::Sales::Pages::GrantValueCheck < ::Form::Page
"grant_outside_common_range?" => true,
},
]
- @informative_text = {}
+ @title_text = {
+ "translation" => "soft_validations.grant.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "grant",
+ "i18n_template" => "grant",
+ },
+ ],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.grant.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -15,4 +28,8 @@ class Form::Sales::Pages::GrantValueCheck < ::Form::Page
Form::Sales::Questions::GrantValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[grant]
+ end
end
diff --git a/app/models/form/sales/pages/handover_date_check.rb b/app/models/form/sales/pages/handover_date_check.rb
index 5d656200b..2a3bfdbf3 100644
--- a/app/models/form/sales/pages/handover_date_check.rb
+++ b/app/models/form/sales/pages/handover_date_check.rb
@@ -16,4 +16,8 @@ class Form::Sales::Pages::HandoverDateCheck < ::Form::Page
Form::Sales::Questions::HandoverDateCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[hodate saledate]
+ end
end
diff --git a/app/models/form/sales/pages/household_wheelchair_check.rb b/app/models/form/sales/pages/household_wheelchair_check.rb
index 0cd457444..72b78cc2b 100644
--- a/app/models/form/sales/pages/household_wheelchair_check.rb
+++ b/app/models/form/sales/pages/household_wheelchair_check.rb
@@ -7,6 +7,7 @@ class Form::Sales::Pages::HouseholdWheelchairCheck < ::Form::Page
},
]
@informative_text = {}
+ @title_text = { "translation" => "soft_validations.wheelchair.title_text" }
end
def questions
@@ -14,4 +15,8 @@ class Form::Sales::Pages::HouseholdWheelchairCheck < ::Form::Page
Form::Sales::Questions::HouseholdWheelchairCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[disabled wheel]
+ end
end
diff --git a/app/models/form/sales/pages/monthly_charges_value_check.rb b/app/models/form/sales/pages/monthly_charges_value_check.rb
index 909212b52..662a048bb 100644
--- a/app/models/form/sales/pages/monthly_charges_value_check.rb
+++ b/app/models/form/sales/pages/monthly_charges_value_check.rb
@@ -8,9 +8,18 @@ class Form::Sales::Pages::MonthlyChargesValueCheck < ::Form::Page
]
@title_text = {
"translation" => "soft_validations.monthly_charges_over_soft_max.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "mscharge",
+ "i18n_template" => "mscharge",
+ },
+ ],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.monthly_charges_over_soft_max.hint_text",
"arguments" => [],
}
- @informative_text = {}
end
def questions
@@ -18,4 +27,8 @@ class Form::Sales::Pages::MonthlyChargesValueCheck < ::Form::Page
Form::Sales::Questions::MonthlyChargesValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[type mscharge proptype]
+ end
end
diff --git a/app/models/form/sales/pages/mortgage_value_check.rb b/app/models/form/sales/pages/mortgage_value_check.rb
index 4bff3556d..949cea27f 100644
--- a/app/models/form/sales/pages/mortgage_value_check.rb
+++ b/app/models/form/sales/pages/mortgage_value_check.rb
@@ -4,6 +4,20 @@ class Form::Sales::Pages::MortgageValueCheck < ::Form::Page
@depends_on = depends_on
@informative_text = {}
@person_index = person_index
+ @title_text = {
+ "translation" => "soft_validations.mortgage.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "mortgage",
+ "i18n_template" => "mortgage",
+ },
+ ],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.mortgage.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -28,4 +42,8 @@ class Form::Sales::Pages::MortgageValueCheck < ::Form::Page
]
end
end
+
+ def interruption_screen_question_ids
+ %w[mortgage inc1mort inc2mort jointpur income1 income2 inc1mort inc2mort]
+ end
end
diff --git a/app/models/form/sales/pages/old_persons_shared_ownership_value_check.rb b/app/models/form/sales/pages/old_persons_shared_ownership_value_check.rb
index 9198af18a..537a6679f 100644
--- a/app/models/form/sales/pages/old_persons_shared_ownership_value_check.rb
+++ b/app/models/form/sales/pages/old_persons_shared_ownership_value_check.rb
@@ -7,10 +7,13 @@ class Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck < ::Form::Page
},
]
@title_text = {
- "translation" => "soft_validations.old_persons_shared_ownership",
+ "translation" => "soft_validations.old_persons_shared_ownership.title_text",
+ "arguments" => [],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.old_persons_shared_ownership.hint_text",
"arguments" => [],
}
- @informative_text = {}
end
def questions
@@ -18,4 +21,8 @@ class Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck < ::Form::Page
Form::Sales::Questions::OldPersonsSharedOwnershipValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[type jointpur age1 age2]
+ end
end
diff --git a/app/models/form/sales/pages/percentage_discount_value_check.rb b/app/models/form/sales/pages/percentage_discount_value_check.rb
index 1e3beb3e6..37ff4eea4 100644
--- a/app/models/form/sales/pages/percentage_discount_value_check.rb
+++ b/app/models/form/sales/pages/percentage_discount_value_check.rb
@@ -5,11 +5,18 @@ class Form::Sales::Pages::PercentageDiscountValueCheck < ::Form::Page
"translation" => "soft_validations.percentage_discount_value.title_text",
"arguments" => [{ "key" => "discount", "label" => true, "i18n_template" => "discount" }],
}
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.percentage_discount_value.hint_text",
+ "arguments" => [],
+ }
@depends_on = [{ "percentage_discount_invalid?" => true }]
end
def questions
@questions ||= [Form::Sales::Questions::PercentageDiscountValueCheck.new(nil, nil, self)]
end
+
+ def interruption_screen_question_ids
+ %w[discount proptype]
+ end
end
diff --git a/app/models/form/sales/pages/person_student_not_child_value_check.rb b/app/models/form/sales/pages/person_student_not_child_value_check.rb
index e3513e169..a798c8e16 100644
--- a/app/models/form/sales/pages/person_student_not_child_value_check.rb
+++ b/app/models/form/sales/pages/person_student_not_child_value_check.rb
@@ -18,4 +18,8 @@ class Form::Sales::Pages::PersonStudentNotChildValueCheck < Form::Sales::Pages::
Form::Sales::Questions::PersonStudentNotChildValueCheck.new(nil, nil, self, person_index: @person_index),
]
end
+
+ def interruption_screen_question_ids
+ ["relat#{@person_index}", "ecstat#{@person_index}", "age#{@person_index}"]
+ end
end
diff --git a/app/models/form/sales/pages/retirement_value_check.rb b/app/models/form/sales/pages/retirement_value_check.rb
index b1af2a6d4..9e5dbb87f 100644
--- a/app/models/form/sales/pages/retirement_value_check.rb
+++ b/app/models/form/sales/pages/retirement_value_check.rb
@@ -11,27 +11,13 @@ class Form::Sales::Pages::RetirementValueCheck < Form::Sales::Pages::Person
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_#{person_index}",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- }
- @informative_text = {
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_#{person_index}",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_#{person_index}",
- "label" => false,
+ "key" => "age#{person_index}",
+ "label" => true,
"i18n_template" => "age",
},
],
}
+ @informative_text = {}
end
def questions
@@ -39,4 +25,8 @@ class Form::Sales::Pages::RetirementValueCheck < Form::Sales::Pages::Person
Form::Sales::Questions::RetirementValueCheck.new(nil, nil, self, person_index: @person_index),
]
end
+
+ def interruption_screen_question_ids
+ ["age#{@person_index}", "ecstat#{@person_index}"]
+ end
end
diff --git a/app/models/form/sales/pages/savings_value_check.rb b/app/models/form/sales/pages/savings_value_check.rb
index 779bdae30..6a45a1929 100644
--- a/app/models/form/sales/pages/savings_value_check.rb
+++ b/app/models/form/sales/pages/savings_value_check.rb
@@ -6,7 +6,20 @@ class Form::Sales::Pages::SavingsValueCheck < ::Form::Page
"savings_over_soft_max?" => true,
},
]
- @informative_text = {}
+ @title_text = {
+ "translation" => "soft_validations.savings.title_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "savings",
+ "i18n_template" => "savings",
+ },
+ ],
+ }
+ @informative_text = {
+ "translation" => "soft_validations.savings.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -14,4 +27,8 @@ class Form::Sales::Pages::SavingsValueCheck < ::Form::Page
Form::Sales::Questions::SavingsValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[savings]
+ end
end
diff --git a/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb b/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
index 4730248ed..258697161 100644
--- a/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
+++ b/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
@@ -12,8 +12,8 @@ class Form::Sales::Pages::SharedOwnershipDepositValueCheck < ::Form::Page
"arguments" => [
{
"key" => "field_formatted_as_currency",
- "arguments_for_key" => "expected_shared_ownership_deposit_value",
- "i18n_template" => "expected_shared_ownership_deposit_value",
+ "arguments_for_key" => "mortgage_deposit_and_discount_total",
+ "i18n_template" => "mortgage_deposit_and_discount_total",
},
],
}
@@ -24,4 +24,8 @@ class Form::Sales::Pages::SharedOwnershipDepositValueCheck < ::Form::Page
Form::Sales::Questions::SharedOwnershipDepositValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[mortgage mortgageused cashdis type deposit value equity]
+ end
end
diff --git a/app/models/form/sales/pages/staircase_bought_value_check.rb b/app/models/form/sales/pages/staircase_bought_value_check.rb
index b7b8178ff..283261a53 100644
--- a/app/models/form/sales/pages/staircase_bought_value_check.rb
+++ b/app/models/form/sales/pages/staircase_bought_value_check.rb
@@ -8,7 +8,7 @@ class Form::Sales::Pages::StaircaseBoughtValueCheck < ::Form::Page
},
]
@title_text = {
- "translation" => "soft_validations.staircase_bought_seems_high",
+ "translation" => "soft_validations.staircase_bought_seems_high.title_text",
"arguments" => [
{
"key" => "stairbought",
@@ -16,7 +16,10 @@ class Form::Sales::Pages::StaircaseBoughtValueCheck < ::Form::Page
},
],
}
- @informative_text = {}
+ @informative_text = {
+ "translation" => "soft_validations.staircase_bought_seems_high.hint_text",
+ "arguments" => [],
+ }
end
def questions
@@ -24,4 +27,8 @@ class Form::Sales::Pages::StaircaseBoughtValueCheck < ::Form::Page
Form::Sales::Questions::StaircaseBoughtValueCheck.new(nil, nil, self),
]
end
+
+ def interruption_screen_question_ids
+ %w[stairbought]
+ end
end
diff --git a/app/models/form/sales/questions/household_wheelchair_check.rb b/app/models/form/sales/questions/household_wheelchair_check.rb
index f2c15b9ac..50498b099 100644
--- a/app/models/form/sales/questions/household_wheelchair_check.rb
+++ b/app/models/form/sales/questions/household_wheelchair_check.rb
@@ -3,7 +3,7 @@ class Form::Sales::Questions::HouseholdWheelchairCheck < ::Form::Question
super
@id = "wheel_value_check"
@check_answer_label = "Does anyone in the household use a wheelchair?"
- @header = "Are you sure? You said previously that somebody in household uses a wheelchair"
+ @header = "You told us that someone in the household uses a wheelchair."
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },
diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb
index ee84c3e32..cdebdc679 100644
--- a/app/models/form_handler.rb
+++ b/app/models/form_handler.rb
@@ -40,6 +40,28 @@ class FormHandler
}
end
+ def ordered_sales_questions_for_all_years
+ sales_forms = forms.filter { |name, _form| name.end_with? "sales" }.values
+ ordered_questions = sales_forms.pop.questions.uniq(&:id)
+ question_ids = ordered_questions.map(&:id)
+ all_questions_from_previous_forms = sales_forms.flat_map(&:questions)
+ deprecated_questions_by_preceding_question_id(question_ids, all_questions_from_previous_forms).each do |preceding_question_id, deprecated_question|
+ index_of_preceding_question = ordered_questions.index { |q| q.id == preceding_question_id }
+ ordered_questions.insert(index_of_preceding_question + 1, deprecated_question)
+ end
+ ordered_questions
+ end
+
+ def deprecated_questions_by_preceding_question_id(current_form_question_ids, all_questions_from_previous_forms)
+ deprecated_questions = {}
+ all_questions_from_previous_forms.each_cons(2) do |preceding_question, question|
+ next if current_form_question_ids.include?(question.id) || deprecated_questions.values.map(&:id).include?(question.id)
+
+ deprecated_questions[preceding_question.id] = question
+ end
+ deprecated_questions
+ end
+
def lettings_forms
forms = {}
directories.each do |directory|
@@ -95,9 +117,9 @@ class FormHandler
forms.count { |form| now.between?(form.start_date, form.end_date) } > 1
end
- def use_fake_forms!
+ def use_fake_forms!(fake_forms = nil)
@directories = ["spec/fixtures/forms"]
- @forms = get_all_forms
+ @forms = fake_forms || get_all_forms
end
def use_real_forms!
diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb
index 1afdc3678..13f4ef148 100644
--- a/app/models/lettings_log.rb
+++ b/app/models/lettings_log.rb
@@ -540,24 +540,6 @@ class LettingsLog < Log
private
- def reset_derived_questions
- dependent_questions = { waityear: [{ key: :renewal, value: 0 }],
- referral: [{ key: :renewal, value: 0 }],
- rsnvac: [{ key: :renewal, value: 0 }],
- underoccupation_benefitcap: [{ key: :renewal, value: 0 }],
- wchair: [{ key: :needstype, value: 1 }],
- location_id: [{ key: :needstype, value: 1 }] }
-
- dependent_questions.each do |dependent, conditions|
- condition_key = conditions.first[:key]
- condition_value = conditions.first[:value]
- if public_send("#{condition_key}_changed?") && condition_value == public_send(condition_key) && !public_send("#{dependent}_changed?")
- Rails.logger.debug("Cleared derived #{dependent} value")
- self[dependent] = nil
- end
- end
- end
-
def reset_invalid_unresolved_log_fields!
return unless unresolved?
@@ -590,7 +572,6 @@ private
reset_invalid_unresolved_log_fields!
reset_scheme
- reset_derived_questions
end
def dynamically_not_required
diff --git a/app/models/log.rb b/app/models/log.rb
index 5df04a72f..2c6c0254a 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -158,6 +158,10 @@ class Log < ApplicationRecord
end
end
+ def creation_method
+ bulk_upload_id ? "bulk upload" : "single log"
+ end
+
private
# Handle logs that are older than previous collection start date
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
index ac7af79d1..db31edfbe 100644
--- a/app/models/sales_log.rb
+++ b/app/models/sales_log.rb
@@ -233,6 +233,20 @@ class SalesLog < Log
value * equity / 100
end
+ def mortgage_deposit_and_discount_total
+ mortgage_amount = mortgage || 0
+ deposit_amount = deposit || 0
+ cashdis_amount = cashdis || 0
+
+ mortgage_amount + deposit_amount + cashdis_amount
+ end
+
+ def mortgage_and_deposit_total
+ return unless mortgage && deposit
+
+ mortgage + deposit
+ end
+
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
return if postcode.blank?
diff --git a/app/models/validations/local_authority_validations.rb b/app/models/validations/local_authority_validations.rb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb
index c3b1446c9..02fceeadc 100644
--- a/app/models/validations/sales/financial_validations.rb
+++ b/app/models/validations/sales/financial_validations.rb
@@ -7,7 +7,7 @@ module Validations::Sales::FinancialValidations
relevant_fields = %i[income1 ownershipsch uprn la postcode_full]
if record.london_property? && record.income1 > 90_000
- relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_london") }
+ relevant_fields.each { |field| record.errors.add field, :over_hard_max_for_london, message: I18n.t("validations.financial.income.over_hard_max_for_london") }
elsif record.property_not_in_london? && record.income1 > 80_000
relevant_fields.each { |field| record.errors.add field, :over_hard_max_for_outside_london, message: I18n.t("validations.financial.income.over_hard_max_for_outside_london") }
end
@@ -18,9 +18,9 @@ module Validations::Sales::FinancialValidations
relevant_fields = %i[income2 ownershipsch uprn la postcode_full]
if record.london_property? && record.income2 > 90_000
- relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_london") }
+ relevant_fields.each { |field| record.errors.add field, :over_hard_max_for_london, message: I18n.t("validations.financial.income.over_hard_max_for_london") }
elsif record.property_not_in_london? && record.income2 > 80_000
- relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_outside_london") }
+ relevant_fields.each { |field| record.errors.add field, :over_hard_max_for_outside_london, message: I18n.t("validations.financial.income.over_hard_max_for_outside_london") }
end
end
diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb
index 19d150c7e..e1545759d 100644
--- a/app/models/validations/sales/soft_validations.rb
+++ b/app/models/validations/sales/soft_validations.rb
@@ -82,8 +82,8 @@ module Validations::Sales::SoftValidations
saledate - hodate >= 3.years
end
- def purchase_price_min_or_max_text
- value < sale_range.soft_min ? "minimum" : "maximum"
+ def purchase_price_higher_or_lower_text
+ value < sale_range.soft_min ? "lower" : "higher"
end
def purchase_price_soft_min_or_soft_max
diff --git a/app/models/validations/soft_validations.rb b/app/models/validations/soft_validations.rb
index 5c571af6a..303f525cd 100644
--- a/app/models/validations/soft_validations.rb
+++ b/app/models/validations/soft_validations.rb
@@ -93,6 +93,10 @@ module Validations::SoftValidations
voiddate.present? && startdate.present? && voiddate.between?(startdate.to_date - TEN_YEARS_IN_DAYS, startdate.to_date - TWO_YEARS_IN_DAYS)
end
+ def net_income_higher_or_lower_text
+ net_income_in_soft_max_range? ? "higher" : "lower"
+ end
+
private
def details_known_or_lead_tenant?(tenant_number)
@@ -124,11 +128,9 @@ private
def retired_under_soft_min_age?(person_num)
age = public_send("age#{person_num}")
economic_status = public_send("ecstat#{person_num}")
- gender = public_send("sex#{person_num}")
- return unless age && economic_status && gender
+ return unless age && economic_status
- %w[M X].include?(gender) && tenant_is_retired?(economic_status) && age < retirement_age_for_person(person_num) ||
- gender == "F" && tenant_is_retired?(economic_status) && age < 60
+ tenant_is_retired?(economic_status) && age < 60
end
def not_retired_over_soft_max_age?(person_num)
diff --git a/app/models/validations/tenancy_validations.rb b/app/models/validations/tenancy_validations.rb
index 2d4c15640..b03d4844b 100644
--- a/app/models/validations/tenancy_validations.rb
+++ b/app/models/validations/tenancy_validations.rb
@@ -30,6 +30,7 @@ module Validations::TenancyValidations
conditions.each do |condition|
next unless condition[:condition]
+ record.errors.add :needstype, condition[:error]
record.errors.add :tenancylength, :tenancylength_invalid, message: condition[:error]
record.errors.add :tenancy, condition[:error]
end
diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb
index 9d273dab5..953487cd7 100644
--- a/app/services/bulk_upload/lettings/year2022/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb
@@ -1,6 +1,7 @@
class BulkUpload::Lettings::Year2022::RowParser
include ActiveModel::Model
include ActiveModel::Attributes
+ include InterruptionScreenHelper
QUESTIONS = {
field_1: "What is the letting type?",
@@ -279,9 +280,20 @@ class BulkUpload::Lettings::Year2022::RowParser
attribute :field_133, :integer
attribute :field_134, :integer
- validates :field_1, presence: { message: I18n.t("validations.not_answered", question: "letting type") },
- inclusion: { in: (1..12).to_a, message: I18n.t("validations.invalid_option", question: "letting type") }, on: :after_log
- validates :field_4, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_1) } }, on: :after_log
+ validate :validate_valid_radio_option, on: :before_log
+
+ validates :field_1,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "letting type"),
+ category: :setup,
+ },
+ inclusion: {
+ in: (1..12).to_a,
+ message: I18n.t("validations.invalid_option", question: "letting type"),
+ category: :setup,
+ unless: -> { field_1.blank? },
+ },
+ on: :after_log
validates :field_12, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }, on: :after_log
validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true, on: :after_log
@@ -292,14 +304,33 @@ class BulkUpload::Lettings::Year2022::RowParser
validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true, on: :after_log
validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true, on: :after_log
- validates :field_96, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }, on: :after_log
- validates :field_97, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }, on: :after_log
- validates :field_98, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (year)") }, on: :after_log
-
- validates :field_98, format: { with: /\A\d{2}\z/, message: I18n.t("validations.setup.startdate.year_not_two_digits") }, on: :after_log
+ validates :field_96,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (day)"),
+ category: :setup,
+ }, on: :after_log
+
+ validates :field_97,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (month)"),
+ category: :setup,
+ },
+ on: :after_log
+
+ validates :field_98,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (year)"),
+ category: :setup,
+ },
+ format: {
+ with: /\A\d{2}\z/,
+ message: I18n.t("validations.setup.startdate.year_not_two_digits"),
+ unless: -> { field_98.blank? },
+ category: :setup,
+ },
+ on: :after_log
validate :validate_data_types, on: :after_log
- validate :validate_nulls, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
validate :validate_la_with_local_housing_referral, on: :after_log
validate :validate_cannot_be_la_referral_if_general_needs_and_la, on: :after_log
@@ -309,6 +340,7 @@ class BulkUpload::Lettings::Year2022::RowParser
validate :validate_no_disabled_needs_conjunction, on: :after_log
validate :validate_dont_know_disabled_needs_conjunction, on: :after_log
validate :validate_no_and_dont_know_disabled_needs_conjunction, on: :after_log
+ validate :validate_no_housing_needs_questions_answered, on: :after_log
validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? }
validate :validate_owning_org_data_given, on: :after_log
@@ -334,7 +366,9 @@ class BulkUpload::Lettings::Year2022::RowParser
validate :validate_declaration_acceptance, on: :after_log
- validate :validate_valid_radio_option, on: :before_log
+ validate :validate_incomplete_soft_validations, on: :after_log
+
+ validate :validate_nulls, on: :after_log
def self.question_for_field(field)
QUESTIONS[field]
@@ -422,7 +456,11 @@ private
fields = field_mapping_for_errors[question_id.to_sym] || []
fields.each do |field|
- errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]))
+ if setup_question?(question)
+ errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]), category: :setup)
+ else
+ errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]))
+ end
end
end
end
@@ -479,13 +517,13 @@ private
def validate_location_exists
if scheme && field_5.present? && location.nil?
- errors.add(:field_5, "Location could be found with provided scheme code")
+ errors.add(:field_5, "Location could be found with provided scheme code", category: :setup)
end
end
def validate_location_data_given
if bulk_upload.supported_housing? && field_5.blank?
- errors.add(:field_5, "The scheme code must be present", category: "setup")
+ errors.add(:field_5, I18n.t("validations.not_answered", question: "scheme code"), category: :setup)
end
end
@@ -497,19 +535,19 @@ private
unless owned_by_owning_org || owned_by_managing_org
block_log_creation!
- errors.add(:field_4, "This management group code does not belong to your organisation, or any of your stock owners / managing agents")
+ errors.add(:field_4, "This management group code does not belong to your organisation, or any of your stock owners / managing agents", category: :setup)
end
end
def validate_scheme_exists
if field_4.present? && scheme.nil?
- errors.add(:field_4, "The management group code is not correct")
+ errors.add(:field_4, "The management group code is not correct", category: :setup)
end
end
def validate_scheme_data_given
if bulk_upload.supported_housing? && field_4.blank?
- errors.add(:field_4, "The management group code is not correct", category: "setup")
+ errors.add(:field_4, I18n.t("validations.not_answered", question: "management group code"), category: :setup)
end
end
@@ -536,7 +574,7 @@ private
def validate_managing_org_data_given
if field_113.blank?
block_log_creation!
- errors.add(:field_113, "The managing organisation code is incorrect", category: :setup)
+ errors.add(:field_113, I18n.t("validations.not_answered", question: "managing organisation"), category: :setup)
end
end
@@ -565,7 +603,7 @@ private
block_log_creation!
if errors[:field_111].blank?
- errors.add(:field_111, "The owning organisation code is incorrect", category: :setup)
+ errors.add(:field_111, I18n.t("validations.not_answered", question: "owning organisation"), category: :setup)
end
end
end
@@ -611,6 +649,16 @@ private
end
end
+ def validate_no_housing_needs_questions_answered
+ if [field_55, field_56, field_57, field_58, field_59, field_60].all?(&:blank?)
+ errors.add(:field_59, I18n.t("validations.not_answered", question: "anybody with disabled access needs"))
+ errors.add(:field_58, I18n.t("validations.not_answered", question: "other access needs"))
+ %i[field_55 field_56 field_57].each do |field|
+ errors.add(field, I18n.t("validations.not_answered", question: "disabled access needs type"))
+ end
+ end
+ end
+
def validate_lettings_type_matches_bulk_upload
if [1, 3, 5, 7, 9, 11].include?(field_1) && !bulk_upload.general_needs?
errors.add(:field_1, I18n.t("validations.setup.lettype.supported_housing_mismatch"))
@@ -643,9 +691,9 @@ private
return if start_date.blank? || bulk_upload.form.blank?
unless bulk_upload.form.valid_start_date_for_form?(start_date)
- errors.add(:field_96, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_97, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_98, I18n.t("validations.date.outside_collection_window"))
+ errors.add(:field_96, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_97, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_98, I18n.t("validations.date.outside_collection_window"), category: :setup)
end
end
@@ -702,7 +750,7 @@ private
if setup_question?(question)
fields.each do |field|
- if errors[field].present?
+ if errors.select { |e| fields.include?(e.attribute) }.none?
errors.add(field, I18n.t("validations.not_answered", question: question.check_answer_label&.downcase), category: :setup)
end
end
@@ -716,6 +764,23 @@ private
end
end
+ def validate_incomplete_soft_validations
+ routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }
+ routed_to_soft_validation_questions.each do |question|
+ next unless question
+ next if question.completed?(log)
+
+ question.page.interruption_screen_question_ids.each do |interruption_screen_question_id|
+ field_mapping_for_errors[interruption_screen_question_id.to_sym].each do |field|
+ unless errors.any? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
+ error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(". ")
+ errors.add(field, message: error_message, category: :soft_validation)
+ end
+ end
+ end
+ end
+ end
+
def setup_question?(question)
log.form.setup_sections[0].subsections[0].questions.include?(question)
end
diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb
index 4393d1af2..85abd180d 100644
--- a/app/services/bulk_upload/lettings/year2023/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb
@@ -1,6 +1,7 @@
class BulkUpload::Lettings::Year2023::RowParser
include ActiveModel::Model
include ActiveModel::Attributes
+ include InterruptionScreenHelper
QUESTIONS = {
field_1: "Which organisation owns this property?",
@@ -279,9 +280,61 @@ class BulkUpload::Lettings::Year2023::RowParser
attribute :field_133, :integer
attribute :field_134, :decimal
- validates :field_5, presence: { message: I18n.t("validations.not_answered", question: "letting type") },
- inclusion: { in: (1..12).to_a, message: I18n.t("validations.invalid_option", question: "letting type") }, on: :after_log
- validates :field_16, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_5) } }, on: :after_log
+ validate :validate_valid_radio_option, on: :before_log
+
+ validates :field_5,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "letting type"),
+ category: :setup,
+ },
+ inclusion: {
+ in: (1..12).to_a,
+ message: I18n.t("validations.invalid_option", question: "letting type"),
+ unless: -> { field_5.blank? },
+ category: :setup,
+ },
+ on: :after_log
+
+ validates :field_6,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "property renewal"),
+ category: :setup,
+ },
+ on: :after_log
+
+ validates :field_7,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (day)"),
+ category: :setup,
+ },
+ on: :after_log
+
+ validates :field_8,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (month)"),
+ category: :setup,
+ },
+ on: :after_log
+
+ validates :field_9,
+ presence: {
+ message: I18n.t("validations.not_answered", question: "tenancy start date (year)"),
+ category: :setup,
+ },
+ format: {
+ with: /\A\d{2}\z/,
+ message: I18n.t("validations.setup.startdate.year_not_two_digits"),
+ category: :setup,
+ unless: -> { field_9.blank? },
+ },
+ on: :after_log
+
+ validates :field_16,
+ presence: {
+ if: proc { [2, 4, 6, 8, 10, 12].include?(field_5) },
+ category: :setup,
+ },
+ on: :after_log
validates :field_46, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }, on: :after_log
validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true, on: :after_log
@@ -292,16 +345,8 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true, on: :after_log
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true, on: :after_log
- validates :field_4, presence: { message: I18n.t("validations.not_answered", question: "needs type") }, on: :after_log
- validates :field_6, presence: { message: I18n.t("validations.not_answered", question: "property renewal") }, on: :after_log
- validates :field_7, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }, on: :after_log
- validates :field_8, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }, on: :after_log
- validates :field_9, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (year)") }, on: :after_log
-
- validates :field_9, format: { with: /\A\d{2}\z/, message: I18n.t("validations.setup.startdate.year_not_two_digits") }, on: :after_log
-
+ validate :validate_needs_type_present, on: :after_log
validate :validate_data_types, on: :after_log
- validate :validate_nulls, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
validate :validate_la_with_local_housing_referral, on: :after_log
validate :validate_cannot_be_la_referral_if_general_needs_and_la, on: :after_log
@@ -311,6 +356,7 @@ class BulkUpload::Lettings::Year2023::RowParser
validate :validate_no_disabled_needs_conjunction, on: :after_log
validate :validate_dont_know_disabled_needs_conjunction, on: :after_log
validate :validate_no_and_dont_know_disabled_needs_conjunction, on: :after_log
+ validate :validate_no_housing_needs_questions_answered, on: :after_log
validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? }
validate :validate_owning_org_data_given, on: :after_log
@@ -335,10 +381,12 @@ class BulkUpload::Lettings::Year2023::RowParser
validate :validate_declaration_acceptance, on: :after_log
- validate :validate_valid_radio_option, on: :before_log
+ validate :validate_nulls, on: :after_log
validate :validate_uprn_exists_if_any_key_adddress_fields_are_blank, on: :after_log
+ validate :validate_incomplete_soft_validations, on: :after_log
+
def self.question_for_field(field)
QUESTIONS[field]
end
@@ -425,7 +473,11 @@ private
fields = field_mapping_for_errors[question_id.to_sym] || []
fields.each do |field|
- errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]))
+ if setup_question?(question)
+ errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]), category: :setup)
+ else
+ errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]))
+ end
end
end
end
@@ -457,6 +509,23 @@ private
end
end
+ def validate_incomplete_soft_validations
+ routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }
+ routed_to_soft_validation_questions.each do |question|
+ next unless question
+ next if question.completed?(log)
+
+ question.page.interruption_screen_question_ids.each do |interruption_screen_question_id|
+ field_mapping_for_errors[interruption_screen_question_id.to_sym].each do |field|
+ unless errors.any? { |e| field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
+ error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(". ")
+ errors.add(field, message: error_message, category: :soft_validation)
+ end
+ end
+ end
+ end
+ end
+
def duplicate_check_fields
%w[
startdate
@@ -473,7 +542,7 @@ private
def validate_needs_type_present
if field_4.blank?
- errors.add(:field_4, I18n.t("validations.not_answered", question: "needs type"))
+ errors.add(:field_4, I18n.t("validations.not_answered", question: "needs type"), category: :setup)
end
end
@@ -516,6 +585,16 @@ private
end
end
+ def validate_no_housing_needs_questions_answered
+ if [field_83, field_84, field_85, field_86, field_87, field_88].all?(&:blank?)
+ errors.add(:field_87, I18n.t("validations.not_answered", question: "anybody with disabled access needs"))
+ errors.add(:field_86, I18n.t("validations.not_answered", question: "other access needs"))
+ %i[field_83 field_84 field_85].each do |field|
+ errors.add(field, I18n.t("validations.not_answered", question: "disabled access needs type"))
+ end
+ end
+ end
+
def validate_lettings_type_matches_bulk_upload
if [1, 3, 5, 7, 9, 11].include?(field_5) && !general_needs?
errors.add(:field_5, I18n.t("validations.setup.lettype.supported_housing_mismatch"))
@@ -556,9 +635,9 @@ private
return if start_date.blank? || bulk_upload.form.blank?
unless bulk_upload.form.valid_start_date_for_form?(start_date)
- errors.add(:field_7, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_8, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_9, I18n.t("validations.date.outside_collection_window"))
+ errors.add(:field_7, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_8, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_9, I18n.t("validations.date.outside_collection_window"), category: :setup)
end
end
@@ -579,7 +658,7 @@ private
if setup_question?(question)
fields.each do |field|
- if errors[field].present?
+ if errors.select { |e| fields.include?(e.attribute) }.none?
question_text = question.check_answer_label.presence || question.header.presence || "this question"
errors.add(field, I18n.t("validations.not_answered", question: question_text.downcase), category: :setup)
end
@@ -600,19 +679,19 @@ private
unless location.scheme == scheme
block_log_creation!
- errors.add(:field_17, "Scheme code must relate to a location that is owned by owning organisation or managing organisation")
+ errors.add(:field_17, "Scheme code must relate to a location that is owned by owning organisation or managing organisation", category: :setup)
end
end
def validate_location_exists
if scheme && field_17.present? && location.nil?
- errors.add(:field_17, "Location could be found with provided scheme code")
+ errors.add(:field_17, "Location could be found with provided scheme code", category: :setup)
end
end
def validate_location_data_given
if supported_housing? && field_17.blank?
- errors.add(:field_17, "The scheme code must be present", category: "setup")
+ errors.add(:field_17, I18n.t("validations.not_answered", question: "scheme code"), category: "setup")
end
end
@@ -624,19 +703,19 @@ private
unless owned_by_owning_org || owned_by_managing_org
block_log_creation!
- errors.add(:field_16, "This management group code does not belong to your organisation, or any of your stock owners / managing agents")
+ errors.add(:field_16, "This management group code does not belong to your organisation, or any of your stock owners / managing agents", category: :setup)
end
end
def validate_scheme_exists
if field_16.present? && scheme.nil?
- errors.add(:field_16, "The management group code is not correct")
+ errors.add(:field_16, "The management group code is not correct", category: :setup)
end
end
def validate_scheme_data_given
if supported_housing? && field_16.blank?
- errors.add(:field_16, "The management group code is not correct", category: "setup")
+ errors.add(:field_16, I18n.t("validations.not_answered", question: "management group code"), category: "setup")
end
end
@@ -690,7 +769,7 @@ private
def validate_owning_org_data_given
if field_1.blank?
block_log_creation!
- errors.add(:field_1, "The owning organisation code is incorrect", category: :setup)
+ errors.add(:field_1, I18n.t("validations.not_answered", question: "owning organisation"), category: :setup)
end
end
diff --git a/app/services/bulk_upload/sales/year2022/row_parser.rb b/app/services/bulk_upload/sales/year2022/row_parser.rb
index b08db8585..4383898fb 100644
--- a/app/services/bulk_upload/sales/year2022/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2022/row_parser.rb
@@ -1,6 +1,7 @@
class BulkUpload::Sales::Year2022::RowParser
include ActiveModel::Model
include ActiveModel::Attributes
+ include InterruptionScreenHelper
QUESTIONS = {
field_1: "What is the purchaser code?",
@@ -283,6 +284,7 @@ class BulkUpload::Sales::Year2022::RowParser
validate :validate_created_by_exists, on: :after_log
validate :validate_created_by_related, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
+ validate :validate_incomplete_soft_validations, on: :after_log
def self.question_for_field(field)
QUESTIONS[field]
@@ -939,9 +941,26 @@ private
return if saledate.blank? || bulk_upload.form.blank?
unless bulk_upload.form.valid_start_date_for_form?(saledate)
- errors.add(:field_2, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_3, I18n.t("validations.date.outside_collection_window"))
- errors.add(:field_4, I18n.t("validations.date.outside_collection_window"))
+ errors.add(:field_2, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_3, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ errors.add(:field_4, I18n.t("validations.date.outside_collection_window"), category: :setup)
+ end
+ end
+
+ def validate_incomplete_soft_validations
+ routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }
+ routed_to_soft_validation_questions.each do |question|
+ next unless question
+ next if question.completed?(log)
+
+ question.page.interruption_screen_question_ids.each do |interruption_screen_question_id|
+ field_mapping_for_errors[interruption_screen_question_id.to_sym].each do |field|
+ unless errors.any? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
+ error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(". ")
+ errors.add(field, message: error_message, category: :soft_validation)
+ end
+ end
+ end
end
end
end
diff --git a/app/services/csv/sales_log_csv_service.rb b/app/services/csv/sales_log_csv_service.rb
new file mode 100644
index 000000000..a9573df41
--- /dev/null
+++ b/app/services/csv/sales_log_csv_service.rb
@@ -0,0 +1,107 @@
+module Csv
+ class SalesLogCsvService
+ def initialize(export_type:)
+ @export_type = export_type
+ @attributes = sales_log_attributes
+ end
+
+ def prepare_csv(logs)
+ CSV.generate(headers: true) do |csv|
+ csv << @attributes
+
+ logs.find_each do |log|
+ csv << @attributes.map { |attribute| value(attribute, log) }
+ end
+ end
+ end
+
+ private
+
+ ATTRIBUTES_OF_RELATED_OBJECTS = {
+ day: %i[saledate day],
+ month: %i[saledate month],
+ year: %i[saledate year],
+ is_dpo: %i[created_by is_dpo],
+ created_by_name: %i[created_by name],
+ owning_organisation_name: %i[owning_organisation name],
+ }.freeze
+
+ FIELDS_ALWAYS_EXPORTED_AS_CODES = %w[
+ la
+ prevloc
+ ].freeze
+
+ FIELDS_ALWAYS_EXPORTED_AS_LABELS = {
+ "la_label" => "la",
+ "prevloc_label" => "prevloc",
+ }.freeze
+
+ DATE_FIELDS = %w[
+ created_at
+ updated_at
+ ].freeze
+
+ def value(attribute, log)
+ if ATTRIBUTES_OF_RELATED_OBJECTS.key? attribute.to_sym
+ call_chain = ATTRIBUTES_OF_RELATED_OBJECTS[attribute.to_sym]
+ call_chain.reduce(log) { |object, next_call| object&.public_send(next_call) }
+ elsif FIELDS_ALWAYS_EXPORTED_AS_CODES.include? attribute
+ log.send(attribute)
+ elsif FIELDS_ALWAYS_EXPORTED_AS_LABELS.key? attribute
+ attribute = FIELDS_ALWAYS_EXPORTED_AS_LABELS[attribute]
+ field_value = log.send(attribute)
+ get_label(field_value, attribute, log)
+ elsif DATE_FIELDS.include? attribute
+ log.send(attribute)&.iso8601
+ else
+ value = log.public_send(attribute)
+ case @export_type
+ when "codes"
+ value
+ when "labels"
+ answer_label = get_label(value, attribute, log)
+ answer_label || label_if_boolean_value(value) || value
+ end
+ end
+ end
+
+ def get_label(value, attribute, log)
+ log.form
+ .get_question(attribute, log)
+ &.label_from_value(value)
+ end
+
+ def label_if_boolean_value(value)
+ return "Yes" if value == true
+ return "No" if value == false
+ end
+
+ ATTRIBUTE_MAPPINGS = {
+ "saledate" => %w[day month year],
+ "exdate" => %w[exday exmonth exyear],
+ "hodate" => %w[hoday homonth hoyear],
+ "postcode_full" => %w[pcode1 pcode2],
+ "ppostcode_full" => %w[ppostc1 ppostc2],
+ "la" => %w[la la_label],
+ "prevloc" => %w[prevloc prevloc_label],
+ "created_by_id" => %w[created_by_name],
+ "owning_organisation_id" => %w[owning_organisation_name],
+ }.freeze
+
+ def sales_log_attributes
+ ordered_questions = FormHandler.instance.ordered_sales_questions_for_all_years
+ ordered_questions.reject! { |q| q.id.match?(/((? %w[ecstat1],
%i[tshortfall no_outstanding_charges] => %w[tshortfall hbrentshortfall],
%i[beds outside_the_range] => %w[beds],
- %i[tcharge complete_1_of_3] => %w[brent scharge pscharge supcharg tcharge],
- %i[scharge under_min] => %w[brent scharge pscharge supcharg tcharge],
+ %i[tcharge complete_1_of_3] => charges_attributes,
+ %i[scharge under_min] => charges_attributes,
%i[tshortfall must_be_positive] => %w[tshortfall tshortfall_known],
%i[referral referral_invalid] => %w[referral],
- %i[pscharge outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
- %i[supcharg outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
- %i[scharge outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
+ %i[pscharge outside_the_range] => charges_attributes,
+ %i[supcharg outside_the_range] => charges_attributes,
+ %i[scharge outside_the_range] => charges_attributes,
%i[location_id not_active] => %w[location_id scheme_id],
- %i[tcharge under_10] => %w[brent scharge pscharge supcharg tcharge],
- %i[brent over_hard_max] => %w[brent scharge pscharge supcharg tcharge],
+ %i[tcharge under_10] => charges_attributes,
+ %i[brent over_hard_max] => charges_attributes,
}
(2..8).each do |person|
@@ -464,11 +467,11 @@ module Imports
def previous_postcode_known(xml_doc, previous_postcode, prevloc)
previous_postcode_known = string_or_nil(xml_doc, "Q12bnot")
if previous_postcode_known == "Temporary_or_Unknown" || (previous_postcode.nil? && prevloc.present?)
- 0
+ 0 # not known
elsif previous_postcode.nil?
nil
else
- 1
+ 1 # known
end
end
diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb
index 8702a8846..6e2c11bf3 100644
--- a/app/services/imports/sales_logs_import_service.rb
+++ b/app/services/imports/sales_logs_import_service.rb
@@ -70,7 +70,7 @@ module Imports
attributes["inc1mort"] = unsafe_string_as_integer(xml_doc, "Q2Person1Mortgage")
attributes["income2"] = safe_string_as_integer(xml_doc, "Q2Person2Income")
attributes["income2nk"] = income_known(unsafe_string_as_integer(xml_doc, "P2IncKnown"))
- attributes["savings"] = safe_string_as_integer(xml_doc, "Q3Savings")
+ attributes["savings"] = safe_string_as_integer(xml_doc, "Q3Savings")&.round(-1)
attributes["savingsnk"] = savings_known(xml_doc)
attributes["prevown"] = unsafe_string_as_integer(xml_doc, "Q4PrevOwnedProperty")
attributes["mortgage"] = safe_string_as_decimal(xml_doc, "CALCMORT")
@@ -217,38 +217,46 @@ module Imports
attributes.delete("ppcodenk") if error.attribute == :ppostcode_full
end
@logs_overridden << sales_log.old_id
- save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:postcode_full, :postcodes_not_matching)
- @logger.warn("Log #{sales_log.old_id}: Removing previous postcode known and previous postcode as the postcode is invalid")
- @logs_overridden << sales_log.old_id
- attributes.delete("ppcodenk")
- attributes.delete("ppostcode_full")
- save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:exdate, :over_a_year_from_saledate)
- @logger.warn("Log #{sales_log.old_id}: Removing exchange date as the exchange date is invalid")
- @logs_overridden << sales_log.old_id
- attributes.delete("exdate")
- save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:income1, :over_hard_max_for_outside_london)
- @logger.warn("Log #{sales_log.old_id}: Removing income1 as the income1 is invalid")
- @logs_overridden << sales_log.old_id
- attributes.delete("income1")
- save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:equity, :over_max) || sales_log.errors.of_kind?(:equity, :under_min)
- @logger.warn("Log #{sales_log.old_id}: Removing equity as the equity is invalid")
+ return save_sales_log(attributes, previous_status)
+ end
+
+ errors = {
+ %i[postcode_full postcodes_not_matching] => %w[ppcodenk ppostcode_full],
+ %i[exdate over_a_year_from_saledate] => %w[exdate],
+ %i[income1 over_hard_max_for_outside_london] => %w[income1],
+ %i[income1 over_hard_max_for_london] => %w[income1],
+ %i[income2 over_hard_max_for_outside_london] => %w[income2],
+ %i[income2 over_hard_max_for_london] => %w[income2],
+ %i[equity over_max] => %w[equity],
+ %i[equity under_min] => %w[equity],
+ %i[mscharge under_min] => %w[mscharge has_mscharge],
+ %i[mortgage cannot_be_0] => %w[mortgage],
+ %i[frombeds outside_the_range] => %w[frombeds],
+ }
+
+ errors.each do |(error, fields)|
+ next unless sales_log.errors.of_kind?(*error)
+
+ attribute, _type = error
+ fields.each do |field|
+ @logger.warn("Log #{sales_log.old_id}: Removing #{field} with error: #{sales_log.errors[attribute].sort.join(', ')}")
+ attributes.delete(field)
+ end
@logs_overridden << sales_log.old_id
- attributes.delete("equity")
- save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:postcode_full, :wrong_format)
+ return save_sales_log(attributes, previous_status)
+ end
+
+ if sales_log.errors.of_kind?(:postcode_full, :wrong_format)
@logger.warn("Log #{sales_log.old_id}: Removing postcode as the postcode is invalid")
@logs_overridden << sales_log.old_id
attributes.delete("postcode_full")
attributes["pcodenk"] = attributes["la"].present? ? 1 : nil
save_sales_log(attributes, previous_status)
- elsif sales_log.errors.of_kind?(:mortgage, :cannot_be_0)
- @logger.warn("Log #{sales_log.old_id}: Removing mortgage because it cannot be 0")
+ elsif sales_log.errors.of_kind?(:ppostcode_full, :wrong_format)
+ @logger.warn("Log #{sales_log.old_id}: Removing previous postcode as the postcode is invalid")
@logs_overridden << sales_log.old_id
- attributes.delete("mortgage")
+ attributes.delete("ppostcode_full")
+ attributes["ppcodenk"] = attributes["prevloc"].present? ? 1 : nil
save_sales_log(attributes, previous_status)
elsif sales_log.errors.of_kind?(:uprn, :uprn_error)
@logger.warn("Log #{sales_log.old_id}: Setting uprn_known to no with error: #{sales_log.errors[:uprn].join(', ')}")
diff --git a/app/views/form/_check_answers_summary_list.html.erb b/app/views/form/_check_answers_summary_list.html.erb
index 653cd610d..a008e67d8 100644
--- a/app/views/form/_check_answers_summary_list.html.erb
+++ b/app/views/form/_check_answers_summary_list.html.erb
@@ -1,5 +1,5 @@
<%= govuk_summary_list do |summary_list| %>
- <% total_applicable_questions(subsection, @log, current_user).each do |question| %>
+ <% questions.each do |question| %>
<% summary_list.row do |row| %>
<% row.key { get_question_label(question) } %>
<% row.value do %>
@@ -23,7 +23,7 @@
<% if @log.collection_period_open? %>
<% row.action(
text: question.action_text(@log),
- href: question.action_href(@log, question.page.id),
+ href: action_href(@log, question.page.id, referrer),
visually_hidden_text: question.check_answer_label.to_s.downcase,
) %>
<% end %>
diff --git a/app/views/form/_interruption_screen_banner.html.erb b/app/views/form/_interruption_screen_banner.html.erb
new file mode 100644
index 000000000..14a89b770
--- /dev/null
+++ b/app/views/form/_interruption_screen_banner.html.erb
@@ -0,0 +1,13 @@
+<% if question.page.routed_to?(@log, current_user) %>
+ <%= govuk_panel(
+ classes: "app-panel--interruption",
+ ) do %>
+
<%= display_title_text(title_text, lettings_log) %>
+ <% if informative_text.present? %>
+ <%= display_informative_text(informative_text, lettings_log) %>
+ <% end %>
+ <% if question.hint_text.present? %>
+ <%= question.hint_text&.html_safe %>
+ <% end %>
+ <% end %>
+<% end %>
diff --git a/app/views/form/_interruption_screen_question.html.erb b/app/views/form/_interruption_screen_question.html.erb
index c5da48a92..a37254d1e 100644
--- a/app/views/form/_interruption_screen_question.html.erb
+++ b/app/views/form/_interruption_screen_question.html.erb
@@ -1,22 +1,24 @@
-<%= govuk_panel(
- title_text: display_title_text(title_text, lettings_log),
- classes: "app-panel--interruption",
-) do %>
- <%= display_informative_text(informative_text, lettings_log) %>
- <%= f.govuk_radio_buttons_fieldset question.id.to_sym,
- legend: { text: question.header },
- hint: { text: question.hint_text&.html_safe } do %>
- <% question.answer_options.map do |key, options| %>
- <% if key.starts_with?("divider") %>
- <%= f.govuk_radio_divider %>
- <% else %>
- <%= f.govuk_radio_button question.id,
- key,
- label: { text: options["value"] },
- hint: { text: options["hint"] },
- **stimulus_html_attributes(question) %>
- <% end %>
- <% end %>
- <% end %>
- <%= f.govuk_submit "Save and continue", accesskey: "s", class: "app-button--inverse govuk-!-margin-bottom-0" %>
-<% end %>
+<%= render partial: "form/interruption_screen_banner", locals: { question:, title_text:, informative_text:, lettings_log: } %>
+
+
+ Make sure these answers are correct:
+
+
+
+
+ <%= render partial: "form/check_answers_summary_list", locals: {
+ lettings_log:,
+ questions: soft_validation_affected_questions(question, @log).filter { |q| q.page.routed_to?(@log, current_user) },
+ referrer: "interruption_screen",
+ } %>
+
+
+
+<%= f.hidden_field question.id, value: "0" %>
+
+ <%= f.govuk_submit "Confirm and continue" %>
+ <%= govuk_link_to(
+ (@page.skip_text || "Skip for now"),
+ (@page.skip_href(@log) || send(@log.form.next_page_redirect_path(@page, @log, current_user), @log)),
+ ) %>
+
diff --git a/app/views/form/check_answers.html.erb b/app/views/form/check_answers.html.erb
index 3da071be5..3267b4008 100644
--- a/app/views/form/check_answers.html.erb
+++ b/app/views/form/check_answers.html.erb
@@ -25,6 +25,8 @@
<%= render partial: "form/check_answers_summary_list", locals: {
subsection:,
lettings_log: @log,
+ questions: total_applicable_questions(subsection, @log, current_user),
+ referrer: "check_answers",
} %>
<% end %>
diff --git a/app/views/form/page.html.erb b/app/views/form/page.html.erb
index 9b4d14d9d..b5ce2ead7 100644
--- a/app/views/form/page.html.erb
+++ b/app/views/form/page.html.erb
@@ -7,7 +7,7 @@
<%= form_with model: @log, url: request.original_url, method: "post", local: true do |f| %>
-
">
+
<% remove_other_page_errors(@log, @page) %>
<%= f.govuk_error_summary %>
@@ -59,6 +59,8 @@
<% end %>
<%= f.hidden_field :page, value: @page.id %>
+ <%= f.hidden_field :interruption_page_id, value: @interruption_page_id %>
+ <%= f.hidden_field :interruption_page_referrer_type, value: @interruption_page_referrer_type %>
<% if !@page.interruption_screen? && if request.query_parameters["referrer"] != "check_answers" %>
diff --git a/app/views/form/review.html.erb b/app/views/form/review.html.erb
index 0e63875d9..e619da2f8 100644
--- a/app/views/form/review.html.erb
+++ b/app/views/form/review.html.erb
@@ -23,7 +23,7 @@
<%= subsection.label %>
- <%= render partial: "form/check_answers_summary_list", locals: { subsection: } %>
+ <%= render partial: "form/check_answers_summary_list", locals: { subsection:, questions: total_applicable_questions(subsection, @log, current_user), referrer: "check_answers" } %>
<% end %>
diff --git a/app/views/logs/_log_list.html.erb b/app/views/logs/_log_list.html.erb
index 9112cde81..e92186d4d 100644
--- a/app/views/logs/_log_list.html.erb
+++ b/app/views/logs/_log_list.html.erb
@@ -1,6 +1,6 @@
<%= render(SearchResultCaptionComponent.new(searched:, count: pagy.count, item_label:, total_count:, item: "logs", path: request.path)) %>
- <% if logs&.first&.lettings? %>
+ <% if logs&.any? %>
<%= govuk_link_to "Download (CSV)", csv_download_url, type: "text/csv", class: "govuk-!-margin-right-4" %>
<% if @current_user.support? %>
<%= govuk_link_to "Download (CSV, codes only)", csv_codes_only_download_url, type: "text/csv" %>
diff --git a/app/views/logs/csv_confirmation.html.erb b/app/views/logs/csv_confirmation.html.erb
index 90f90813c..847be9ebf 100644
--- a/app/views/logs/csv_confirmation.html.erb
+++ b/app/views/logs/csv_confirmation.html.erb
@@ -9,7 +9,7 @@
Open your email inbox and click the link to download your CSV file.
- <%= govuk_link_to "Return to logs", lettings_logs_path %>
+ <%= govuk_link_to "Return to logs", logs_path_for_controller(controller) %>
diff --git a/app/views/logs/index.html.erb b/app/views/logs/index.html.erb
index 04209be73..7a4fcba06 100644
--- a/app/views/logs/index.html.erb
+++ b/app/views/logs/index.html.erb
@@ -78,8 +78,8 @@
searched: @searched,
item_label:,
total_count: @total_count,
- csv_download_url: csv_download_url_for_controller(controller_type: controller, search: @search_term, codes_only: false),
- csv_codes_only_download_url: csv_download_url_for_controller(controller_type: controller, search: @search_term, codes_only: true),
+ csv_download_url: csv_download_url_for_controller(controller:, search: @search_term, codes_only: false),
+ csv_codes_only_download_url: csv_download_url_for_controller(controller:, search: @search_term, codes_only: true),
} %>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %>
diff --git a/app/views/merge_requests/confirm_telephone_number.html.erb b/app/views/merge_requests/confirm_telephone_number.html.erb
index 0c92a4f28..8b3a354b4 100644
--- a/app/views/merge_requests/confirm_telephone_number.html.erb
+++ b/app/views/merge_requests/confirm_telephone_number.html.erb
@@ -21,7 +21,12 @@
<% if @merge_request.absorbing_organisation.phone.present? %>
<%= f.govuk_radio_buttons_fieldset(:telephone_number_correct, legend: nil) do %>
<%= f.govuk_radio_button :telephone_number_correct, true, checked: @merge_request.telephone_number_correct?, label: { text: "This telephone number is correct" }, link_errors: true %>
- <%= f.govuk_radio_button :telephone_number_correct, false, checked: @merge_request.new_telephone_number.present?, label: { text: "Enter a new phone number" } do %>
+ <%= f.govuk_radio_button(
+ :telephone_number_correct,
+ false,
+ checked: (@merge_request.new_telephone_number.present? || @merge_request.errors.key?(:new_telephone_number)),
+ label: { text: "Enter a new phone number" },
+ ) do %>
<%= f.govuk_text_field :new_telephone_number, label: { text: "Telephone number" }, width: "two-thirds" %>
<% end %>
<%= f.hidden_field :page, value: "confirm_telephone_number" %>
diff --git a/app/views/merge_requests/new_organisation_address.html.erb b/app/views/merge_requests/new_organisation_address.html.erb
index 32dc57c86..7dd331507 100644
--- a/app/views/merge_requests/new_organisation_address.html.erb
+++ b/app/views/merge_requests/new_organisation_address.html.erb
@@ -1,5 +1,33 @@
<% content_for :before_content do %>
<% title = "New organisation address" %>
<% content_for :title, title %>
- <%= govuk_back_link href: new_organisation_name_merge_request_path(id: @merge_request) %>
+ <%= govuk_back_link href: new_organisation_name_merge_request_path(@merge_request) %>
+<% end %>
+
+<%= form_with model: @merge_request, url: merge_request_path, method: :patch do |f| %>
+ <%= f.govuk_error_summary %>
+
+ What is <%= @merge_request.new_organisation_name.possessive %> address?
+
+
+ <%= f.govuk_text_field :new_organisation_address_line1,
+ label: { text: "Address line 1", size: "m" },
+ autocomplete: "address-line1" %>
+
+ <%= f.govuk_text_field :new_organisation_address_line2,
+ label: { text: "Address line 2", size: "m" },
+ autocomplete: "address-line2" %>
+
+ <%= f.govuk_text_field :new_organisation_postcode,
+ label: { text: "Postcode", size: "m" },
+ autocomplete: "postal-code",
+ width: 10 %>
+
+ <%= f.hidden_field :page, value: "new_organisation_address" %>
+
+ <%= f.govuk_submit %>
+ <%= govuk_link_to("Skip for now", new_organisation_telephone_number_merge_request_path(@merge_request)) %>
+
+
+
<% end %>
diff --git a/app/views/merge_requests/new_organisation_telephone_number.html.erb b/app/views/merge_requests/new_organisation_telephone_number.html.erb
new file mode 100644
index 000000000..059ca752d
--- /dev/null
+++ b/app/views/merge_requests/new_organisation_telephone_number.html.erb
@@ -0,0 +1,5 @@
+<% content_for :before_content do %>
+ <% title = "New organisation telephone number" %>
+ <% content_for :title, title %>
+ <%= govuk_back_link href: new_organisation_address_merge_request_path(@merge_request) %>
+<% end %>
diff --git a/app/views/organisations/logs.html.erb b/app/views/organisations/logs.html.erb
index bac737e6c..55c130c29 100644
--- a/app/views/organisations/logs.html.erb
+++ b/app/views/organisations/logs.html.erb
@@ -34,8 +34,8 @@
searched: @searched,
item_label:,
total_count: @total_count,
- csv_download_url: logs_csv_download_organisation_path(@organisation, search: @search_term, codes_only: false),
- csv_codes_only_download_url: logs_csv_download_organisation_path(@organisation, search: @search_term, codes_only: true),
+ csv_download_url: csv_download_url_by_log_type(@log_type, @organisation, search: @search_term, codes_only: false),
+ csv_codes_only_download_url: csv_download_url_by_log_type(@log_type, @organisation, search: @search_term, codes_only: true),
} %>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %>
diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json
index c3b4e3341..5a65e6f0e 100644
--- a/config/forms/2022_2023.json
+++ b/config/forms/2022_2023.json
@@ -789,7 +789,10 @@
"title_text": {
"translation": "soft_validations.void_date.title_text"
},
- "informative_text": {},
+ "informative_text": {
+ "translation": "soft_validations.void_date.hint_text",
+ "arguments": []
+ },
"questions": {
"void_date_value_check": {
"check_answer_label": "Void date confirmation",
@@ -814,7 +817,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["voiddate", "startdate"]
},
"property_major_repairs": {
"header": "",
@@ -898,7 +902,10 @@
"title_text": {
"translation": "soft_validations.major_repairs_date.title_text"
},
- "informative_text": {},
+ "informative_text": {
+ "translation": "soft_validations.major_repairs_date.hint_text",
+ "arguments": []
+ },
"questions": {
"major_repairs_date_value_check": {
"check_answer_label": "Major repairs date confirmation",
@@ -923,7 +930,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["mrcdate", "startdate"]
}
},
"displayed_in_tasklist": [
@@ -1237,7 +1245,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check": {
"depends_on": [
@@ -1280,7 +1289,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"lead_tenant_age": {
"header": "",
@@ -1379,7 +1389,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_lead_age_value_check": {
"depends_on": [
@@ -1422,7 +1433,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"lead_tenant_gender_identity": {
"header": "",
@@ -1500,7 +1512,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_lead_value_check": {
"depends_on": [
@@ -1543,7 +1556,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"lead_tenant_ethnic_group": {
"header": "",
@@ -1839,27 +1853,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_1",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_1",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_1",
- "label": false,
+ "key": "age1",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -1885,7 +1885,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat1", "age1"]
},
"lead_tenant_over_retirement_value_check": {
"depends_on": [
@@ -1943,7 +1944,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat1", "sex1", "age1"]
},
"person_2_known": {
"header": "You’ve given us the details for 1 person in the household",
@@ -2123,7 +2125,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_2_age_value_check": {
"depends_on": [
@@ -2167,7 +2170,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_2_gender_identity": {
"header": "",
@@ -2246,7 +2250,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_2_value_check": {
"depends_on": [
@@ -2290,7 +2295,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_2_working_situation": {
"header": "",
@@ -2377,27 +2383,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_2",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_2",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_2",
- "label": false,
+ "key": "age2",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -2423,7 +2415,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat2", "age2"]
},
"person_2_over_retirement_value_check": {
"depends_on": [
@@ -2481,7 +2474,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat2", "sex2", "age2"]
},
"person_3_known": {
"header": "You’ve given us the details for 2 people in the household",
@@ -2658,7 +2652,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_3_age_value_check": {
"depends_on": [
@@ -2702,7 +2697,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_3_gender_identity": {
"header": "",
@@ -2781,7 +2777,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_3_value_check": {
"depends_on": [
@@ -2825,7 +2822,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_3_working_situation": {
"header": "",
@@ -2912,27 +2910,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_3",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_3",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_3",
- "label": false,
+ "key": "age3",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -2958,7 +2942,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat3", "age3"]
},
"person_3_over_retirement_value_check": {
"depends_on": [
@@ -3016,7 +3001,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat3", "sex3", "age3"]
},
"person_4_known": {
"header": "You’ve given us the details for 3 people in the household",
@@ -3190,7 +3176,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_4_age_value_check": {
"depends_on": [
@@ -3234,7 +3221,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_4_gender_identity": {
"header": "",
@@ -3313,7 +3301,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_4_value_check": {
"depends_on": [
@@ -3357,7 +3346,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_4_working_situation": {
"header": "",
@@ -3444,27 +3434,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_4",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_4",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_4",
- "label": false,
+ "key": "age4",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -3490,7 +3466,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat4", "age4"]
},
"person_4_over_retirement_value_check": {
"depends_on": [
@@ -3548,7 +3525,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat4", "sex4", "age4"]
},
"person_5_known": {
"header": "You’ve given us the details for 4 people in the household",
@@ -3719,7 +3697,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_5_age_value_check": {
"depends_on": [
@@ -3763,7 +3742,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_5_gender_identity": {
"header": "",
@@ -3842,7 +3822,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_5_value_check": {
"depends_on": [
@@ -3886,7 +3867,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_5_working_situation": {
"header": "",
@@ -3973,27 +3955,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_5",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_5",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_5",
- "label": false,
+ "key": "age5",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -4019,7 +3987,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat5", "age5"]
},
"person_5_over_retirement_value_check": {
"depends_on": [
@@ -4077,7 +4046,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat5", "sex5", "age5"]
},
"person_6_known": {
"header": "You’ve given us the details for 5 people in the household",
@@ -4245,7 +4215,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_6_age_value_check": {
"depends_on": [
@@ -4289,7 +4260,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_6_gender_identity": {
"header": "",
@@ -4368,7 +4340,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_6_value_check": {
"depends_on": [
@@ -4412,7 +4385,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_6_working_situation": {
"header": "",
@@ -4499,27 +4473,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_6",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_6",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_6",
- "label": false,
+ "key": "age6",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -4545,7 +4505,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat6", "age6"]
},
"person_6_over_retirement_value_check": {
"depends_on": [
@@ -4603,7 +4564,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat6", "sex6", "age6"]
},
"person_7_known": {
"header": "You’ve given us the details for 6 people in the household",
@@ -4768,7 +4730,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_7_age_value_check": {
"depends_on": [
@@ -4812,7 +4775,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_7_gender_identity": {
"header": "",
@@ -4891,7 +4855,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_7_value_check": {
"depends_on": [
@@ -4935,7 +4900,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_7_working_situation": {
"header": "",
@@ -5022,27 +4988,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_7",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_7",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_7",
- "label": false,
+ "key": "age7",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -5068,7 +5020,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat7", "age7"]
},
"person_7_over_retirement_value_check": {
"depends_on": [
@@ -5126,7 +5079,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat7", "sex7", "age7"]
},
"person_8_known": {
"header": "You’ve given us the details for 7 people in the household",
@@ -5288,7 +5242,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_8_age_value_check": {
"depends_on": [
@@ -5332,7 +5287,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_8_gender_identity": {
"header": "",
@@ -5411,7 +5367,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_person_8_value_check": {
"depends_on": [
@@ -5455,7 +5412,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"person_8_working_situation": {
"header": "",
@@ -5542,27 +5500,13 @@
"translation": "soft_validations.retirement.min.title",
"arguments": [
{
- "key": "retirement_age_for_person_8",
- "label": false,
- "i18n_template": "age"
- }
- ]
- },
- "informative_text": {
- "translation": "soft_validations.retirement.min.hint_text",
- "arguments": [
- {
- "key": "plural_gender_for_person_8",
- "label": false,
- "i18n_template": "gender"
- },
- {
- "key": "retirement_age_for_person_8",
- "label": false,
+ "key": "age8",
+ "label": true,
"i18n_template": "age"
}
]
},
+ "informative_text": {},
"questions": {
"retirement_value_check": {
"check_answer_label": "Retirement confirmation",
@@ -5588,7 +5532,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat8", "age8"]
},
"person_8_over_retirement_value_check": {
"depends_on": [
@@ -5646,7 +5591,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat8", "sex8", "age8"]
}
}
},
@@ -5828,7 +5774,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8"]
},
"females_in_soft_age_range_in_pregnant_household_value_check": {
"depends_on": [
@@ -5880,7 +5827,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["preg_occ", "sex1", "sex2", "sex3", "sex4", "sex5", "sex6", "sex7", "sex8", "age1", "age2", "age3", "age4", "age5", "age6", "age7", "age8"]
},
"access_needs_exist": {
"header": "",
@@ -7351,23 +7299,30 @@
}
],
"title_text": {
- "translation": "soft_validations.net_income.title_text"
- },
- "informative_text": {
- "translation": "soft_validations.net_income.hint_text",
- "arguments": [
+ "translation": "soft_validations.net_income.title_text",
+ "arguments" :[
{
- "key": "ecstat1",
+ "key": "incfreq",
"label": true,
- "i18n_template": "ecstat1"
+ "i18n_template": "incfreq"
},
{
- "key": "earnings",
- "label": true,
+ "key": "field_formatted_as_currency",
+ "arguments_for_key": "earnings",
"i18n_template": "earnings"
}
]
},
+ "informative_text": {
+ "translation": "soft_validations.net_income.hint_text",
+ "arguments": [
+ {
+ "key": "net_income_higher_or_lower_text",
+ "label": false,
+ "i18n_template": "net_income_higher_or_lower_text"
+ }
+ ]
+ },
"questions": {
"net_income_value_check": {
"check_answer_label": "Net income confirmation",
@@ -7392,7 +7347,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["incfreq", "earnings", "ecstat1"]
},
"housing_benefit": {
"header": "",
@@ -7754,7 +7710,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["chcharge", "is_carehome"]
},
"rent_weekly": {
"header": "Household rent and charges",
@@ -8268,8 +8225,8 @@
}
]
},
- "header": "This rent is lower than expected for this property type, in this area. Check:",
- "hint_text": "- the decimal point is not missing (£X.XX)
- the frequency is correct, for example weekly, monthly
- the rent type is correct, for example affordable or social rent
Are you sure this is correct?
",
+ "header": "Are you sure this is correct?",
+ "hint_text": "This is lower than we would expect. Check:- the decimal point
- the frequency, for example every week or every calendar month
- the rent type is correct, for example affordable or social rent
",
"type": "interruption_screen",
"answer_options": {
"0": {
@@ -8280,7 +8237,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["brent", "startdate", "la", "beds", "rent_type", "needstype"]
},
"max_rent_value_check": {
"depends_on": [
@@ -8312,8 +8270,8 @@
}
]
},
- "header": "This rent is higher than expected for this property type, in this area. Check:",
- "hint_text": "- the decimal point is not missing (£X.XX)
- the frequency is correct, for example weekly, monthly
- the rent type is correct, for example affordable or social rent
Are you sure this is correct?
",
+ "header": "Are you sure this is correct?",
+ "hint_text": "This is higher than we would expect. Check:- the decimal point
- the frequency, for example every week or every calendar month
- the rent type is correct, for example affordable or social rent
",
"type": "interruption_screen",
"answer_options": {
"0": {
@@ -8324,7 +8282,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["brent", "startdate", "la", "beds", "rent_type", "needstype"]
},
"outstanding": {
"header": "",
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 4ab359ccf..78e3d7890 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -533,44 +533,54 @@ en:
soft_validations:
net_income:
- title_text: "Net income is outside the expected range based on the lead tenant’s working situation"
- hint_text: "You told us the lead tenant’s working situation is: %{ecstat1}.
The household income you have entered is %{earnings}.
"
+ title_text: "You told us the lead tenant’s income is %{earnings} %{incfreq}."
+ hint_text: "This is %{net_income_higher_or_lower_text} than we would expect for their working situation."
in_soft_min_range:
message: "Net income is lower than expected based on the lead tenant’s working situation. Are you sure this is correct?"
in_soft_max_range:
message: "Net income is higher than expected based on the lead tenant’s working situation. Are you sure this is correct?"
income:
- under_soft_min_for_economic_status: "You said income was %{income}, which is below this working situation's minimum (%{minimum})"
+ under_soft_min_for_economic_status:
+ title_text: "You told us income was %{income}."
+ hint_text: "This is less than we would expect for someone in this working situation."
rent:
outside_range_title: "You told us the rent is %{brent}"
min_hint_text: "The minimum rent expected for this type of property in this local authority is %{soft_min_for_period}."
max_hint_text: "The maximum rent expected for this type of property in this local authority is %{soft_max_for_period}."
purchase_price:
title_text: "You told us the purchase price is %{value}"
- hint_text: "The %{min_or_max} purchase price expected for this type of property in this local authority is %{soft_min_or_soft_max}"
+ hint_text: "This is %{higher_or_lower} than we would expect"
retirement:
min:
- title: "You told us this person is under %{age} and retired"
+ title: "You told us this person is aged %{age} years and retired."
hint_text: "The minimum expected retirement age for %{gender} in England is %{age}."
max:
title: "You told us this person is %{age} or over and not retired"
hint_text: "The minimum expected retirement age for %{gender} in England is %{age}."
extra_borrowing:
- title: "The mortgage and deposit are higher than the purchase minus the discount"
+ title_text: "You told us that the mortgage and deposit total is %{mortgage_and_deposit_total}"
+ hint_text: "This is higher than the purchase price minus the discount."
pregnancy:
title: "You told us somebody in the household is pregnant"
no_females: "You also told us there are no female tenants living at the property."
females_not_in_soft_age_range: "You also told us that any female tenants living at the property are in the following age ranges:- under 16 years old
- over 50 years old
"
major_repairs_date:
- title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years"
+ title_text: "You told us the property has been vacant for 2 years."
+ hint_text: "This is higher than we would expect."
void_date:
- title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years"
+ title_text: "You told us that the property has been vacant for more than 2 years."
+ hint_text: "This is higher than we would expect."
shared_ownership_deposit:
- title_text: "Mortgage, deposit and cash discount total should equal %{expected_shared_ownership_deposit_value}"
- old_persons_shared_ownership: "At least one buyer should be aged over 64 for Older persons’ shared ownership scheme"
- staircase_bought_seems_high: "You said %{percentage}% was bought in this staircasing transaction, which seems high. Are you sure?"
+ title_text: "You told us that the mortgage, deposit and discount add up to %{mortgage_deposit_and_discount_total}"
+ old_persons_shared_ownership:
+ title_text: "You told us the buyer is using the Older Persons Shared Ownership scheme."
+ hint_text: "At least one buyer must be aged 65 years and over to use this scheme."
+ staircase_bought_seems_high:
+ title_text: "You told us that %{percentage}% was bought in this staircasing transaction."
+ hint_text: "Most staircasing transactions are less than 50%"
monthly_charges_over_soft_max:
- title_text: "The amount of monthly charges is high for this type of property and sale type"
+ title_text: "You told us that the monthly charges were %{mscharge}."
+ hint_text: "This is higher than we would expect."
student_not_child:
title_text: "You told us this person is a student aged beween 16 and 19"
discounted_sale_value:
@@ -579,11 +589,28 @@ en:
care_home_charges:
title_text: "Care home charges should be provided if this is a care home accommodation"
buyer1_livein_wrong_for_ownership_type:
- title_text: "You told us that buyer 1 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
+ title_text: "You told us that buyer 1 will not live in the property."
+ hint_text: " For %{ownership_scheme} types, the buyer usually lives in the property."
buyer2_livein_wrong_for_ownership_type:
- title_text: "You told us that buyer 2 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
+ title_text: "You told us that buyer 2 will not live in the property."
+ hint_text: " For %{ownership_scheme} types, the buyer usually lives in the property."
percentage_discount_value:
- title_text: "You told us that the percentage discount was %{discount}. This seems high for this type of property."
+ title_text: "You told us that the percentage discount is %{discount}."
+ hint_text: "This is higher than we would expect."
+ savings:
+ title_text: "You told us the buyer’s savings were %{savings}."
+ hint_text: "This is higher than we would expect."
+ deposit:
+ title_text: "You told us the buyer’s deposit was %{deposit} and their savings were %{savings}."
+ hint_text: "The deposit amount is higher than we would expect for the amount of savings they have."
+ grant:
+ title_text: "You told us that the grant amount is %{grant}"
+ hint_text: "Loans, grants and subsidies are usually between £9,000 and £16,000."
+ wheelchair:
+ title_text: "You told us that someone in the household uses a wheelchair."
+ mortgage:
+ title_text: "You told us that the mortgage amount is %{mortgage}"
+ hint_text: "This is more than 5 times the income, which is higher than we would expect."
devise:
two_factor_authentication:
diff --git a/config/routes.rb b/config/routes.rb
index 48afc3357..e815b5137 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -113,9 +113,12 @@ Rails.application.routes.draw do
get "users/invite", to: "users/account#new"
get "lettings-logs", to: "organisations#lettings_logs"
get "sales-logs", to: "organisations#sales_logs"
- get "logs/csv-download", to: "organisations#download_csv"
- post "logs/email-csv", to: "organisations#email_csv"
- get "logs/csv-confirmation", to: "lettings_logs#csv_confirmation"
+ get "lettings-logs/csv-download", to: "organisations#download_lettings_csv"
+ post "lettings-logs/email-csv", to: "organisations#email_lettings_csv"
+ get "lettings-logs/csv-confirmation", to: "lettings_logs#csv_confirmation"
+ get "sales-logs/csv-download", to: "organisations#download_sales_csv"
+ post "sales-logs/email-csv", to: "organisations#email_sales_csv"
+ get "sales-logs/csv-confirmation", to: "sales_logs#csv_confirmation"
get "schemes", to: "organisations#schemes"
get "stock-owners", to: "organisation_relationships#stock_owners"
get "stock-owners/add", to: "organisation_relationships#add_stock_owner"
@@ -140,6 +143,7 @@ Rails.application.routes.draw do
get "confirm-telephone-number"
get "new-organisation-name"
get "new-organisation-address"
+ get "new-organisation-telephone-number"
get "merge-date"
end
end
@@ -197,6 +201,10 @@ Rails.application.routes.draw do
resources :sales_logs, path: "/sales-logs" do
collection do
+ get "csv-download", to: "sales_logs#download_csv"
+ post "email-csv", to: "sales_logs#email_csv"
+ get "csv-confirmation", to: "sales_logs#csv_confirmation"
+
resources :bulk_upload_sales_logs, path: "bulk-upload-logs" do
collection do
get :start
diff --git a/db/migrate/20230504111352_add_new_organisation_address.rb b/db/migrate/20230504111352_add_new_organisation_address.rb
new file mode 100644
index 000000000..9b10decba
--- /dev/null
+++ b/db/migrate/20230504111352_add_new_organisation_address.rb
@@ -0,0 +1,9 @@
+class AddNewOrganisationAddress < ActiveRecord::Migration[7.0]
+ def change
+ change_table :merge_requests, bulk: true do |t|
+ t.column :new_organisation_address_line1, :string
+ t.column :new_organisation_address_line2, :string
+ t.column :new_organisation_postcode, :string
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index cbe185ed4..b75324351 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2023_05_02_135049) do
+ActiveRecord::Schema[7.0].define(version: 2023_05_04_111352) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -372,6 +372,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_05_02_135049) do
t.boolean "telephone_number_correct"
t.string "new_telephone_number"
t.string "new_organisation_name"
+ t.string "new_organisation_address_line1"
+ t.string "new_organisation_address_line2"
+ t.string "new_organisation_postcode"
end
create_table "organisation_relationships", force: :cascade do |t|
diff --git a/package.json b/package.json
index 8b6a0dbe1..b4f225668 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,6 @@
"accessible-autocomplete": "^2.0.3",
"babel-loader": "^8.2.3",
"babel-plugin-macros": "^3.1.0",
- "chart.js": "^3.6.0",
"copy-webpack-plugin": "^10.2.4",
"core-js": "^3.21.1",
"css-loader": "^6.7.1",
@@ -29,7 +28,7 @@
"sass": "^1.49.9",
"sass-loader": "^12.6.0",
"unfetch": "^4.2.0",
- "webpack": "^5.70.0",
+ "webpack": "^5.76.0",
"webpack-cli": "^4.9.2",
"webpack-remove-empty-scripts": "^0.7.3"
},
diff --git a/spec/components/check_answers_summary_list_card_component_spec.rb b/spec/components/check_answers_summary_list_card_component_spec.rb
index 8bf9f4a45..842f55e14 100644
--- a/spec/components/check_answers_summary_list_card_component_spec.rb
+++ b/spec/components/check_answers_summary_list_card_component_spec.rb
@@ -62,13 +62,21 @@ RSpec.describe CheckAnswersSummaryListCardComponent, type: :component do
context "when in 23/24 collection" do
context "when given a set of questions" do
- let(:user) { build(:user) }
- let(:log) { build(:lettings_log, :completed, age2: 99, startdate: Time.zone.local(2023, 5, 1)) }
+ let(:user) { create(:user) }
+ let(:log) { create(:lettings_log, :completed, age2: 99, startdate: Time.zone.local(2023, 5, 1)) }
let(:subsection_id) { "household_characteristics" }
let(:subsection) { log.form.get_subsection(subsection_id) }
let(:questions) { subsection.applicable_questions(log) }
- it "renders a summary list card includinq question numbers for the answers to those questions" do
+ around do |example|
+ Timecop.freeze(Time.zone.local(2023, 5, 1))
+ Singleton.__init__(FormHandler)
+ example.run
+ Timecop.return
+ Singleton.__init__(FormHandler)
+ end
+
+ it "renders a summary list card including question numbers for the answers to those questions" do
expect(rendered).to have_content(questions.first.answer_label(log))
expect(rendered).to have_content("Q32 - Lead tenant’s age")
end
diff --git a/spec/factories/form.rb b/spec/factories/form.rb
new file mode 100644
index 000000000..9694cfaac
--- /dev/null
+++ b/spec/factories/form.rb
@@ -0,0 +1,25 @@
+class FormFixture < Form
+ attr_accessor :sections, :subsections, :pages, :questions
+end
+
+class FormFactory
+ def initialize(year:, type:)
+ @year = year
+ @type = type
+ end
+
+ def with_sections(sections)
+ @sections = sections
+ self
+ end
+
+ def build
+ form = FormFixture.new(nil, @year, [], @type)
+ @sections.each { |section| section.form = form }
+ form.sections = @sections
+ form.subsections = form.sections.flat_map(&:subsections)
+ form.pages = form.subsections.flat_map(&:pages)
+ form.questions = form.pages.flat_map(&:questions)
+ form
+ end
+end
diff --git a/spec/factories/page.rb b/spec/factories/page.rb
new file mode 100644
index 000000000..2b5b27969
--- /dev/null
+++ b/spec/factories/page.rb
@@ -0,0 +1,21 @@
+FactoryBot.define do
+ factory :page, class: "Form::Page" do
+ id { "page_id" }
+ initialize_with { new(id, nil, nil) }
+ trait :with_question do
+ transient do
+ question_id { nil }
+ question { nil }
+ end
+
+ after :build do |page, evaluator|
+ page.questions = if (q = evaluator.question)
+ q.page = page
+ [q]
+ else
+ [build(:question, id: evaluator.question_id, page:)]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/factories/question.rb b/spec/factories/question.rb
new file mode 100644
index 000000000..e34bc5e75
--- /dev/null
+++ b/spec/factories/question.rb
@@ -0,0 +1,6 @@
+FactoryBot.define do
+ factory :question, class: "Form::Question" do
+ initialize_with { new(id, nil, nil) }
+ type { "text" }
+ end
+end
diff --git a/spec/factories/sales_log.rb b/spec/factories/sales_log.rb
index fa5773ef3..b17efec90 100644
--- a/spec/factories/sales_log.rb
+++ b/spec/factories/sales_log.rb
@@ -120,7 +120,8 @@ FactoryBot.define do
has_mscharge { 1 }
mscharge { 100 }
mortlen { 10 }
- pcodenk { 1 }
+ pcodenk { 0 }
+ postcode_full { "SW1A 1AA" }
is_la_inferred { false }
mortgagelender { 5 }
extrabor { 1 }
diff --git a/spec/factories/section.rb b/spec/factories/section.rb
new file mode 100644
index 000000000..71bfd52ae
--- /dev/null
+++ b/spec/factories/section.rb
@@ -0,0 +1,16 @@
+FactoryBot.define do
+ factory :section, class: "Form::Section" do
+ id { "section_id" }
+ initialize_with { new(id, nil, nil) }
+ trait :with_questions do
+ transient do
+ question_ids { nil }
+ questions { nil }
+ end
+
+ after :build do |section, evaluator|
+ section.subsections = [build(:subsection, :with_questions, question_ids: evaluator.question_ids, questions: evaluator.questions, section:)]
+ end
+ end
+ end
+end
diff --git a/spec/factories/subsection.rb b/spec/factories/subsection.rb
new file mode 100644
index 000000000..f4e4b307e
--- /dev/null
+++ b/spec/factories/subsection.rb
@@ -0,0 +1,20 @@
+FactoryBot.define do
+ factory :subsection, class: "Form::Subsection" do
+ id { "subsection_id" }
+ initialize_with { new(id, nil, nil) }
+ trait :with_questions do
+ transient do
+ question_ids { nil }
+ questions { nil }
+ end
+
+ after :build do |subsection, evaluator|
+ subsection.pages = if evaluator.questions
+ evaluator.questions.map { |question| build(:page, :with_question, question:, subsection:) }
+ else
+ evaluator.question_ids.map { |question_id| build(:page, :with_question, question_id:, subsection:) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/form/validations_spec.rb b/spec/features/form/validations_spec.rb
index 12e5bb657..420114129 100644
--- a/spec/features/form/validations_spec.rb
+++ b/spec/features/form/validations_spec.rb
@@ -138,28 +138,62 @@ RSpec.describe "validations" do
let(:income_over_soft_limit) { 750 }
let(:income_under_soft_limit) { 700 }
- it "prompts the user to confirm the value is correct with an interruption screen" do
+ before do
visit("/lettings-logs/#{lettings_log.id}/net-income")
fill_in("lettings-log-earnings-field", with: income_over_soft_limit)
choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue")
+ end
+
+ it "prompts the user to confirm the value is correct with an interruption screen" do
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
- expect(page).to have_content("Net income is outside the expected range based on the lead tenant’s working situation")
- expect(page).to have_content("You told us the lead tenant’s working situation is: full-time – 30 hours or more")
- expect(page).to have_content("The household income you have entered is £750.00 every week")
- choose("lettings-log-net-income-value-check-0-field", allow_label_click: true)
- click_button("Save and continue")
+ expect(page).to have_content("You told us the lead tenant’s income is £750.00 weekly.")
+ expect(page).to have_content("This is higher than we would expect for their working situation.")
+ click_button("Confirm and continue")
expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-uc-proportion")
end
- it "returns the user to the previous question if they do not confirm the value as correct on the interruption screen" do
- visit("/lettings-logs/#{lettings_log.id}/net-income")
- fill_in("lettings-log-earnings-field", with: income_over_soft_limit)
+ it "allows to fix the questions that trigger the soft validation" do
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen").twice
+ expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen", match: :first)
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen")
+ fill_in("lettings-log-earnings-field", with: income_under_soft_limit)
choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue")
- choose("lettings-log-net-income-value-check-1-field", allow_label_click: true)
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ expect(page).not_to have_content("You told us the lead tenant’s income is £750.00 weekly.")
+ expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
+ end
+
+ it "allows to fix the questions from different sections" do
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen").twice
+ expect(page).to have_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ click_link("Change", href: "/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/person-1-working-situation?referrer=interruption_screen")
+ choose("lettings-log-ecstat1-10-field", allow_label_click: true)
+ click_button("Save and continue")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check")
+ expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success")
+ end
+
+ it "returns the user back to the check_your_answers after fixing a validation from check_your_anwers" do
+ lettings_log.update!(earnings: income_over_soft_limit, incfreq: 1)
+ visit("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers")
+ click_link("Answer", href: "/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers")
+ click_link("Change", href: "/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen", match: :first)
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income?referrer=interruption_screen")
+ fill_in("lettings-log-earnings-field", with: income_under_soft_limit)
+ choose("lettings-log-incfreq-1-field", allow_label_click: true)
click_button("Save and continue")
- expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/net-income-value-check?referrer=check_answers")
+ click_button("Confirm and continue")
+ expect(page).to have_current_path("/lettings-logs/#{lettings_log.id}/income-and-benefits/check-answers")
end
end
end
diff --git a/spec/fixtures/files/sales_logs_csv_export_codes.csv b/spec/fixtures/files/sales_logs_csv_export_codes.csv
new file mode 100644
index 000000000..89a6a27bd
--- /dev/null
+++ b/spec/fixtures/files/sales_logs_csv_export_codes.csv
@@ -0,0 +1,2 @@
+id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by_name,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
+,completed,2023-02-08T16:52:15+00:00,2023-02-08T16:52:15+00:00,,2022,single log,false,DLUHC,Danny Rojas,2,2,2023,,2,8,,,,1,1,2,1,1,0,,,,,,,SW1A,1AA,1,E09000003,Barnet,1,2,1,30,X,17,17,18,1,1,P,35,X,,,,1,1,1,C,14,X,9,X,18,X,3,R,40,X,2,R,40,X,1,1,1,,,0,,,1,1,1,1,,,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,1000.0,,1,100.0,,10000.0
diff --git a/spec/fixtures/files/sales_logs_csv_export_labels.csv b/spec/fixtures/files/sales_logs_csv_export_labels.csv
new file mode 100644
index 000000000..c17122c18
--- /dev/null
+++ b/spec/fixtures/files/sales_logs_csv_export_labels.csv
@@ -0,0 +1,2 @@
+id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by_name,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
+,completed,2023-02-08T16:52:15+00:00,2023-02-08T16:52:15+00:00,,2022,single log,false,DLUHC,Danny Rojas,2,2,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,2,Flat or maisonette,Purpose built,Yes,,,,,,,SW1A,1AA,Yes,E09000003,Barnet,Yes,Yes,1,30,Non-binary,Buyer 1 prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,,,,Full-time - 30 hours or more,Yes,1,Child,14,Non-binary,Child under 16,Other,18,Non-binary,"In government training into work, such as New Deal",Person prefers not to say,40,Non-binary,Part-time - Less than 30 hours,Person prefers not to say,40,Non-binary,Full-time - 30 hours or more,Local authority tenant,No,,,No,,,1,1,1,1,,,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,Don’t know ,No,,Yes,2,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,1000.0,,Yes,100.0,,10000.0
diff --git a/spec/fixtures/forms/2021_2022.json b/spec/fixtures/forms/2021_2022.json
index 139ac8399..5a400d095 100644
--- a/spec/fixtures/forms/2021_2022.json
+++ b/spec/fixtures/forms/2021_2022.json
@@ -226,7 +226,8 @@
"operand": 50
}
}
- ]
+ ],
+ "interruption_screen_question_ids": ["age1", "ecstat1"]
},
"person_2_working_situation": {
"header": "",
@@ -740,27 +741,43 @@
}
],
"title_text": {
- "translation": "soft_validations.net_income.title_text"
- },
- "informative_text": {
- "translation": "soft_validations.net_income.hint_text",
+ "translation": "soft_validations.net_income.title_text",
"arguments": [
{
- "key": "ecstat1",
+ "key": "incfreq",
"label": true,
- "i18n_template": "ecstat1"
+ "i18n_template": "incfreq"
},
{
- "key": "earnings",
- "label": true,
+ "key": "field_formatted_as_currency",
+ "arguments_for_key": "earnings",
"i18n_template": "earnings"
}
]
},
+ "informative_text": {
+ "translation": "soft_validations.net_income.hint_text",
+ "arguments": [
+ {
+ "key": "net_income_higher_or_lower_text",
+ "label": false,
+ "i18n_template": "net_income_higher_or_lower_text"
+ }
+ ]
+ },
"questions": {
"net_income_value_check": {
"check_answer_label": "Net income soft validation",
- "hidden_in_check_answers": true,
+ "hidden_in_check_answers": {
+ "depends_on": [
+ {
+ "net_income_value_check": 0
+ },
+ {
+ "net_income_value_check": 1
+ }
+ ]
+ },
"header": "Are you sure this is correct?",
"type": "interruption_screen",
"answer_options": {
@@ -772,7 +789,8 @@
}
}
}
- }
+ },
+ "interruption_screen_question_ids": ["ecstat1", "incfreq", "earnings"]
},
"net_income_uc_proportion": {
"questions": {
diff --git a/spec/helpers/form_page_helper_spec.rb b/spec/helpers/form_page_helper_spec.rb
new file mode 100644
index 000000000..aeded6f8d
--- /dev/null
+++ b/spec/helpers/form_page_helper_spec.rb
@@ -0,0 +1,28 @@
+require "rails_helper"
+
+RSpec.describe FormPageHelper do
+ describe "#action_href" do
+ let(:lettings_log) { FactoryBot.create(:lettings_log) }
+ let(:sales_log) { FactoryBot.create(:sales_log) }
+
+ context "with a lettings log" do
+ it "has an update answer link href helper" do
+ expect(action_href(lettings_log, "net_income")).to eq("/lettings-logs/#{lettings_log.id}/net-income?referrer=check_answers")
+ end
+
+ it "returns a correct referrer in the url" do
+ expect(action_href(lettings_log, "retirement_value_check", "interruption_screen")).to eq("/lettings-logs/#{lettings_log.id}/retirement-value-check?referrer=interruption_screen")
+ end
+ end
+
+ context "with a sales log" do
+ it "has an update answer link href helper" do
+ expect(action_href(sales_log, "buyer_1_age")).to eq("/sales-logs/#{sales_log.id}/buyer-1-age?referrer=check_answers")
+ end
+
+ it "returns a correct referrer in the url" do
+ expect(action_href(sales_log, "grant_value_check", "interruption_screen")).to eq("/sales-logs/#{sales_log.id}/grant-value-check?referrer=interruption_screen")
+ end
+ end
+ end
+end
diff --git a/spec/helpers/interruption_screen_helper_spec.rb b/spec/helpers/interruption_screen_helper_spec.rb
index 33553f39f..6d9122f27 100644
--- a/spec/helpers/interruption_screen_helper_spec.rb
+++ b/spec/helpers/interruption_screen_helper_spec.rb
@@ -34,14 +34,9 @@ RSpec.describe InterruptionScreenHelper do
"translation" => "soft_validations.net_income.hint_text",
"arguments" => [
{
- "key" => "ecstat1",
- "label" => true,
- "i18n_template" => "ecstat1",
- },
- {
- "key" => "earnings",
- "label" => true,
- "i18n_template" => "earnings",
+ "key" => "net_income_higher_or_lower_text",
+ "label" => false,
+ "i18n_template" => "net_income_higher_or_lower_text",
},
],
}
@@ -49,8 +44,7 @@ RSpec.describe InterruptionScreenHelper do
.to eq(
I18n.t(
"soft_validations.net_income.hint_text",
- ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase,
- earnings: lettings_log.form.get_question("earnings", lettings_log).answer_label(lettings_log),
+ net_income_higher_or_lower_text: "higher",
),
)
end
@@ -241,4 +235,13 @@ RSpec.describe InterruptionScreenHelper do
end
end
end
+
+ describe "soft_validation_affected_questions" do
+ let(:question) { lettings_log.form.get_question("retirement_value_check", lettings_log) }
+
+ it "returns a list of questions affected by the soft validation" do
+ expect(soft_validation_affected_questions(question, lettings_log).count).to eq(2)
+ expect(soft_validation_affected_questions(question, lettings_log).map(&:id)).to eq(%w[age1 ecstat1])
+ end
+ end
end
diff --git a/spec/jobs/email_csv_job_spec.rb b/spec/jobs/email_csv_job_spec.rb
index 29dceff59..40f13e022 100644
--- a/spec/jobs/email_csv_job_spec.rb
+++ b/spec/jobs/email_csv_job_spec.rb
@@ -26,6 +26,7 @@ describe EmailCsvJob do
let(:storage_service) { instance_double(Storage::S3Service) }
let(:mailer) { instance_double(CsvDownloadMailer) }
+ let(:sales_log_csv_service) { instance_double(Csv::SalesLogCsvService) }
before do
FactoryBot.create(:lettings_log,
@@ -39,18 +40,44 @@ describe EmailCsvJob do
allow(storage_service).to receive(:write_file)
allow(storage_service).to receive(:get_presigned_url).and_return(test_url)
+ allow(Csv::SalesLogCsvService).to receive(:new).and_return(sales_log_csv_service)
+ allow(sales_log_csv_service).to receive(:prepare_csv).and_return("")
+
allow(CsvDownloadMailer).to receive(:new).and_return(mailer)
allow(mailer).to receive(:send_csv_download_mail)
end
- it "uses an appropriate filename in S3" do
- expect(storage_service).to receive(:write_file).with(/logs-.*\.csv/, anything)
- job.perform(user)
+ context "when exporting lettings logs" do
+ it "uses an appropriate filename in S3" do
+ expect(storage_service).to receive(:write_file).with(/lettings-logs-.*\.csv/, anything)
+ job.perform(user)
+ end
+
+ it "includes the organisation name in the filename when one is provided" do
+ expect(storage_service).to receive(:write_file).with(/lettings-logs-#{organisation.name}-.*\.csv/, anything)
+ job.perform(user, nil, {}, nil, organisation)
+ end
end
- it "includes the organisation name in the filename when one is provided" do
- expect(storage_service).to receive(:write_file).with(/logs-#{organisation.name}-.*\.csv/, anything)
- job.perform(user, nil, {}, nil, organisation)
+ context "when exporting sales logs" do
+ it "uses an appropriate filename in S3" do
+ expect(storage_service).to receive(:write_file).with(/sales-logs-.*\.csv/, anything)
+ job.perform(user, nil, {}, nil, nil, nil, "sales")
+ end
+
+ it "includes the organisation name in the filename when one is provided" do
+ expect(storage_service).to receive(:write_file).with(/sales-logs-#{organisation.name}-.*\.csv/, anything)
+ job.perform(user, nil, {}, nil, organisation, nil, "sales")
+ end
+
+ it "creates a SalesLogCsvService with the correct export type" do
+ expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "labels")
+ codes_only = false
+ job.perform(user, nil, {}, nil, nil, codes_only, "sales")
+ expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "codes")
+ codes_only = true
+ job.perform(user, nil, {}, nil, nil, codes_only, "sales")
+ end
end
it "sends an E-mail with the presigned URL and duration" do
diff --git a/spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb b/spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb
index c81538146..6d2b8f7a8 100644
--- a/spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb
@@ -41,4 +41,8 @@ RSpec.describe Form::Lettings::Pages::CareHomeChargesValueCheck, type: :model do
it "has the correct informative_text" do
expect(page.informative_text).to eq("")
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[chcharge is_carehome])
+ end
end
diff --git a/spec/models/form/lettings/pages/max_rent_value_check_spec.rb b/spec/models/form/lettings/pages/max_rent_value_check_spec.rb
index 1d712d886..5d803252b 100644
--- a/spec/models/form/lettings/pages/max_rent_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/max_rent_value_check_spec.rb
@@ -34,4 +34,8 @@ RSpec.describe Form::Lettings::Pages::MaxRentValueCheck, type: :model do
it "has the correct informative_text" do
expect(page.informative_text).to eq({ "arguments" => [{ "arguments_for_key" => "soft_max_for_period", "i18n_template" => "soft_max_for_period", "key" => "field_formatted_as_currency" }], "translation" => "soft_validations.rent.max_hint_text" })
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[brent startdate la beds rent_type needstype])
+ end
end
diff --git a/spec/models/form/lettings/pages/min_rent_value_check_spec.rb b/spec/models/form/lettings/pages/min_rent_value_check_spec.rb
index 818599b06..e4b6b5478 100644
--- a/spec/models/form/lettings/pages/min_rent_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/min_rent_value_check_spec.rb
@@ -52,4 +52,8 @@ RSpec.describe Form::Lettings::Pages::MinRentValueCheck, type: :model do
],
})
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[brent startdate la beds rent_type needstype])
+ end
end
diff --git a/spec/models/form/lettings/pages/net_income_value_check_spec.rb b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
index c43eb3381..f07ec84ab 100644
--- a/spec/models/form/lettings/pages/net_income_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
@@ -28,12 +28,12 @@ RSpec.describe Form::Lettings::Pages::NetIncomeValueCheck, type: :model do
end
it "has the correct title_text" do
- expect(page.title_text).to eq({ "translation" => "soft_validations.net_income.title_text" })
+ expect(page.title_text).to eq({ "translation" => "soft_validations.net_income.title_text", "arguments" => [{ "i18n_template" => "incfreq", "key" => "incfreq", "label" => true }, { "arguments_for_key" => "earnings", "i18n_template" => "earnings", "key" => "field_formatted_as_currency" }] })
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({
- "arguments" => [{ "arguments_for_key" => "ecstat1", "i18n_template" => "ecstat1", "key" => "field_formatted_as_currency" }, { "arguments_for_key" => "earnings", "i18n_template" => "earnings", "key" => "field_formatted_as_currency" }],
+ "arguments" => [{ "i18n_template" => "net_income_higher_or_lower_text", "key" => "net_income_higher_or_lower_text", "label" => false }],
"translation" => "soft_validations.net_income.hint_text",
})
end
diff --git a/spec/models/form/lettings/pages/person_under_retirement_value_check_spec.rb b/spec/models/form/lettings/pages/person_under_retirement_value_check_spec.rb
index a2a6dd20f..929009ce7 100644
--- a/spec/models/form/lettings/pages/person_under_retirement_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/person_under_retirement_value_check_spec.rb
@@ -39,8 +39,8 @@ RSpec.describe Form::Lettings::Pages::PersonUnderRetirementValueCheck, type: :mo
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_2",
- "label" => false,
+ "key" => "age2",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -48,21 +48,7 @@ RSpec.describe Form::Lettings::Pages::PersonUnderRetirementValueCheck, type: :mo
end
it "has the correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_2",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_2",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
end
end
@@ -84,8 +70,8 @@ RSpec.describe Form::Lettings::Pages::PersonUnderRetirementValueCheck, type: :mo
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_3",
- "label" => false,
+ "key" => "age3",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -93,21 +79,7 @@ RSpec.describe Form::Lettings::Pages::PersonUnderRetirementValueCheck, type: :mo
end
it "has the correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_3",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_3",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
end
end
end
diff --git a/spec/models/form/question_spec.rb b/spec/models/form/question_spec.rb
index ede6636f7..751523d37 100644
--- a/spec/models/form/question_spec.rb
+++ b/spec/models/form/question_spec.rb
@@ -257,11 +257,6 @@ RSpec.describe Form::Question, type: :model do
expect(question.action_text(lettings_log)).to match(/Change/)
end
- it "has an update answer link href helper" do
- lettings_log.id = 1
- expect(question.action_href(lettings_log, page.id)).to eq("/lettings-logs/1/net-income?referrer=check_answers")
- end
-
context "when the question has an inferred answer" do
let(:section_id) { "tenancy_and_property" }
let(:subsection_id) { "property_information" }
diff --git a/spec/models/form/sales/pages/about_price_value_check_spec.rb b/spec/models/form/sales/pages/about_price_value_check_spec.rb
index 6c8d27463..881969703 100644
--- a/spec/models/form/sales/pages/about_price_value_check_spec.rb
+++ b/spec/models/form/sales/pages/about_price_value_check_spec.rb
@@ -45,10 +45,14 @@ RSpec.describe Form::Sales::Pages::AboutPriceValueCheck, type: :model do
"i18n_template" => "soft_min_or_soft_max",
},
{
- "key" => "purchase_price_min_or_max_text",
- "i18n_template" => "min_or_max",
+ "key" => "purchase_price_higher_or_lower_text",
+ "i18n_template" => "higher_or_lower",
},
],
})
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[value beds la])
+ end
end
diff --git a/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb b/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb
index f770bd651..8aa6ef233 100644
--- a/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb
+++ b/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb
@@ -34,4 +34,8 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeValueCheck, type: :model do
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
+
+ it "is has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[ecstat1 income1])
+ end
end
diff --git a/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb b/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb
index 9d00b086b..22d1433bc 100644
--- a/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb
+++ b/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb
@@ -43,6 +43,10 @@ RSpec.describe Form::Sales::Pages::BuyerLiveInValueCheck, type: :model do
})
end
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[ownershipsch buy1livein])
+ end
+
context "with buyer 2" do
let(:person_index) { 2 }
@@ -60,5 +64,9 @@ RSpec.describe Form::Sales::Pages::BuyerLiveInValueCheck, type: :model do
"arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
})
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[ownershipsch buy2livein])
+ end
end
end
diff --git a/spec/models/form/sales/pages/deposit_value_check_spec.rb b/spec/models/form/sales/pages/deposit_value_check_spec.rb
index 91e1cccc5..9f8c99966 100644
--- a/spec/models/form/sales/pages/deposit_value_check_spec.rb
+++ b/spec/models/form/sales/pages/deposit_value_check_spec.rb
@@ -34,4 +34,8 @@ RSpec.describe Form::Sales::Pages::DepositValueCheck, type: :model do
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
+
+ it "is has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[savings deposit])
+ end
end
diff --git a/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb b/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
index d086542dc..ce0d7be8e 100644
--- a/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
+++ b/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
@@ -49,4 +49,8 @@ RSpec.describe Form::Sales::Pages::DiscountedSaleValueCheck, type: :model do
},
])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[value deposit ownershipsch mortgage mortgageused discount grant type])
+ end
end
diff --git a/spec/models/form/sales/pages/handover_date_check_spec.rb b/spec/models/form/sales/pages/handover_date_check_spec.rb
index 6bd3f3874..cd358a2b8 100644
--- a/spec/models/form/sales/pages/handover_date_check_spec.rb
+++ b/spec/models/form/sales/pages/handover_date_check_spec.rb
@@ -44,4 +44,8 @@ RSpec.describe Form::Sales::Pages::HandoverDateCheck, type: :model do
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
+
+ it "is has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[hodate saledate])
+ end
end
diff --git a/spec/models/form/sales/pages/household_wheelchair_check_spec.rb b/spec/models/form/sales/pages/household_wheelchair_check_spec.rb
index 4eb6182d9..20d0a325f 100644
--- a/spec/models/form/sales/pages/household_wheelchair_check_spec.rb
+++ b/spec/models/form/sales/pages/household_wheelchair_check_spec.rb
@@ -34,4 +34,8 @@ RSpec.describe Form::Sales::Pages::HouseholdWheelchairCheck, type: :model do
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
+
+ it "is has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[disabled wheel])
+ end
end
diff --git a/spec/models/form/sales/pages/monthly_charges_value_check_spec.rb b/spec/models/form/sales/pages/monthly_charges_value_check_spec.rb
index ac378dc82..5add5d8e7 100644
--- a/spec/models/form/sales/pages/monthly_charges_value_check_spec.rb
+++ b/spec/models/form/sales/pages/monthly_charges_value_check_spec.rb
@@ -38,11 +38,15 @@ RSpec.describe Form::Sales::Pages::MonthlyChargesValueCheck, type: :model do
it "has correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.monthly_charges_over_soft_max.title_text",
- "arguments" => [],
+ "arguments" => [{ "arguments_for_key" => "mscharge", "i18n_template" => "mscharge", "key" => "field_formatted_as_currency" }],
})
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({})
+ expect(page.informative_text).to eq({ "arguments" => [], "translation" => "soft_validations.monthly_charges_over_soft_max.hint_text" })
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[type mscharge proptype])
end
end
diff --git a/spec/models/form/sales/pages/mortgage_value_check_spec.rb b/spec/models/form/sales/pages/mortgage_value_check_spec.rb
index 8c7375f81..f33525652 100644
--- a/spec/models/form/sales/pages/mortgage_value_check_spec.rb
+++ b/spec/models/form/sales/pages/mortgage_value_check_spec.rb
@@ -36,6 +36,10 @@ RSpec.describe Form::Sales::Pages::MortgageValueCheck, type: :model do
])
end
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[mortgage inc1mort inc2mort jointpur income1 income2 inc1mort inc2mort])
+ end
+
context "when checking buyer 2" do
let(:index) { 2 }
diff --git a/spec/models/form/sales/pages/old_persons_shared_ownership_value_check_spec.rb b/spec/models/form/sales/pages/old_persons_shared_ownership_value_check_spec.rb
index 05b6f7734..d9c4beed9 100644
--- a/spec/models/form/sales/pages/old_persons_shared_ownership_value_check_spec.rb
+++ b/spec/models/form/sales/pages/old_persons_shared_ownership_value_check_spec.rb
@@ -33,12 +33,16 @@ RSpec.describe Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck, type: :m
it "has the correct title_text" do
expect(page.title_text).to eq({
- "translation" => "soft_validations.old_persons_shared_ownership",
+ "translation" => "soft_validations.old_persons_shared_ownership.title_text",
"arguments" => [],
})
end
it "has the correct informative_text" do
- expect(page.informative_text).to eq({})
+ expect(page.informative_text).to eq({ "arguments" => [], "translation" => "soft_validations.old_persons_shared_ownership.hint_text" })
+ end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[type jointpur age1 age2])
end
end
diff --git a/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb b/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb
index d933e3278..6b1fc36a4 100644
--- a/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb
+++ b/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb
@@ -31,7 +31,10 @@ RSpec.describe Form::Sales::Pages::PercentageDiscountValueCheck, type: :model do
end
it "has the correct informative_text" do
- expect(page.informative_text).to eq({})
+ expect(page.informative_text).to eq({
+ "translation" => "soft_validations.percentage_discount_value.hint_text",
+ "arguments" => [],
+ })
end
it "is interruption screen page" do
@@ -45,4 +48,8 @@ RSpec.describe Form::Sales::Pages::PercentageDiscountValueCheck, type: :model do
},
])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[discount proptype])
+ end
end
diff --git a/spec/models/form/sales/pages/person_student_not_child_value_check_spec.rb b/spec/models/form/sales/pages/person_student_not_child_value_check_spec.rb
index 3499cda9f..c0d1b2734 100644
--- a/spec/models/form/sales/pages/person_student_not_child_value_check_spec.rb
+++ b/spec/models/form/sales/pages/person_student_not_child_value_check_spec.rb
@@ -39,6 +39,10 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
expect(page.questions.map(&:id)).to eq(%w[student_not_child_value_check])
end
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat2 ecstat2 age2])
+ end
+
context "with person 2" do
let(:person_index) { 2 }
let(:page_id) { "person_2_student_not_child_value_check" }
@@ -50,6 +54,10 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "person_2_student_not_child?" => true }])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat2 ecstat2 age2])
+ end
end
context "with person 3" do
@@ -63,6 +71,10 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "person_3_student_not_child?" => true }])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat3 ecstat3 age3])
+ end
end
context "with person 4" do
@@ -76,6 +88,10 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "person_4_student_not_child?" => true }])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat4 ecstat4 age4])
+ end
end
context "with person 5" do
@@ -89,6 +105,10 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "person_5_student_not_child?" => true }])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat5 ecstat5 age5])
+ end
end
context "with person 6" do
@@ -102,5 +122,9 @@ RSpec.describe Form::Sales::Pages::PersonStudentNotChildValueCheck, type: :model
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "person_6_student_not_child?" => true }])
end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[relat6 ecstat6 age6])
+ end
end
end
diff --git a/spec/models/form/sales/pages/retirement_value_check_spec.rb b/spec/models/form/sales/pages/retirement_value_check_spec.rb
index 76599d982..b09760ff5 100644
--- a/spec/models/form/sales/pages/retirement_value_check_spec.rb
+++ b/spec/models/form/sales/pages/retirement_value_check_spec.rb
@@ -46,8 +46,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_1",
- "label" => false,
+ "key" => "age1",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -55,21 +55,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_1",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_1",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age1 ecstat1])
end
end
@@ -94,8 +84,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_2",
- "label" => false,
+ "key" => "age2",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -103,21 +93,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_2",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_2",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age2 ecstat2])
end
end
@@ -142,8 +122,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_3",
- "label" => false,
+ "key" => "age3",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -151,21 +131,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_3",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_3",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age3 ecstat3])
end
end
@@ -190,8 +160,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_4",
- "label" => false,
+ "key" => "age4",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -199,21 +169,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_4",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_4",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age4 ecstat4])
end
end
@@ -238,8 +198,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_5",
- "label" => false,
+ "key" => "age5",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -247,21 +207,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_5",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_5",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age5 ecstat5])
end
end
@@ -286,8 +236,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
"translation" => "soft_validations.retirement.min.title",
"arguments" => [
{
- "key" => "retirement_age_for_person_6",
- "label" => false,
+ "key" => "age6",
+ "label" => true,
"i18n_template" => "age",
},
],
@@ -295,21 +245,11 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end
it "has correct informative_text" do
- expect(page.informative_text).to eq({
- "translation" => "soft_validations.retirement.min.hint_text",
- "arguments" => [
- {
- "key" => "plural_gender_for_person_6",
- "label" => false,
- "i18n_template" => "gender",
- },
- {
- "key" => "retirement_age_for_person_6",
- "label" => false,
- "i18n_template" => "age",
- },
- ],
- })
+ expect(page.informative_text).to eq({})
+ end
+
+ it "has correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[age6 ecstat6])
end
end
end
diff --git a/spec/models/form/sales/pages/savings_value_check_spec.rb b/spec/models/form/sales/pages/savings_value_check_spec.rb
index 80606afb5..cfff9c74d 100644
--- a/spec/models/form/sales/pages/savings_value_check_spec.rb
+++ b/spec/models/form/sales/pages/savings_value_check_spec.rb
@@ -34,4 +34,8 @@ RSpec.describe Form::Sales::Pages::SavingsValueCheck, type: :model do
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[savings])
+ end
end
diff --git a/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb b/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
index 45744cde4..9a184a6fc 100644
--- a/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
+++ b/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
@@ -34,11 +34,15 @@ RSpec.describe Form::Sales::Pages::SharedOwnershipDepositValueCheck, type: :mode
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.shared_ownership_deposit.title_text",
- "arguments" => [{ "arguments_for_key" => "expected_shared_ownership_deposit_value", "i18n_template" => "expected_shared_ownership_deposit_value", "key" => "field_formatted_as_currency" }],
+ "arguments" => [{ "arguments_for_key" => "mortgage_deposit_and_discount_total", "i18n_template" => "mortgage_deposit_and_discount_total", "key" => "field_formatted_as_currency" }],
})
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({})
end
+
+ it "has the correct interruption_screen_question_ids" do
+ expect(page.interruption_screen_question_ids).to eq(%w[mortgage mortgageused cashdis type deposit value equity])
+ end
end
diff --git a/spec/models/form/sales/questions/household_wheelchair_check_spec.rb b/spec/models/form/sales/questions/household_wheelchair_check_spec.rb
index 92f80fdb1..d203ee444 100644
--- a/spec/models/form/sales/questions/household_wheelchair_check_spec.rb
+++ b/spec/models/form/sales/questions/household_wheelchair_check_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Form::Sales::Questions::HouseholdWheelchairCheck, type: :model do
end
it "has the correct header" do
- expect(question.header).to eq("Are you sure? You said previously that somebody in household uses a wheelchair")
+ expect(question.header).to eq("You told us that someone in the household uses a wheelchair.")
end
it "has the correct check_answer_label" do
diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb
index bbeb56e55..547ed2f21 100644
--- a/spec/models/form_handler_spec.rb
+++ b/spec/models/form_handler_spec.rb
@@ -219,5 +219,56 @@ RSpec.describe FormHandler do
end
end
end
+
+ describe "#ordered_sales_questions_for_all_years" do
+ let(:result) { described_class.instance.ordered_sales_questions_for_all_years }
+ let(:now) { Time.zone.now }
+
+ it "returns an array of questions" do
+ section = build(:section, :with_questions, question_ids: %w[1 2 3])
+ sales_form = FormFactory.new(year: 1936, type: "sales")
+ .with_sections([section])
+ .build
+ described_class.instance.use_fake_forms!({ only_sales: sales_form })
+ expect(result).to(satisfy { |result| result.all? { |element| element.is_a?(Form::Question) } })
+ end
+
+ it "does not return multiple questions with the same id" do
+ first_section = build(:section, :with_questions, question_ids: %w[1 2 3])
+ second_section = build(:section, :with_questions, question_ids: %w[2 3 4 5])
+ sales_form = FormFactory.new(year: 1936, type: "sales")
+ .with_sections([first_section, second_section])
+ .build
+ described_class.instance.use_fake_forms!({ only_sales: sales_form })
+ expect(result.map(&:id)).to eq %w[1 2 3 4 5]
+ end
+
+ it "returns the questions in the same order as the form" do
+ first_section = build(:section, :with_questions, question_ids: %w[1 2 3])
+ second_section = build(:section, :with_questions, question_ids: %w[4 5 6])
+ sales_form = FormFactory.new(year: 1945, type: "sales")
+ .with_sections([first_section, second_section])
+ .build
+ described_class.instance.use_fake_forms!({ only_sales: sales_form })
+ expect(result.map(&:id)).to eq %w[1 2 3 4 5 6]
+ end
+
+ it "inserts questions from all years in their correct positions" do
+ original_section = build(:section, :with_questions, question_ids: %w[1 1a_deprecated 2 3])
+ new_section = build(:section, :with_questions, question_ids: %w[1 2 2a_new 3])
+ original_form = FormFactory.new(year: 1066, type: "sales")
+ .with_sections([original_section])
+ .build
+ new_form = FormFactory.new(year: 1485, type: "sales")
+ .with_sections([new_section])
+ .build
+ fake_forms = {
+ earlier_sales: original_form,
+ newer_sales: new_form,
+ }
+ described_class.instance.use_fake_forms!(fake_forms)
+ expect(result.map(&:id)).to eq %w[1 1a_deprecated 2 2a_new 3]
+ end
+ end
# rubocop:enable RSpec/PredicateMatcher
end
diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb
index 05da0a5a8..5e661fe16 100644
--- a/spec/models/lettings_log_spec.rb
+++ b/spec/models/lettings_log_spec.rb
@@ -268,13 +268,6 @@ RSpec.describe LettingsLog do
expect(record_from_db["mrcdate"].year).to eq(2021)
end
- it "correctly derives and saves partial and full major property void date" do
- record_from_db = ActiveRecord::Base.connection.execute("select voiddate from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["voiddate"].day).to eq(3)
- expect(record_from_db["voiddate"].month).to eq(3)
- expect(record_from_db["voiddate"].year).to eq(2021)
- end
-
it "correctly derives and saves incref" do
record_from_db = ActiveRecord::Base.connection.execute("select incref from lettings_logs where id=#{lettings_log.id}").to_a[0]
expect(record_from_db["incref"]).to eq(1)
@@ -1504,334 +1497,329 @@ RSpec.describe LettingsLog do
expect(record_from_db["has_benefits"]).to eq(1)
end
- context "when it is a renewal" do
+ context "when updating values that derive vacdays" do
+ let(:lettings_log) { create(:lettings_log, startdate:) }
+
+ context "when start date is set" do
+ let(:startdate) { Time.zone.now }
+
+ it "correctly derives vacdays when voiddate is set" do
+ day_count = 3
+ expect { lettings_log.update!(voiddate: startdate - day_count.days) }.to change(lettings_log, :vacdays).to day_count
+ expect { lettings_log.update!(voiddate: nil) }.to change(lettings_log, :vacdays).from(day_count).to nil
+ end
+
+ it "correctly derives vacdays when mrcdate is set" do
+ day_count = 3
+ expect { lettings_log.update!(mrcdate: startdate - day_count.days) }.to change(lettings_log, :vacdays).to day_count
+ expect { lettings_log.update!(mrcdate: nil) }.to change(lettings_log, :vacdays).from(day_count).to nil
+ end
+ end
+
+ context "when start date is not set" do
+ let(:startdate) { nil }
+
+ it "correctly derives vacdays when voiddate is set" do
+ day_count = 3
+ lettings_log.update!(voiddate: Time.zone.now - day_count.days)
+ expect(lettings_log.vacdays).to be nil
+ end
+
+ it "correctly derives vacdays when mrcdate is set" do
+ day_count = 3
+ lettings_log.update!(mrcdate: Time.zone.now - day_count.days)
+ expect(lettings_log.vacdays).to be nil
+ end
+ end
+ end
+
+ context "when updating renewal" do
let!(:lettings_log) do
described_class.create({
managing_organisation: owning_organisation,
owning_organisation:,
created_by: created_by_user,
- renewal: 1,
startdate: Time.zone.local(2021, 4, 10),
created_at: Time.utc(2022, 2, 8, 16, 52, 15),
})
end
- it "correctly derives and saves waityear" do
- record_from_db = ActiveRecord::Base.connection.execute("select waityear from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["waityear"]).to eq(2)
- expect(lettings_log["waityear"]).to eq(2)
+ it "correctly derives the length of time on local authority waiting list" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :waityear).to 2
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :waityear).from(2).to nil
end
- it "correctly derives and saves underoccupation_benefitcap if year is 2021" do
- record_from_db = ActiveRecord::Base.connection.execute("select underoccupation_benefitcap from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["underoccupation_benefitcap"]).to eq(2)
- expect(lettings_log["underoccupation_benefitcap"]).to eq(2)
+ it "correctly derives the number of times previously offered since becoming available" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :offered).to 0
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :offered).from(0).to nil
end
- it "correctly derives and saves prevten" do
- lettings_log.managing_organisation.update!({ provider_type: "PRP" })
- lettings_log.update!({ needstype: 1 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select prevten from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["prevten"]).to eq(32)
- expect(lettings_log["prevten"]).to eq(32)
+ it "correctly derives referral if the letting is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :referral).to 1
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :referral).from(1).to nil
+ end
- lettings_log.managing_organisation.update!({ provider_type: "LA" })
- lettings_log.update!({ needstype: 1 })
+ it "correctly derives voiddate if the letting is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :voiddate).to lettings_log.startdate
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :voiddate).from(lettings_log.startdate).to nil
+ end
- record_from_db = ActiveRecord::Base.connection.execute("select prevten from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["prevten"]).to eq(30)
- expect(lettings_log["prevten"]).to eq(30)
+ it "correctly derives first_time_property_let_as_social_housing and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :first_time_property_let_as_social_housing).to 0
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :first_time_property_let_as_social_housing).from(0).to nil
end
- it "correctly derives and saves referral" do
- record_from_db = ActiveRecord::Base.connection.execute("select referral from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["referral"]).to eq(1)
- expect(lettings_log["referral"]).to eq(1)
+ it "correctly derives vacancy reason and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :rsnvac).to 14
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :rsnvac).from(14).to nil
end
- it "correctly derives and saves vacdays" do
- record_from_db = ActiveRecord::Base.connection.execute("select vacdays from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["vacdays"]).to eq(0)
- expect(lettings_log["vacdays"]).to eq(0)
+ it "derives vacdays as 0 if log is renewal" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :vacdays).to 0
end
- it "correctly derives and saves first_time_property_let_as_social_housing" do
- record_from_db = ActiveRecord::Base.connection.execute(
- "select first_time_property_let_as_social_housing" \
- " from lettings_logs where id=#{lettings_log.id}",
- ).to_a[0]
- expect(record_from_db["first_time_property_let_as_social_housing"]).to eq(0)
- expect(lettings_log["first_time_property_let_as_social_housing"]).to eq(0)
+ it "correctly derives underoccupation_benefitcap if log is a renewal from 2021/22" do
+ lettings_log.update!(renewal: 1)
+ expect(lettings_log.underoccupation_benefitcap).to be 2
end
- it "derives vacancy reason as relet" do
- record_from_db = ActiveRecord::Base.connection.execute("select rsnvac from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["rsnvac"]).to eq(14)
- expect(lettings_log["rsnvac"]).to eq(14)
+ it "clears underoccupation_benefitcap if log is no longer a renewal" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :underoccupation_benefitcap).to 2
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :underoccupation_benefitcap).from(2).to nil
end
- context "when deriving renttype and unitletas" do
- before do
- Timecop.freeze(Time.zone.local(2022, 1, 1))
- allow(FeatureToggle).to receive(:startdate_two_week_validation_enabled?).and_return(false)
- lettings_log.update!(rent_type:, irproduct_other: "other")
- end
+ it "clears underoccupation_benefitcap if log is no longer in 2021/22" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :underoccupation_benefitcap).to 2
+ Timecop.return
+ expect { lettings_log.update!(startdate: Time.zone.local(2023, 1, 1)) }.to change(lettings_log, :underoccupation_benefitcap).from(2).to nil
+ end
- after do
- Timecop.unfreeze
- end
+ context "when the log is general needs" do
+ context "and the managing organisation is a private registered provider" do
+ before do
+ lettings_log.managing_organisation.update!(provider_type: "PRP")
+ lettings_log.update!(needstype: 1, renewal: 1)
+ end
- context "when the rent_type is Social Rent (0)" do
- let(:rent_type) { 0 }
+ it "correctly derives prevten" do
+ expect(lettings_log.prevten).to be 32
+ end
- it "derives and saves renttype and unitletas as Social rent(1)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(1)
- expect(record_from_db["renttype"]).to eq(1)
+ it "clears prevten if the log is marked as supported housing" do
+ lettings_log.update!(needstype: 2)
+ expect(lettings_log.prevten).to be nil
end
- it "derives and saves unitletas as Social rent(1)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(1)
- expect(record_from_db["unitletas"]).to eq(1)
+ it "clears prevten if renewal is update to no" do
+ lettings_log.update!(renewal: 0)
+ expect(lettings_log.prevten).to be nil
end
+ end
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
- end
+ context "and the managing organisation is a local authority" do
+ before do
+ lettings_log.managing_organisation.update!(provider_type: "LA")
+ lettings_log.update!(needstype: 1, renewal: 1)
+ end
- after do
- Timecop.unfreeze
- end
+ it "correctly derives prevten" do
+ expect(lettings_log.prevten).to be 30
+ end
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
- end
+ it "clears prevten if the log is marked as supported housing" do
+ expect { lettings_log.update!(needstype: 2) }.to change(lettings_log, :prevten).to nil
+ end
- it "derives and saves unitletas as Social rent(1)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(1)
- expect(record_from_db["unitletas"]).to eq(1)
- end
+ it "clears prevten if renewal is update to no" do
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :prevten).to nil
end
end
+ end
- context "when the rent_type is Affordable Rent(1)" do
- let(:rent_type) { 1 }
+ context "and updating rent_type" do
+ let(:irproduct_other) { nil }
- it "derives and saves renttype as Affordable Rent(2)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(2)
- expect(record_from_db["renttype"]).to eq(2)
+ around do |example|
+ Timecop.freeze(now) do
+ Singleton.__init__(FormHandler)
+ lettings_log.update!(rent_type:, irproduct_other:, startdate: now)
+ example.run
end
+ end
- it "derives and saves unitletas as Affordable Rent(2)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(2)
- expect(record_from_db["unitletas"]).to eq(2)
- end
+ context "when collection year is 2022/23 or earlier" do
+ let(:now) { Time.zone.local(2023, 1, 1) }
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
- end
+ context "when rent_type is Social Rent" do
+ let(:rent_type) { 0 }
- after do
- Timecop.unfreeze
+ it "derives the most recent let type as Social Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 1
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(1).to nil
end
+ end
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
- end
+ context "when rent_type is Affordable Rent" do
+ let(:rent_type) { 1 }
- it "derives and saves unitletas as Affordable Rent basis(2)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(2)
- expect(record_from_db["unitletas"]).to eq(2)
+ it "derives the most recent let type as Affordable Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 2
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(2).to nil
end
end
- end
- context "when the rent_type is London Affordable Rent(2)" do
- let(:rent_type) { 2 }
+ context "when rent_type is London Affordable Rent" do
+ let(:rent_type) { 2 }
- it "derives and saves renttype as London Affordable Rent(2)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(2)
- expect(record_from_db["renttype"]).to eq(2)
+ it "derives the most recent let type as Affordable Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 2
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(2).to nil
+ end
end
- it "derives and saves unitletas as London Affordable Rent(2)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(2)
- expect(record_from_db["unitletas"]).to eq(2)
- end
+ context "when rent_type is Rent to Buy" do
+ let(:rent_type) { 3 }
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
+ it "derives the most recent let type as Intermediate Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 4
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(4).to nil
end
+ end
- after do
- Timecop.unfreeze
- end
+ context "when rent_type is London Living Rent" do
+ let(:rent_type) { 4 }
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
+ it "derives the most recent let type as Intermediate Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 4
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(4).to nil
end
+ end
+
+ context "when rent_type is Other intermediate rent product" do
+ let(:rent_type) { 5 }
+ let(:irproduct_other) { "Rent first" }
- it "derives and saves unitletas as London Affordable Rent basis(5)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(5)
- expect(record_from_db["unitletas"]).to eq(5)
+ it "derives the most recent let type as Intermediate Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 4
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(4).to nil
end
end
end
- context "when the rent_type is Rent to Buy(3)" do
- let(:rent_type) { 3 }
+ context "when collection year is 2023/24 or later" do
+ let(:now) { Time.zone.local(2024, 1, 1) }
- it "derives and saves renttype as Intermediate Rent(3)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(3)
- expect(record_from_db["renttype"]).to eq(3)
- end
+ context "when rent_type is Social Rent" do
+ let(:rent_type) { 0 }
- it "derives and saves unitletas as Intermediate Rent(4)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(4)
- expect(record_from_db["unitletas"]).to eq(4)
+ it "derives the most recent let type as Social Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 1
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(1).to nil
+ end
end
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
- end
+ context "when rent_type is Affordable Rent" do
+ let(:rent_type) { 1 }
- after do
- Timecop.unfreeze
+ it "derives the most recent let type as Affordable Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 2
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(2).to nil
end
+ end
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
- end
+ context "when rent_type is London Affordable Rent" do
+ let(:rent_type) { 2 }
- it "derives and saves unitletas as Rent to Buy basis(6)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(6)
- expect(record_from_db["unitletas"]).to eq(6)
+ it "derives the most recent let type as London Affordable Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 5
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(5).to nil
end
end
- end
- context "when the rent_type is London Living Rent(4)" do
- let(:rent_type) { 4 }
+ context "when rent_type is Rent to Buy" do
+ let(:rent_type) { 3 }
- it "derives and saves renttype as Intermediate Rent(3)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(3)
- expect(record_from_db["renttype"]).to eq(3)
- end
-
- it "derives and saves unitletas as Intermediate Rent(4)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(4)
- expect(record_from_db["unitletas"]).to eq(4)
+ it "derives the most recent let type as Rent to Buy basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 6
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(6).to nil
+ end
end
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
- end
+ context "when rent_type is London Living Rent" do
+ let(:rent_type) { 4 }
- after do
- Timecop.unfreeze
+ it "derives the most recent let type as London Living Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 7
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(7).to nil
end
+ end
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
- end
+ context "when rent_type is Other intermediate rent product" do
+ let(:rent_type) { 5 }
+ let(:irproduct_other) { "Rent first" }
- it "derives and saves unitletas as London Living Rent basis(7)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(7)
- expect(record_from_db["unitletas"]).to eq(7)
+ it "derives the most recent let type as Another Intermediate Rent basis if it is a renewal and clears it if it is not" do
+ expect { lettings_log.update!(renewal: 1) }.to change(lettings_log, :unitletas).to 8
+ expect { lettings_log.update!(renewal: 0) }.to change(lettings_log, :unitletas).from(8).to nil
end
end
end
+ end
+ end
+
+ context "when updating rent type" do
+ let(:irproduct_other) { nil }
+
+ before do
+ lettings_log.update!(rent_type:, irproduct_other:)
+ end
+
+ context "when rent_type is Social Rent" do
+ let(:rent_type) { 0 }
+
+ it "derives renttype as Social Rent" do
+ expect(lettings_log.renttype).to be 1
+ end
+ end
- context "when the rent_type is Other intermediate rent product(5)" do
- let(:rent_type) { 5 }
+ context "when rent_type is Affordable Rent" do
+ let(:rent_type) { 1 }
- it "derives and saves renttype as Intermediate Rent(3)" do
- record_from_db = ActiveRecord::Base.connection.execute("select renttype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.renttype).to eq(3)
- expect(record_from_db["renttype"]).to eq(3)
- end
+ it "derives renttype as Affordable Rent" do
+ expect(lettings_log.renttype).to be 2
+ end
+ end
- it "derives and saves unitletas as Intermediate Rent(4)" do
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(4)
- expect(record_from_db["unitletas"]).to eq(4)
- end
+ context "when rent_type is London Affordable Rent" do
+ let(:rent_type) { 2 }
- context "and it is a 23/24 form" do
- before do
- Timecop.freeze(Time.zone.local(2023, 5, 1))
- end
+ it "derives renttype as Affordable Rent" do
+ expect(lettings_log.renttype).to be 2
+ end
+ end
- after do
- Timecop.unfreeze
- end
+ context "when rent_type is Rent to Buy" do
+ let(:rent_type) { 3 }
- around do |example|
- Timecop.freeze(Time.zone.local(2023, 5, 1)) do
- Singleton.__init__(FormHandler)
- example.run
- end
- Timecop.return
- Singleton.__init__(FormHandler)
- end
+ it "derives renttype as Intermediate Rent" do
+ expect(lettings_log.renttype).to be 3
+ end
+ end
- it "derives and saves unitletas as Other intermediate rent basis(8)" do
- lettings_log.update!(startdate: Time.zone.local(2023, 5, 1))
- record_from_db = ActiveRecord::Base.connection.execute("select unitletas from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(lettings_log.unitletas).to eq(8)
- expect(record_from_db["unitletas"]).to eq(8)
- end
- end
+ context "when rent_type is London Living Rent" do
+ let(:rent_type) { 4 }
+
+ it "derives renttype as Intermediate Rent" do
+ expect(lettings_log.renttype).to be 3
+ end
+ end
+
+ context "when rent_type is Other intermediate rent product" do
+ let(:rent_type) { 5 }
+ let(:irproduct_other) { "Rent first" }
+
+ it "derives renttype as Intermediate Rent" do
+ expect(lettings_log.renttype).to be 3
end
end
end
@@ -2168,37 +2156,6 @@ RSpec.describe LettingsLog do
expect(record_from_db["wchair"]).to eq(1)
end
end
-
- context "and renewal" do
- before do
- Timecop.freeze(Time.zone.local(2022, 4, 2))
- end
-
- after do
- Timecop.unfreeze
- end
-
- let(:scheme) { create(:scheme) }
- let(:location) { create(:location, scheme:) }
- let!(:supported_housing_lettings_log) do
- described_class.create!({
- managing_organisation: owning_organisation,
- owning_organisation:,
- created_by: created_by_user,
- needstype: 2,
- scheme_id: scheme.id,
- location_id: location.id,
- renewal: 1,
- startdate: Time.zone.local(2022, 4, 2),
- created_at: Time.utc(2022, 2, 8, 16, 52, 15),
- })
- end
-
- it "correctly infers and saves the renewal date" do
- record_from_db = ActiveRecord::Base.connection.execute("SELECT voiddate from lettings_logs where id=#{supported_housing_lettings_log.id}").to_a[0]
- expect(record_from_db["voiddate"].to_i).to eq(supported_housing_lettings_log.startdate.to_i)
- end
- end
end
context "when saving accessibility needs" do
@@ -2434,77 +2391,18 @@ RSpec.describe LettingsLog do
end
end
- context "when it changes from a renewal to not a renewal" do
- let(:lettings_log) { create(:lettings_log) }
-
- it "resets inferred waityear value" do
- lettings_log.update!({ renewal: 1 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select waityear from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["waityear"]).to eq(2)
- expect(lettings_log["waityear"]).to eq(2)
-
- lettings_log.update!({ renewal: 0 })
- record_from_db = ActiveRecord::Base.connection.execute("select waityear from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["waityear"]).to eq(nil)
- expect(lettings_log["waityear"]).to eq(nil)
- end
-
- it "resets inferred vacancy reason value" do
- vacancy_reason = "rsnvac"
-
- lettings_log.update!({ renewal: 1 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select #{vacancy_reason} from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db[vacancy_reason]).to eq(14)
- expect(lettings_log[vacancy_reason]).to eq(14)
-
- lettings_log.update!({ renewal: 0 })
- record_from_db = ActiveRecord::Base.connection.execute("select #{vacancy_reason} from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db[vacancy_reason]).to eq(nil)
- expect(lettings_log[vacancy_reason]).to eq(nil)
- end
- end
-
context "when it changes from a supported housing to not a supported housing" do
let(:location) { create(:location, mobility_type: "A", postcode: "SW1P 4DG") }
let(:lettings_log) { create(:lettings_log, location:) }
it "resets inferred wchair value" do
- lettings_log.update!({ needstype: 2 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select wchair from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["wchair"]).to eq(2)
- expect(lettings_log["wchair"]).to eq(2)
-
- lettings_log.update!({ needstype: 1 })
- record_from_db = ActiveRecord::Base.connection.execute("select needstype from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["wchair"]).to eq(nil)
- expect(lettings_log["wchair"]).to eq(nil)
+ expect { lettings_log.update!(needstype: 2) }.to change(lettings_log, :wchair).to(2)
+ expect { lettings_log.update!(needstype: 1) }.to change(lettings_log, :wchair).from(2).to(nil)
end
it "resets location" do
- lettings_log.update!({ needstype: 2 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select location_id from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["location_id"]).to eq(location.id)
- expect(lettings_log["location_id"]).to eq(location.id)
- lettings_log.update!({ needstype: 1 })
- record_from_db = ActiveRecord::Base.connection.execute("select location_id from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["location_id"]).to eq(nil)
- expect(lettings_log["location_id"]).to eq(nil)
- end
- end
-
- context "when it is not a renewal" do
- let(:lettings_log) { create(:lettings_log) }
-
- it "saves waityear value" do
- lettings_log.update!({ renewal: 0, waityear: 2 })
-
- record_from_db = ActiveRecord::Base.connection.execute("select waityear from lettings_logs where id=#{lettings_log.id}").to_a[0]
- expect(record_from_db["waityear"]).to eq(2)
- expect(lettings_log["waityear"]).to eq(2)
+ lettings_log.update!(needstype: 2)
+ expect { lettings_log.update!(needstype: 1) }.to change(lettings_log, :location_id).from(location.id).to(nil)
end
end
diff --git a/spec/models/validations/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb
index b51a084f5..acffc9cac 100644
--- a/spec/models/validations/soft_validations_spec.rb
+++ b/spec/models/validations/soft_validations_spec.rb
@@ -84,25 +84,9 @@ RSpec.describe Validations::SoftValidations do
describe "retirement soft validations" do
context "when the tenant is retired but under the expected retirement age" do
- context "when the tenant is female" do
- it "shows the interruption screen" do
- record.update!(age1: 43, sex1: "F", ecstat1: 5)
- expect(record.person_1_retired_under_soft_min_age?).to be true
- end
- end
-
- context "when the tenant is male" do
- it "shows the interruption screen" do
- record.update!(age1: 43, sex1: "M", ecstat1: 5)
- expect(record.person_1_retired_under_soft_min_age?).to be true
- end
- end
-
- context "when the tenant is non-binary" do
- it "shows the interruption screen" do
- record.update!(age1: 43, sex1: "X", ecstat1: 5)
- expect(record.person_1_retired_under_soft_min_age?).to be true
- end
+ it "shows the interruption screen" do
+ record.update!(age1: 43, ecstat1: 5)
+ expect(record.person_1_retired_under_soft_min_age?).to be true
end
end
@@ -130,25 +114,9 @@ RSpec.describe Validations::SoftValidations do
end
context "when the tenant prefers not to say what their economic status is but is under the expected retirement age" do
- context "when the tenant is female" do
- it "does not show the interruption screen" do
- record.update!(age1: 43, sex1: "F", ecstat1: 10)
- expect(record.person_1_retired_under_soft_min_age?).to be false
- end
- end
-
- context "when the tenant is male" do
- it "does not show the interruption screen" do
- record.update!(age1: 43, sex1: "M", ecstat1: 10)
- expect(record.person_1_retired_under_soft_min_age?).to be false
- end
- end
-
- context "when the tenant is non-binary" do
- it "does not show the interruption screen" do
- record.update!(age1: 43, sex1: "X", ecstat1: 10)
- expect(record.person_1_retired_under_soft_min_age?).to be false
- end
+ it "does not show the interruption screen" do
+ record.update!(age1: 43, ecstat1: 10)
+ expect(record.person_1_retired_under_soft_min_age?).to be false
end
end
diff --git a/spec/models/validations/tenancy_validations_spec.rb b/spec/models/validations/tenancy_validations_spec.rb
index e2dae02e2..f52c19bb9 100644
--- a/spec/models/validations/tenancy_validations_spec.rb
+++ b/spec/models/validations/tenancy_validations_spec.rb
@@ -23,6 +23,7 @@ RSpec.describe Validations::TenancyValidations do
record.tenancy = 3
record.tenancylength = 10
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -42,6 +43,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 1
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -51,6 +53,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 100
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -60,8 +63,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = 3
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
@@ -69,8 +71,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = nil
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
end
@@ -90,6 +91,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 1
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -99,6 +101,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 100
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -108,8 +111,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = 3
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
@@ -117,8 +119,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = nil
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
end
@@ -149,6 +150,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 1
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -158,6 +160,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 100
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -167,8 +170,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = 3
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
@@ -176,8 +178,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = nil
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
end
@@ -196,6 +197,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 1
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -205,6 +207,7 @@ RSpec.describe Validations::TenancyValidations do
it "adds an error" do
record.tenancylength = 100
tenancy_validator.validate_fixed_term_tenancy(record)
+ expect(record.errors["needstype"]).to include(match(expected_error))
expect(record.errors["tenancylength"]).to include(match(expected_error))
expect(record.errors["tenancy"]).to include(match(expected_error))
end
@@ -214,8 +217,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = 3
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
@@ -223,8 +225,7 @@ RSpec.describe Validations::TenancyValidations do
it "does not add an error" do
record.tenancylength = nil
tenancy_validator.validate_fixed_term_tenancy(record)
- expect(record.errors["tenancylength"]).to be_empty
- expect(record.errors["tenancy"]).to be_empty
+ expect(record.errors).to be_empty
end
end
end
diff --git a/spec/requests/form_controller_spec.rb b/spec/requests/form_controller_spec.rb
index de2e0b571..5d9042c7c 100644
--- a/spec/requests/form_controller_spec.rb
+++ b/spec/requests/form_controller_spec.rb
@@ -532,6 +532,56 @@ RSpec.describe FormController, type: :request do
end
end
end
+
+ context "when the question was accessed from an interruption screen (soft validation)" do
+ let(:params) do
+ {
+ id: lettings_log.id,
+ lettings_log: {
+ page: page_id,
+ age1: 20,
+ interruption_page_id: "retirement_value_check",
+ },
+ }
+ end
+
+ before do
+ post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}?referrer=interruption_screen", params:
+ end
+
+ it "redirects back to the soft validation page" do
+ expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/retirement-value-check")
+ end
+
+ it "displays a success banner" do
+ follow_redirect!
+ follow_redirect!
+ expect(response.body).to include("You have successfully updated lead tenant’s age")
+ end
+ end
+
+ context "when requesting a soft validation page for validation that isn't triggering" do
+ before do
+ get "/lettings-logs/#{lettings_log.id}/retirement-value-check", headers: headers.merge({ "HTTP_REFERER" => referrer })
+ end
+
+ context "when the referrer header has interruption_screen" do
+ let(:referrer) { "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}?referrer=interruption_screen" }
+
+ it "routes to the soft validation page" do
+ expect(response.body).to include("Make sure these answers are correct:")
+ end
+ end
+
+ context "when the referrer header does not have interruption screen" do
+ let(:referrer) { "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}" }
+
+ it "skips the soft validation page" do
+ follow_redirect!
+ expect(response.body).not_to include("Make sure these answers are correct:")
+ end
+ end
+ end
end
context "with checkbox questions" do
diff --git a/spec/requests/merge_requests_controller_spec.rb b/spec/requests/merge_requests_controller_spec.rb
index 3ffe1fe13..b8bc22d55 100644
--- a/spec/requests/merge_requests_controller_spec.rb
+++ b/spec/requests/merge_requests_controller_spec.rb
@@ -553,6 +553,86 @@ RSpec.describe MergeRequestsController, type: :request do
end
end
end
+
+ describe "#new_organsation_address" do
+ let(:merge_request) { MergeRequest.create!(requesting_organisation: organisation, new_organisation_name: "New name", new_absorbing_organisation: true) }
+
+ context "when viewing the new organisation name page" do
+ before do
+ get "/merge-request/#{merge_request.id}/new-organisation-address", headers:
+ end
+
+ it "displays the correct question" do
+ expect(page).to have_content("What is New name’s address?")
+ end
+
+ it "has the correct back button" do
+ expect(page).to have_link("Back", href: new_organisation_name_merge_request_path(merge_request))
+ end
+
+ it "has a skip link" do
+ expect(page).to have_link("Skip for now", href: new_organisation_telephone_number_merge_request_path(merge_request))
+ end
+ end
+
+ context "when updating the new organisation address" do
+ let(:params) do
+ { merge_request: {
+ new_organisation_address_line1: "first address line",
+ new_organisation_address_line2: "second address line",
+ new_organisation_postcode: "new postcode",
+ page: "new_organisation_address",
+ } }
+ end
+
+ let(:request) do
+ patch "/merge-request/#{merge_request.id}", headers:, params:
+ end
+
+ it "redirects to new organisation telephone path" do
+ request
+ expect(response).to redirect_to(new_organisation_telephone_number_merge_request_path(merge_request))
+ end
+
+ it "updates new organisation address line 1 to correct addess line" do
+ expect { request }.to change {
+ merge_request.reload.new_organisation_address_line1
+ }.from(nil).to("first address line")
+ end
+
+ it "updates new organisation address line 2 to correct addess line" do
+ expect { request }.to change {
+ merge_request.reload.new_organisation_address_line2
+ }.from(nil).to("second address line")
+ end
+
+ it "updates new organisation postcode to correct addess line" do
+ expect { request }.to change {
+ merge_request.reload.new_organisation_postcode
+ }.from(nil).to("new postcode")
+ end
+ end
+
+ context "when address is not provided" do
+ let(:params) do
+ { merge_request: {
+ new_organisation_address_line1: nil,
+ new_organisation_address_line2: nil,
+ new_organisation_postcode: nil,
+ page: "new_organisation_address",
+ } }
+ end
+
+ let(:request) do
+ patch "/merge-request/#{merge_request.id}", headers:, params:
+ end
+
+ it "does not throw an error" do
+ request
+ expect(response).to redirect_to(new_organisation_telephone_number_merge_request_path(merge_request))
+ end
+ end
+ end
end
end
diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb
index d526f218f..6013a5813 100644
--- a/spec/requests/organisations_controller_spec.rb
+++ b/spec/requests/organisations_controller_spec.rb
@@ -367,7 +367,7 @@ RSpec.describe OrganisationsController, type: :request do
end
end
- context "when viewing logs for other organisation" do
+ context "when viewing lettings logs for other organisation" do
it "does not display the lettings logs" do
get "/organisations/#{unauthorised_organisation.id}/lettings-logs", headers:, params: {}
expect(response).to have_http_status(:unauthorized)
@@ -375,13 +375,13 @@ RSpec.describe OrganisationsController, type: :request do
it "prevents CSV download" do
expect {
- post "/organisations/#{unauthorised_organisation.id}/logs/email-csv", headers:, params: {}
+ post "/organisations/#{unauthorised_organisation.id}/lettings-logs/email-csv", headers:, params: {}
}.not_to enqueue_job(EmailCsvJob)
expect(response).to have_http_status(:unauthorized)
end
end
- context "when viewing logs for your organisation" do
+ context "when viewing lettings logs for your organisation" do
it "does not display the logs" do
get "/organisations/#{organisation.id}/lettings-logs", headers:, params: {}
expect(response).to have_http_status(:unauthorized)
@@ -389,7 +389,35 @@ RSpec.describe OrganisationsController, type: :request do
it "prevents CSV download" do
expect {
- post "/organisations/#{organisation.id}/logs/email-csv", headers:, params: {}
+ post "/organisations/#{organisation.id}/lettings-logs/email-csv", headers:, params: {}
+ }.not_to enqueue_job(EmailCsvJob)
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context "when viewing sales logs for other organisation" do
+ it "does not display the sales logs" do
+ get "/organisations/#{unauthorised_organisation.id}/sales-logs", headers:, params: {}
+ expect(response).to have_http_status(:unauthorized)
+ end
+
+ it "prevents CSV download" do
+ expect {
+ post "/organisations/#{unauthorised_organisation.id}/sales-logs/email-csv", headers:, params: {}
+ }.not_to enqueue_job(EmailCsvJob)
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context "when viewing sales logs for your organisation" do
+ it "does not display the logs" do
+ get "/organisations/#{organisation.id}/sales-logs", headers:, params: {}
+ expect(response).to have_http_status(:unauthorized)
+ end
+
+ it "prevents CSV download" do
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv", headers:, params: {}
}.not_to enqueue_job(EmailCsvJob)
expect(response).to have_http_status(:unauthorized)
end
@@ -544,7 +572,7 @@ RSpec.describe OrganisationsController, type: :request do
end
end
- context "when viewing logs for other organisation" do
+ context "when viewing lettings logs for other organisation" do
it "does not display the logs" do
get "/organisations/#{unauthorised_organisation.id}/lettings-logs", headers:, params: {}
expect(response).to have_http_status(:unauthorized)
@@ -552,13 +580,13 @@ RSpec.describe OrganisationsController, type: :request do
it "prevents CSV download" do
expect {
- post "/organisations/#{unauthorised_organisation.id}/logs/email-csv", headers:, params: {}
+ post "/organisations/#{unauthorised_organisation.id}/lettings-logs/email-csv", headers:, params: {}
}.not_to enqueue_job(EmailCsvJob)
expect(response).to have_http_status(:unauthorized)
end
end
- context "when viewing logs for your organisation" do
+ context "when viewing lettings logs for your organisation" do
it "does not display the logs" do
get "/organisations/#{organisation.id}/lettings-logs", headers:, params: {}
expect(response).to have_http_status(:unauthorized)
@@ -566,7 +594,35 @@ RSpec.describe OrganisationsController, type: :request do
it "prevents CSV download" do
expect {
- post "/organisations/#{organisation.id}/logs/email-csv", headers:, params: {}
+ post "/organisations/#{organisation.id}/lettings-logs/email-csv", headers:, params: {}
+ }.not_to enqueue_job(EmailCsvJob)
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context "when viewing sales logs for other organisation" do
+ it "does not display the logs" do
+ get "/organisations/#{unauthorised_organisation.id}/sales-logs", headers:, params: {}
+ expect(response).to have_http_status(:unauthorized)
+ end
+
+ it "prevents CSV download" do
+ expect {
+ post "/organisations/#{unauthorised_organisation.id}/sales-logs/email-csv", headers:, params: {}
+ }.not_to enqueue_job(EmailCsvJob)
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+
+ context "when viewing sales logs for your organisation" do
+ it "does not display the logs" do
+ get "/organisations/#{organisation.id}/sales-logs", headers:, params: {}
+ expect(response).to have_http_status(:unauthorized)
+ end
+
+ it "prevents CSV download" do
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv", headers:, params: {}
}.not_to enqueue_job(EmailCsvJob)
expect(response).to have_http_status(:unauthorized)
end
@@ -1176,15 +1232,15 @@ RSpec.describe OrganisationsController, type: :request do
sign_in user
end
- context "when they view the logs tab" do
+ context "when they view the lettings logs tab" do
before do
FactoryBot.create(:lettings_log, owning_organisation: organisation)
end
it "has CSV download buttons with the correct paths if at least 1 log exists" do
get "/organisations/#{organisation.id}/lettings-logs"
- expect(page).to have_link("Download (CSV)", href: "/organisations/#{organisation.id}/logs/csv-download?codes_only=false")
- expect(page).to have_link("Download (CSV, codes only)", href: "/organisations/#{organisation.id}/logs/csv-download?codes_only=true")
+ expect(page).to have_link("Download (CSV)", href: "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=false")
+ expect(page).to have_link("Download (CSV, codes only)", href: "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=true")
end
context "when you download the CSV" do
@@ -1197,62 +1253,151 @@ RSpec.describe OrganisationsController, type: :request do
end
it "only includes logs from that organisation" do
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=false"
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=false"
expect(page).to have_text("You've selected 3 logs.")
end
it "provides the organisation to the mail job" do
expect {
- post "/organisations/#{organisation.id}/logs/email-csv?status[]=completed&codes_only=false", headers:, params: {}
+ post "/organisations/#{organisation.id}/lettings-logs/email-csv?status[]=completed&codes_only=false", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed] }, false, organisation, false)
end
it "provides the export type to the mail job" do
codes_only_export_type = false
expect {
- post "/organisations/#{organisation.id}/logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
+ post "/organisations/#{organisation.id}/lettings-logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, organisation, codes_only_export_type)
codes_only_export_type = true
expect {
- post "/organisations/#{organisation.id}/logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
+ post "/organisations/#{organisation.id}/lettings-logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
}.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, organisation, codes_only_export_type)
end
end
end
- describe "GET #download_csv" do
+ context "when they view the sales logs tab" do
+ before do
+ FactoryBot.create(:sales_log, owning_organisation: organisation)
+ end
+
+ it "has CSV download buttons with the correct paths if at least 1 log exists" do
+ get "/organisations/#{organisation.id}/sales-logs"
+ expect(page).to have_link("Download (CSV)", href: "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=false")
+ expect(page).to have_link("Download (CSV, codes only)", href: "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=true")
+ end
+
+ context "when you download the CSV" do
+ let(:other_organisation) { FactoryBot.create(:organisation) }
+
+ before do
+ FactoryBot.create_list(:sales_log, 2, owning_organisation: organisation)
+ FactoryBot.create(:sales_log, owning_organisation: organisation, status: "pending", skip_update_status: true)
+ FactoryBot.create_list(:sales_log, 2, owning_organisation: other_organisation)
+ end
+
+ it "only includes logs from that organisation" do
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=false"
+
+ expect(page).to have_text("You've selected 3 logs.")
+ end
+
+ it "provides the organisation to the mail job" do
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv?status[]=completed&codes_only=false", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed] }, false, organisation, false, "sales")
+ end
+
+ it "provides the log type to the mail job" do
+ log_type = "sales"
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv?status[]=completed&codes_only=false", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed] }, false, organisation, false, log_type)
+ end
+
+ it "provides the export type to the mail job" do
+ codes_only_export_type = false
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, organisation, codes_only_export_type, "sales")
+ codes_only_export_type = true
+ expect {
+ post "/organisations/#{organisation.id}/sales-logs/email-csv?codes_only=#{codes_only_export_type}", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, organisation, codes_only_export_type, "sales")
+ end
+ end
+ end
+
+ describe "GET #download_lettings_csv" do
+ it "renders a page with the correct header" do
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=false", headers:, params: {}
+ header = page.find_css("h1")
+ expect(header.text).to include("Download CSV")
+ end
+
+ it "renders a form with the correct target containing a button with the correct text" do
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=false", headers:, params: {}
+ form = page.find("form.button_to")
+ expect(form[:method]).to eq("post")
+ expect(form[:action]).to eq("/organisations/#{organisation.id}/lettings-logs/email-csv")
+ expect(form).to have_button("Send email")
+ end
+
+ it "when codes_only query parameter is false, form contains hidden field with correct value" do
+ codes_only = false
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
+ hidden_field = page.find("form.button_to").find_field("codes_only", type: "hidden")
+ expect(hidden_field.value).to eq(codes_only.to_s)
+ end
+
+ it "when codes_only query parameter is true, form contains hidden field with correct value" do
+ codes_only = true
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
+ hidden_field = page.find("form.button_to").find_field("codes_only", type: "hidden")
+ expect(hidden_field.value).to eq(codes_only.to_s)
+ end
+
+ it "when query string contains search parameter, form contains hidden field with correct value" do
+ search_term = "blam"
+ get "/organisations/#{organisation.id}/lettings-logs/csv-download?codes_only=true&search=#{search_term}", headers:, params: {}
+ hidden_field = page.find("form.button_to").find_field("search", type: "hidden")
+ expect(hidden_field.value).to eq(search_term)
+ end
+ end
+
+ describe "GET #download_sales_csv" do
it "renders a page with the correct header" do
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=false", headers:, params: {}
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=false", headers:, params: {}
header = page.find_css("h1")
expect(header.text).to include("Download CSV")
end
it "renders a form with the correct target containing a button with the correct text" do
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=false", headers:, params: {}
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=false", headers:, params: {}
form = page.find("form.button_to")
expect(form[:method]).to eq("post")
- expect(form[:action]).to eq("/organisations/#{organisation.id}/logs/email-csv")
+ expect(form[:action]).to eq("/organisations/#{organisation.id}/sales-logs/email-csv")
expect(form).to have_button("Send email")
end
it "when codes_only query parameter is false, form contains hidden field with correct value" do
codes_only = false
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
hidden_field = page.find("form.button_to").find_field("codes_only", type: "hidden")
expect(hidden_field.value).to eq(codes_only.to_s)
end
it "when codes_only query parameter is true, form contains hidden field with correct value" do
codes_only = true
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=#{codes_only}", headers:, params: {}
hidden_field = page.find("form.button_to").find_field("codes_only", type: "hidden")
expect(hidden_field.value).to eq(codes_only.to_s)
end
it "when query string contains search parameter, form contains hidden field with correct value" do
search_term = "blam"
- get "/organisations/#{organisation.id}/logs/csv-download?codes_only=true&search=#{search_term}", headers:, params: {}
+ get "/organisations/#{organisation.id}/sales-logs/csv-download?codes_only=true&search=#{search_term}", headers:, params: {}
hidden_field = page.find("form.button_to").find_field("search", type: "hidden")
expect(hidden_field.value).to eq(search_term)
end
diff --git a/spec/requests/sales_logs_controller_spec.rb b/spec/requests/sales_logs_controller_spec.rb
index e400366df..6927d294a 100644
--- a/spec/requests/sales_logs_controller_spec.rb
+++ b/spec/requests/sales_logs_controller_spec.rb
@@ -148,6 +148,16 @@ RSpec.describe SalesLogsController, type: :request do
expect(page).to have_content(other_organisation.name)
end
+ it "shows a link for labelled CSV download of logs" do
+ get "/sales-logs", headers: headers, params: {}
+ expect(page).to have_link("Download (CSV)", href: "/sales-logs/csv-download?codes_only=false")
+ end
+
+ it "shows a link for codes only CSV download of logs" do
+ get "/sales-logs", headers: headers, params: {}
+ expect(page).to have_link("Download (CSV, codes only)", href: "/sales-logs/csv-download?codes_only=true")
+ end
+
context "when there are no logs in the database" do
before do
SalesLog.destroy_all
@@ -157,6 +167,12 @@ RSpec.describe SalesLogsController, type: :request do
get "/sales-logs", headers: headers, params: {}
expect(page).to have_title("Logs - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
+
+ it "does not show CSV download links" do
+ get "/sales-logs", headers: headers, params: {}
+ expect(page).not_to have_link("Download (CSV)")
+ expect(page).not_to have_link("Download (CSV, codes only)")
+ end
end
context "when there is a pending log" do
@@ -298,6 +314,19 @@ RSpec.describe SalesLogsController, type: :request do
expect(page).not_to have_content("Managing organisation")
end
+ it "displays standard CSV download link only, with the correct path" do
+ get "/sales-logs", headers:, params: {}
+ expect(page).to have_link("Download (CSV)", href: "/sales-logs/csv-download?codes_only=false")
+ expect(page).not_to have_link("Download (CSV, codes only)")
+ end
+
+ it "does not display CSV download links if there are no logs" do
+ SalesLog.destroy_all
+ get "/sales-logs", headers:, params: {}
+ expect(page).not_to have_link("Download (CSV)")
+ expect(page).not_to have_link("Download (CSV, codes only)")
+ end
+
context "when using a search query" do
let(:logs) { FactoryBot.create_list(:sales_log, 3, :completed, owning_organisation: user.organisation, created_by: user) }
let(:log_to_search) { FactoryBot.create(:sales_log, :completed, owning_organisation: user.organisation, created_by: user) }
@@ -316,6 +345,13 @@ RSpec.describe SalesLogsController, type: :request do
end
end
+ it "displays the labelled CSV download link, with the search included in the query params" do
+ get "/sales-logs?search=#{log_to_search.id}", headers:, params: {}
+ download_link = page.find_link("Download (CSV)")
+ download_link_params = CGI.parse(URI.parse(download_link[:href]).query)
+ expect(download_link_params).to include("search" => [log_to_search.id.to_s])
+ end
+
context "when search query doesn't match any logs" do
it "doesn't display any logs" do
get "/sales-logs?search=foobar", headers:, params: {}
@@ -352,7 +388,7 @@ RSpec.describe SalesLogsController, type: :request do
end
end
- context "when there are less than 20 logs" do
+ context "when there are fewer than 20 logs" do
before do
get "/sales-logs", headers:, params: {}
end
@@ -469,5 +505,151 @@ RSpec.describe SalesLogsController, type: :request do
page.assert_selector(".govuk-button", text: "Create a new lettings log", count: 0)
end
end
+
+ context "when requesting CSV download" do
+ let(:headers) { { "Accept" => "text/html" } }
+ let(:search_term) { "foot" }
+ let(:codes_only) { false }
+
+ before do
+ allow(user).to receive(:need_two_factor_authentication?).and_return(false)
+ sign_in user
+ get "/sales-logs/csv-download?search=#{search_term}&codes_only=#{codes_only}", headers:
+ end
+
+ it "returns http success" do
+ expect(response).to have_http_status(:success)
+ end
+
+ it "shows a confirmation button" do
+ expect(page).to have_button("Send email")
+ end
+
+ it "has a hidden field with the search term" do
+ expect(page).to have_field("search", type: "hidden", with: search_term)
+ end
+
+ context "when user is not support" do
+ context "and export type is not codes only" do
+ it "has a hidden field with the export type" do
+ expect(page).to have_field("codes_only", type: "hidden", with: codes_only)
+ end
+ end
+
+ context "and export type is codes only" do
+ let(:codes_only) { true }
+
+ it "the user is not authorised" do
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
+ end
+
+ context "when user is support" do
+ let(:user) { FactoryBot.create(:user, :support) }
+
+ context "and export type is not codes only" do
+ it "has a hidden field with the export type" do
+ expect(page).to have_field("codes_only", type: "hidden", with: codes_only)
+ end
+ end
+
+ context "and export type is codes only" do
+ let(:codes_only) { true }
+
+ it "has a hidden field with the export type" do
+ expect(page).to have_field("codes_only", type: "hidden", with: codes_only)
+ end
+ end
+ end
+ end
+
+ context "when confirming the CSV email" do
+ let(:headers) { { "Accept" => "text/html" } }
+
+ it "confirms that the user will receive an email with the requested CSV" do
+ sign_in user
+ get "/sales-logs/csv-confirmation"
+ expect(CGI.unescape_html(response.body)).to include("We’re sending you an email")
+ end
+ end
+ end
+
+ describe "POST #email-csv" do
+ let(:other_organisation) { FactoryBot.create(:organisation) }
+ let(:user) { FactoryBot.create(:user, :support) }
+ let!(:sales_log) do
+ FactoryBot.create(
+ :sales_log,
+ created_by: user,
+ )
+ end
+
+ before do
+ allow(user).to receive(:need_two_factor_authentication?).and_return(false)
+ sign_in user
+ FactoryBot.create(:sales_log)
+ FactoryBot.create(:sales_log,
+ :completed,
+ owning_organisation:,
+ created_by: user)
+ end
+
+ it "creates an E-mail job with the correct log type" do
+ expect {
+ post "/sales-logs/email-csv?codes_only=true", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, nil, true, "sales")
+ end
+
+ it "redirects to the confirmation page" do
+ post "/sales-logs/email-csv?codes_only=true", headers:, params: {}
+ expect(response).to redirect_to(csv_confirmation_sales_logs_path)
+ end
+
+ it "passes the search term" do
+ expect {
+ post "/sales-logs/email-csv?search=#{sales_log.id}&codes_only=false", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, sales_log.id.to_s, {}, false, nil, false, "sales")
+ end
+
+ it "passes filter parameters" do
+ expect {
+ post "/sales-logs/email-csv?status[]=completed&codes_only=true", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, { "status" => %w[completed] }, false, nil, true, "sales")
+ end
+
+ it "passes export type flag" do
+ expect {
+ post "/sales-logs/email-csv?codes_only=true", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, nil, true, "sales")
+ expect {
+ post "/sales-logs/email-csv?codes_only=false", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, nil, false, "sales")
+ end
+
+ it "passes a combination of search term, export type and filter parameters" do
+ postcode = "XX1 1TG"
+
+ expect {
+ post "/sales-logs/email-csv?status[]=completed&search=#{postcode}&codes_only=false", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, postcode, { "status" => %w[completed] }, false, nil, false, "sales")
+ end
+
+ context "when the user is not a support user" do
+ let(:user) { FactoryBot.create(:user, :data_coordinator) }
+
+ it "has permission to download human readable csv" do
+ codes_only_export = false
+ expect {
+ post "/sales-logs/email-csv?codes_only=#{codes_only_export}", headers:, params: {}
+ }.to enqueue_job(EmailCsvJob).with(user, nil, {}, false, nil, false, "sales")
+ end
+
+ it "is not authorized to download codes only csv" do
+ codes_only_export = true
+ post "/sales-logs/email-csv?codes_only=#{codes_only_export}", headers:, params: {}
+ expect(response).to have_http_status(:unauthorized)
+ end
+ end
end
end
diff --git a/spec/services/bulk_upload/lettings/validator_spec.rb b/spec/services/bulk_upload/lettings/validator_spec.rb
index 10adcb86a..3ba36dfc0 100644
--- a/spec/services/bulk_upload/lettings/validator_spec.rb
+++ b/spec/services/bulk_upload/lettings/validator_spec.rb
@@ -208,7 +208,7 @@ RSpec.describe BulkUpload::Lettings::Validator do
error = BulkUploadError.find_by(row: "7", field: "field_96", category: "setup")
expect(error.field).to eql("field_96")
- expect(error.error).to eql("You must answer tenancy start date")
+ expect(error.error).to eql("You must answer tenancy start date (day)")
expect(error.tenant_code).to eql("123")
expect(error.property_ref).to be_nil
expect(error.row).to eql("7")
diff --git a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
index dd9bf4a5b..0587c0f51 100644
--- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb
@@ -303,9 +303,9 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:attributes) { { bulk_upload:, field_7: "123" } }
it "has errors on setup fields" do
- errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute)
+ errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort
- expect(errors).to eql(%i[field_1 field_98 field_97 field_96 field_111 field_113 field_132])
+ expect(errors).to eql(%i[field_1 field_111 field_113 field_132 field_96 field_97 field_98])
end
end
@@ -403,15 +403,13 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
end
end
- describe "#field_4" do
+ describe "#field_4" do # mangement group code
context "when nullable not permitted" do
let(:bulk_upload) { create(:bulk_upload, :lettings, user:, needstype: 2) }
let(:attributes) { { bulk_upload:, field_1: "2", field_4: nil } }
it "cannot be nulled" do
- setup_errors = parser.errors.select { |e| e.options[:category] == "setup" }
-
- expect(setup_errors.find { |e| e.attribute == :field_4 }).to be_present
+ expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql(["You must answer management group code"])
end
end
@@ -427,7 +425,7 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:attributes) { { bulk_upload:, field_1: "1", field_4: "123" } }
it "returns an error" do
- expect(parser.errors[:field_4]).to be_present
+ expect(parser.errors.where(:field_4, category: :setup)).to be_present
end
end
@@ -436,7 +434,7 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:attributes) { { bulk_upload:, field_1: "1", field_4: other_scheme.old_visible_id, field_111: owning_org.old_visible_id } }
it "returns an error" do
- expect(parser.errors[:field_4]).to include("This management group code does not belong to your organisation, or any of your stock owners / managing agents")
+ expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to include("This management group code does not belong to your organisation, or any of your stock owners / managing agents")
end
end
@@ -459,15 +457,13 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
end
end
- describe "#field_5" do
+ describe "#field_5" do # scheme code
context "when not nullable" do
let(:bulk_upload) { create(:bulk_upload, :lettings, user:, needstype: 2) }
let(:attributes) { { bulk_upload:, field_1: "2", field_5: nil } }
it "cannot be nulled" do
- setup_errors = parser.errors.select { |e| e.options[:category] == "setup" }
-
- expect(setup_errors.find { |e| e.attribute == :field_5 }).to be_present
+ expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eql(["You must answer scheme code"])
end
end
@@ -517,8 +513,8 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
}
end
- it "returns an error" do
- expect(parser.errors[:field_5]).to be_present
+ it "returns as setup error" do
+ expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eql(["Location could be found with provided scheme code"])
end
end
end
@@ -715,21 +711,21 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:attributes) { { bulk_upload:, field_1: "1", field_96: nil, field_97: nil, field_98: nil } }
it "returns them as setup errors" do
- setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
-
- expect(setup_errors.find { |e| e.attribute == :field_96 }).to be_present
- expect(setup_errors.find { |e| e.attribute == :field_97 }).to be_present
- expect(setup_errors.find { |e| e.attribute == :field_98 }).to be_present
+ expect(parser.errors.where(:field_96, category: :setup)).to be_present
+ expect(parser.errors.where(:field_97, category: :setup)).to be_present
+ expect(parser.errors.where(:field_98, category: :setup)).to be_present
end
end
- context "when one of these fields is blank" do
+ context "when one of these fields is blank", aggregate_failures: true do
let(:attributes) { { bulk_upload:, field_1: "1", field_96: "1", field_97: "1", field_98: nil } }
it "returns an error only on blank field" do
- expect(parser.errors[:field_96]).to be_blank
- expect(parser.errors[:field_97]).to be_blank
- expect(parser.errors[:field_98]).to be_present
+ expect(parser.errors.where(:field_96, category: :setup)).to be_blank
+ expect(parser.errors.where(:field_97, category: :setup)).to be_blank
+
+ expect(parser.errors.where(:field_98).map(&:message)).to eql(["You must answer tenancy start date (year)"])
+ expect(parser.errors.where(:field_98, category: :setup).map(&:message)).to eql(["You must answer tenancy start date (year)"])
end
end
@@ -737,7 +733,7 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:attributes) { { bulk_upload:, field_98: "2022" } }
it "returns an error" do
- expect(parser.errors[:field_98]).to include("Tenancy start year must be 2 digits")
+ expect(parser.errors.where(:field_98, category: :setup).map(&:message)).to include("Tenancy start year must be 2 digits")
end
end
@@ -774,9 +770,9 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
let(:bulk_upload) { create(:bulk_upload, :lettings, user:, year: 2022) }
it "returns errors" do
- expect(parser.errors[:field_96]).to be_present
- expect(parser.errors[:field_97]).to be_present
- expect(parser.errors[:field_98]).to be_present
+ expect(parser.errors.where(:field_96, category: :setup)).to be_present
+ expect(parser.errors.where(:field_97, category: :setup)).to be_present
+ expect(parser.errors.where(:field_98, category: :setup)).to be_present
end
end
end
@@ -788,7 +784,7 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
it "is not permitted as setup error" do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
- expect(setup_errors.find { |e| e.attribute == :field_111 }.message).to eql("The owning organisation code is incorrect")
+ expect(setup_errors.find { |e| e.attribute == :field_111 }.message).to eql("You must answer owning organisation")
end
it "blocks log creation" do
@@ -897,12 +893,10 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
describe "#field_113" do # managing org
context "when blank" do
- let(:attributes) { { bulk_upload:, field_113: "", field_4: 1 } }
+ let(:attributes) { setup_section_params.merge(field_113: nil) }
it "is not permitted as setup error" do
- setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
-
- expect(setup_errors.find { |e| e.attribute == :field_113 }.message).to eql("The managing organisation code is incorrect")
+ expect(parser.errors.where(:field_113, category: :setup).map(&:message)).to eql(["You must answer managing organisation"])
end
it "blocks log creation" do
@@ -954,6 +948,50 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do
end
end
end
+
+ describe "#field_134" do # renewal
+ context "when none possible option selected" do
+ let(:attributes) { setup_section_params.merge({ field_134: "101" }) }
+
+ it "adds a setup error" do
+ expect(parser.errors.where(:field_134, category: :setup).map(&:message)).to include("Enter a valid value for Is this letting a renewal?")
+ end
+ end
+ end
+
+ describe "#field_55 - #field_60" do
+ context "when all blank" do
+ let(:attributes) { setup_section_params.merge({ field_55: nil, field_56: nil, field_57: nil, field_58: nil, field_59: nil, field_60: nil }) }
+
+ it "adds errors to correct fields" do
+ expect(parser.errors[:field_55]).to be_present
+ expect(parser.errors[:field_56]).to be_present
+ expect(parser.errors[:field_57]).to be_present
+ expect(parser.errors[:field_58]).to be_present
+ expect(parser.errors[:field_59]).to be_present
+ end
+ end
+ end
+
+ describe "soft validations" do
+ context "when soft validation is triggered" do
+ let(:attributes) { setup_section_params.merge({ field_12: 22, field_35: 5 }) }
+
+ it "adds an error to the relevant fields" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_12 }).to be_present
+ expect(soft_validation_errors.find { |e| e.attribute == :field_35 }).to be_present
+ end
+
+ it "populates with correct error message" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_12 }.message).to eql("You told us this person is aged 22 years and retired.")
+ expect(soft_validation_errors.find { |e| e.attribute == :field_35 }.message).to eql("You told us this person is aged 22 years and retired.")
+ end
+ end
+ end
end
describe "#log" do
diff --git a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
index 58b216e43..d881b972b 100644
--- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
@@ -31,6 +31,18 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
before do
create(:organisation_relationship, parent_organisation: owning_org, child_organisation: managing_org)
+
+ LaRentRange.create!(
+ ranges_rent_id: "1",
+ la: "E09000008",
+ beds: 1,
+ lettype: 3,
+ soft_min: 12.41,
+ soft_max: 118.85,
+ hard_min: 9.87,
+ hard_max: 200.99,
+ start_year: 2023,
+ )
end
around do |example|
@@ -489,8 +501,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
context "when matching scheme cannot be found" do
let(:attributes) { { bulk_upload:, field_5: "1", field_16: "123" } }
- it "returns an error" do
- expect(parser.errors[:field_16]).to be_present
+ it "returns a setup error" do
+ expect(parser.errors.where(:field_16, category: :setup)).to be_present
end
end
@@ -498,8 +510,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:other_scheme) { create(:scheme, :with_old_visible_id) }
let(:attributes) { { bulk_upload:, field_5: "1", field_16: other_scheme.old_visible_id, field_1: owning_org.old_visible_id } }
- it "returns an error" do
- expect(parser.errors[:field_16]).to include("This management group code does not belong to your organisation, or any of your stock owners / managing agents")
+ it "returns a setup error" do
+ expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to include("This management group code does not belong to your organisation, or any of your stock owners / managing agents")
end
end
@@ -535,8 +547,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
}
end
- it "returns an error" do
- expect(parser.errors[:field_17]).to be_present
+ it "returns a setup error" do
+ expect(parser.errors.where(:field_17, category: :setup)).to be_present
end
end
@@ -569,8 +581,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
}
end
- it "returns an error" do
- expect(parser.errors[:field_17]).to be_present
+ it "returns a setup error" do
+ expect(parser.errors.where(:field_17, category: :setup)).to be_present
end
end
end
@@ -663,6 +675,20 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
end
+ describe "#field_83 - #field_88" do
+ context "when all blank" do
+ let(:attributes) { setup_section_params.merge({ field_83: nil, field_84: nil, field_85: nil, field_86: nil, field_87: nil, field_88: nil }) }
+
+ it "adds errors to correct fields" do
+ expect(parser.errors[:field_83]).to be_present
+ expect(parser.errors[:field_84]).to be_present
+ expect(parser.errors[:field_85]).to be_present
+ expect(parser.errors[:field_86]).to be_present
+ expect(parser.errors[:field_87]).to be_present
+ end
+ end
+ end
+
describe "#field_119" do # referral
context "when 3 ie PRP nominated by LA and owning org is LA" do
let(:attributes) { { bulk_upload:, field_119: "3", field_1: owning_org.old_visible_id } }
@@ -705,8 +731,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_5: "1", field_7: nil, field_8: nil, field_9: nil } }
it "returns an error" do
- parser.valid?
-
expect(parser.errors[:field_7]).to be_present
expect(parser.errors[:field_8]).to be_present
expect(parser.errors[:field_9]).to be_present
@@ -717,8 +741,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_9: "2022" } }
it "returns an error" do
- parser.valid?
-
expect(parser.errors[:field_9]).to include("Tenancy start year must be 2 digits")
end
end
@@ -737,8 +759,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:bulk_upload) { create(:bulk_upload, :lettings, user:, year: 2022) }
it "does not return errors" do
- parser.valid?
-
expect(parser.errors[:field_7]).not_to be_present
expect(parser.errors[:field_8]).not_to be_present
expect(parser.errors[:field_9]).not_to be_present
@@ -750,19 +770,16 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
Timecop.freeze(Date.new(2022, 4, 2)) do
example.run
end
- Timecop.return
end
let(:attributes) { { bulk_upload:, field_7: "1", field_8: "1", field_9: "22" } }
let(:bulk_upload) { create(:bulk_upload, :lettings, user:, year: 2022) }
- it "returns errors" do
- parser.valid?
-
- expect(parser.errors[:field_7]).to be_present
- expect(parser.errors[:field_8]).to be_present
- expect(parser.errors[:field_9]).to be_present
+ it "returns setup errors" do
+ expect(parser.errors.where(:field_7, category: :setup)).to be_present
+ expect(parser.errors.where(:field_8, category: :setup)).to be_present
+ expect(parser.errors.where(:field_9, category: :setup)).to be_present
end
end
end
@@ -772,9 +789,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_1: "", field_4: 1 } }
it "is not permitted as setup error" do
- setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
-
- expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("The owning organisation code is incorrect")
+ expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql(["You must answer owning organisation"])
end
it "blocks log creation" do
@@ -875,16 +890,12 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
end
- describe "#field_4" do
+ describe "#field_4" do # needs type
context "when blank" do
let(:attributes) { { bulk_upload:, field_4: nil, field_13: "123" } }
it "is reported as a setup error" do
- errors = parser.errors.select { |e| e.options[:category] == :setup }
- error = errors.find { |e| e.attribute == :field_4 }
-
- expect(error).to be_present
- expect(error.type).to eql("You must answer needs type")
+ expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql(["You must answer needs type"])
end
end
end
@@ -893,8 +904,16 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
context "when blank" do
let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_6: "" } }
- it "has errors on the field" do
- expect(parser.errors[:field_6]).to include("You must answer property renewal")
+ it "has setup errors on the field" do
+ expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eql(["You must answer property renewal"])
+ end
+ end
+
+ context "when none possible option selected" do
+ let(:attributes) { setup_section_params.merge({ field_6: "101" }) }
+
+ it "adds a setup error" do
+ expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include("Enter a valid value for Is this letting a renewal?")
end
end
end
@@ -984,6 +1003,43 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
end
end
+
+ describe "soft validations" do
+ context "when soft validation is triggered" do
+ let(:attributes) { setup_section_params.merge({ field_46: 22, field_50: 5 }) }
+
+ it "adds an error to the relevant fields" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_46 }).to be_present
+ expect(soft_validation_errors.find { |e| e.attribute == :field_50 }).to be_present
+ end
+
+ it "populates with correct error message" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_46 }.message).to eql("You told us this person is aged 22 years and retired.")
+ expect(soft_validation_errors.find { |e| e.attribute == :field_50 }.message).to eql("You told us this person is aged 22 years and retired.")
+ end
+ end
+
+ context "when soft validation is triggered and not required" do
+ let(:attributes) { setup_section_params.merge({ field_128: 120, field_126: 1, field_32: 1, field_4: 1, field_5: "3", field_25: "E09000008" }) }
+
+ it "adds an error to the relevant fields" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_128 }).to be_present
+ end
+
+ it "populates with correct error message" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.count { |e| e.attribute == :field_128 }).to be(1)
+ expect(soft_validation_errors.find { |e| e.attribute == :field_128 }.message).to eql("You told us the rent is £120.00 every week. The maximum rent expected for this type of property in this local authority is ££118.85 every week.")
+ end
+ end
+ end
end
describe "#log" do
diff --git a/spec/services/bulk_upload/sales/year2022/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2022/row_parser_spec.rb
index bd5520ea7..7fdf8da4d 100644
--- a/spec/services/bulk_upload/sales/year2022/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2022/row_parser_spec.rb
@@ -506,17 +506,36 @@ RSpec.describe BulkUpload::Sales::Year2022::RowParser do
Timecop.freeze(Date.new(2022, 4, 2)) do
example.run
end
- Timecop.return
end
let(:attributes) { setup_section_params.merge({ field_2: "1", field_3: "1", field_4: "22" }) }
let(:bulk_upload) { create(:bulk_upload, :sales, user:, year: 2022) }
- it "returns errors" do
- expect(parser.errors[:field_2]).to be_present
- expect(parser.errors[:field_3]).to be_present
- expect(parser.errors[:field_4]).to be_present
+ it "returns setup errors" do
+ expect(parser.errors.where(:field_2, category: :setup)).to be_present
+ expect(parser.errors.where(:field_3, category: :setup)).to be_present
+ expect(parser.errors.where(:field_4, category: :setup)).to be_present
+ end
+ end
+ end
+
+ describe "soft validations" do
+ context "when soft validation is triggered" do
+ let(:attributes) { valid_attributes.merge({ field_7: 22, field_24: 5 }) }
+
+ it "adds an error to the relevant fields" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_7 }).to be_present
+ expect(soft_validation_errors.find { |e| e.attribute == :field_24 }).to be_present
+ end
+
+ it "populates with correct error message" do
+ soft_validation_errors = parser.errors.select { |e| e.options[:category] == :soft_validation }
+
+ expect(soft_validation_errors.find { |e| e.attribute == :field_7 }.message).to eql("You told us this person is aged 22 years and retired.")
+ expect(soft_validation_errors.find { |e| e.attribute == :field_24 }.message).to eql("You told us this person is aged 22 years and retired.")
end
end
end
diff --git a/spec/services/csv/sales_log_csv_service_spec.rb b/spec/services/csv/sales_log_csv_service_spec.rb
new file mode 100644
index 000000000..96099aa70
--- /dev/null
+++ b/spec/services/csv/sales_log_csv_service_spec.rb
@@ -0,0 +1,189 @@
+require "rails_helper"
+
+RSpec.describe Csv::SalesLogCsvService do
+ let(:form_handler_mock) { instance_double(FormHandler) }
+ let(:organisation) { create(:organisation) }
+ let!(:log) { create(:sales_log, :completed, owning_organisation: organisation) }
+ let(:service) { described_class.new(export_type: "labels") }
+ let(:csv) { CSV.parse(service.prepare_csv(SalesLog.all)) }
+
+ it "calls the form handler to get all questions in order when initialized" do
+ allow(FormHandler).to receive(:instance).and_return(form_handler_mock)
+ allow(form_handler_mock).to receive(:ordered_sales_questions_for_all_years).and_return([])
+ described_class.new(export_type: "codes")
+ expect(form_handler_mock).to have_received(:ordered_sales_questions_for_all_years)
+ end
+
+ it "returns a string" do
+ result = service.prepare_csv(SalesLog.all)
+ expect(result).to be_a String
+ end
+
+ it "returns a csv with headers" do
+ expect(csv.first.first).to eq "id"
+ expect(csv.second.first).not_to be log.id.to_s
+ end
+
+ context "when stubbing :ordered_sales_questions_for_all_years" do
+ let(:sales_form) do
+ FormFactory.new(year: 1936, type: "sales")
+ .with_sections([build(:section, :with_questions, question_ids:, questions:)])
+ .build
+ end
+ let(:question_ids) { nil }
+ let(:questions) { nil }
+
+ before do
+ allow(FormHandler).to receive(:instance).and_return(form_handler_mock)
+ allow(form_handler_mock).to receive(:form_name_from_start_year)
+ allow(form_handler_mock).to receive(:get_form).and_return(sales_form)
+ allow(form_handler_mock).to receive(:ordered_sales_questions_for_all_years).and_return(sales_form.questions)
+ end
+
+ context "when it returns questions with particular ids" do
+ let(:question_ids) { %w[type age1 buy1livein exdate] }
+
+ it "includes log attributes related to questions to the headers" do
+ headers = csv.first
+ expect(headers).to include(*question_ids.first(3))
+ end
+
+ it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do
+ headers = csv.first
+ expect(headers).not_to include "exdate"
+ expect(headers.last(4)).to eq %w[buy1livein exday exmonth exyear]
+ end
+ end
+
+ context "when it returns questions with particular features" do
+ let(:questions) do
+ [
+ build(:question, id: "attribute_value_check", type: "interruption_screen"),
+ build(:question, id: "something_or_other_known", type: "radio"),
+ build(:question, id: "whatchamacallit_asked", type: "radio"),
+ build(:question, id: "ownershipsch"),
+ build(:question, id: "checkbox_question", type: "checkbox", answer_options: { "pregyrha" => {}, "pregother" => {} }),
+ build(:question, id: "type"),
+ ]
+ end
+
+ it "does not add questions for checks, whether some other attribute is known or whether something else was asked" do
+ headers = csv.first
+ expect(headers).not_to include "attribute_value_check"
+ expect(headers).not_to include "something_or_other_known"
+ expect(headers).not_to include "whatchamacallit_asked"
+ end
+
+ it "does not add the id of checkbox questions, but adds the related attributes of the log in the correct order" do
+ headers = csv.first
+ expect(headers.last(4)).to eq %w[ownershipsch pregyrha pregother type]
+ end
+ end
+ end
+
+ it "includes attributes not related to questions to the headers" do
+ headers = csv.first
+ expect(headers).to include(*%w[id status created_at updated_at old_id])
+ end
+
+ it "returns a csv with the correct number of logs" do
+ create_list(:sales_log, 15)
+ log_count = SalesLog.count
+ expected_row_count_with_headers = log_count + 1
+ expect(csv.size).to be expected_row_count_with_headers
+ end
+
+ context "when exporting with human readable labels" do
+ it "gives answers to radio questions as their labels" do
+ national_column_index = csv.first.index("national")
+ national_value = csv.second[national_column_index]
+ expect(national_value).to eq "United Kingdom"
+ relat2_column_index = csv.first.index("relat2")
+ relat2_value = csv.second[relat2_column_index]
+ expect(relat2_value).to eq "Partner"
+ end
+
+ it "gives answers to free input questions as the user input" do
+ age1_column_index = csv.first.index("age1")
+ age1_value = csv.second[age1_column_index]
+ expect(age1_value).to eq 30.to_s
+ postcode_part1, postcode_part2 = log.postcode_full.split
+ postcode_part1_column_index = csv.first.index("pcode1")
+ postcode_part1_value = csv.second[postcode_part1_column_index]
+ expect(postcode_part1_value).to eq postcode_part1
+ postcode_part2_column_index = csv.first.index("pcode2")
+ postcode_part2_value = csv.second[postcode_part2_column_index]
+ expect(postcode_part2_value).to eq postcode_part2
+ end
+
+ it "exports the code for the local authority under the heading 'la'" do
+ la_column_index = csv.first.index("la")
+ la_value = csv.second[la_column_index]
+ expect(la_value).to eq "E09000003"
+ end
+
+ it "exports the label for the local authority under the heading 'la_label'" do
+ la_label_column_index = csv.first.index("la_label")
+ la_label_value = csv.second[la_label_column_index]
+ expect(la_label_value).to eq "Barnet"
+ end
+
+ it "exports the CSV with all values correct" do
+ expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_labels.csv")
+ values_to_delete = %w[id]
+ values_to_delete.each do |attribute|
+ index = csv.first.index(attribute)
+ csv.second[index] = nil
+ end
+ expect(csv).to eq expected_content
+ end
+ end
+
+ context "when exporting values as codes" do
+ let(:service) { described_class.new(export_type: "codes") }
+
+ it "gives answers to radio questions as their codes" do
+ national_column_index = csv.first.index("national")
+ national_value = csv.second[national_column_index]
+ expect(national_value).to eq 18.to_s
+ relat2_column_index = csv.first.index("relat2")
+ relat2_value = csv.second[relat2_column_index]
+ expect(relat2_value).to eq "P"
+ end
+
+ it "gives answers to free input questions as the user input" do
+ age1_column_index = csv.first.index("age1")
+ age1_value = csv.second[age1_column_index]
+ expect(age1_value).to eq 30.to_s
+ postcode_part1, postcode_part2 = log.postcode_full.split
+ postcode_part1_column_index = csv.first.index("pcode1")
+ postcode_part1_value = csv.second[postcode_part1_column_index]
+ expect(postcode_part1_value).to eq postcode_part1
+ postcode_part2_column_index = csv.first.index("pcode2")
+ postcode_part2_value = csv.second[postcode_part2_column_index]
+ expect(postcode_part2_value).to eq postcode_part2
+ end
+
+ it "exports the code for the local authority under the heading 'la'" do
+ la_column_index = csv.first.index("la")
+ la_value = csv.second[la_column_index]
+ expect(la_value).to eq "E09000003"
+ end
+
+ it "exports the label for the local authority under the heading 'la_label'" do
+ la_label_column_index = csv.first.index("la_label")
+ la_label_value = csv.second[la_label_column_index]
+ expect(la_label_value).to eq "Barnet"
+ end
+
+ it "exports the CSV with all values correct" do
+ expected_content = CSV.read("spec/fixtures/files/sales_logs_csv_export_codes.csv")
+ values_to_delete = %w[id]
+ values_to_delete.each do |attribute|
+ index = csv.first.index(attribute)
+ csv.second[index] = nil
+ end
+ expect(csv).to eq expected_content
+ end
+ end
+end
diff --git a/spec/services/imports/lettings_logs_import_service_spec.rb b/spec/services/imports/lettings_logs_import_service_spec.rb
index ec41ba366..6132890a1 100644
--- a/spec/services/imports/lettings_logs_import_service_spec.rb
+++ b/spec/services/imports/lettings_logs_import_service_spec.rb
@@ -1173,6 +1173,68 @@ RSpec.describe Imports::LettingsLogsImportService do
end
end
+ context "and an error is added to tcharge for in progress log" do
+ let(:lettings_log_id) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
+ let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
+ let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
+
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "saved"
+ lettings_log_xml.at_xpath("//xmlns:Q18ai").content = "1"
+ lettings_log_xml.at_xpath("//xmlns:Q18aii").content = "2"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiii").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiv").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18av").content = "9"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with("Log 00d2343e-d5fa-4c89-8400-ec3854b0f2b4: Removing field tcharge from log triggering validation: under_10")
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.tcharge).to be_nil
+ expect(lettings_log.brent).to be_nil
+ expect(lettings_log.scharge).to be_nil
+ expect(lettings_log.pscharge).to be_nil
+ expect(lettings_log.supcharg).to be_nil
+ end
+ end
+
+ context "and the earnings is not a whole number" do
+ let(:lettings_log_id) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
+ let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
+ let(:lettings_log_xml) { Nokogiri::XML(lettings_log_file) }
+
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "submitted"
+ lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly"
+ lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 100.59
+ lettings_log_xml.at_xpath("//xmlns:Q8Refused").content = ""
+ end
+
+ it "does not error" do
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "rounds the earnings value" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.earnings).to eq(101)
+ end
+ end
+
context "when setting location fields for 23/24 logs" do
let(:lettings_log_id) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
let(:lettings_log_file) { open_file(fixture_directory, lettings_log_id) }
diff --git a/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb
index c06b7bf42..eb7051a81 100644
--- a/spec/services/imports/sales_logs_import_service_spec.rb
+++ b/spec/services/imports/sales_logs_import_service_spec.rb
@@ -528,7 +528,7 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Log shared_ownership_sales_log: Removing equity as the equity is invalid/)
+ expect(logger).to receive(:warn).with(/Removing equity with error: The maximum initial equity stake is 75%/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -552,7 +552,7 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Log shared_ownership_sales_log: Removing equity as the equity is invalid/)
+ expect(logger).to receive(:warn).with(/Removing equity with error: The minimum initial equity stake for this type of shared ownership sale is 25%/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -595,6 +595,33 @@ RSpec.describe Imports::SalesLogsImportService do
end
end
+ context "and it has a record with previous postcode in invalid format" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q7Postcode").content = "L3132AF"
+ sales_log_xml.at_xpath("//xmlns:Q7ONSLACode").content = "E07000223"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Log shared_ownership_sales_log: Removing previous postcode as the postcode is invalid/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers and sets correct prevloc" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.ppostcode_full).to be_nil
+ expect(sales_log.ppcodenk).to eq(1) # not known
+ expect(sales_log.prevloc).to eq("E07000223") # not known
+ end
+ end
+
context "and setup field has validation error in incomplete log" do
let(:sales_log_id) { "shared_ownership_sales_log" }
@@ -631,7 +658,8 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing previous postcode known and previous postcode as the postcode is invalid/)
+ expect(logger).to receive(:warn).with(/Removing ppcodenk with error: Buyer's last accommodation and discounted ownership postcodes must match, Last settled accommodation and discounted ownership property postcodes must match/)
+ expect(logger).to receive(:warn).with(/Removing ppostcode_full with error: Buyer's last accommodation and discounted ownership postcodes must match, Last settled accommodation and discounted ownership property postcodes must match/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -701,7 +729,7 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing exchange date as the exchange date is invalid/)
+ expect(logger).to receive(:warn).with(/Removing exdate with error: Contract exchange date must be less than 1 year before sale completion date/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -726,7 +754,7 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing mortgage because it cannot be 0/)
+ expect(logger).to receive(:warn).with(/Removing mortgage with error: Mortgage amount must be at least £1, Mortgage value cannot be £0 if a mortgage was used for the purchase of this property/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -742,7 +770,7 @@ RSpec.describe Imports::SalesLogsImportService do
end
end
- context "and it has an invalid income" do
+ context "and it has an invalid income 1" do
let(:sales_log_id) { "shared_ownership_sales_log" }
before do
@@ -751,7 +779,58 @@ RSpec.describe Imports::SalesLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with(/Removing income1 as the income1 is invalid/)
+ expect(logger).to receive(:warn).with(/Removing income1 with error: Income must be £80,000 or lower for properties outside London local authority/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.income1).to be_nil
+ end
+ end
+
+ context "and it has an invalid income 2" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q2Person1Income").content = "0"
+ sales_log_xml.at_xpath("//xmlns:Q2Person2Income").content = "95000"
+ sales_log_xml.at_xpath("//xmlns:Q14ONSLACode").content = "E07000223"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing income2 with error: Combined income must be £80,000 or lower for properties outside London local authorities, Income must be £80,000 or lower for properties outside London local authority/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.income2).to be_nil
+ end
+ end
+
+ context "and it has an invalid income 1 for london" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q2Person1Income").content = "95000"
+ sales_log_xml.at_xpath("//xmlns:Q14ONSLACode").content = "E09000012"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing income1 with error: Income must be £90,000 or lower for properties within a London local authority/)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.not_to raise_error
end
@@ -767,6 +846,81 @@ RSpec.describe Imports::SalesLogsImportService do
end
end
+ context "and it has an invalid income 2 for london" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q2Person2Income").content = "95000"
+ sales_log_xml.at_xpath("//xmlns:Q14ONSLACode").content = "E09000012"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing income2 with error: Combined income must be £90,000 or lower for properties within a London local authority, Income must be £90,000 or lower for properties within a London local authority/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.income2).to be_nil
+ end
+ end
+
+ context "and it has an invalid mscharge" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q29MonthlyCharges").content = "0.1"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing mscharge with error: Monthly leasehold charges must be at least £1/)
+ expect(logger).to receive(:warn).with(/Removing has_mscharge with error: Monthly leasehold charges must be at least £1/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.mscharge).to be_nil
+ expect(sales_log.has_mscharge).to be_nil
+ end
+ end
+
+ context "and it has an invalid frombeds" do
+ let(:sales_log_id) { "shared_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q20Bedrooms").content = "0"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with(/Removing frombeds with error: Number of bedrooms in previous property must be between 1 and 6/)
+ expect { sales_log_service.send(:create_log, sales_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ sales_log_service.send(:create_log, sales_log_xml)
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+
+ expect(sales_log).not_to be_nil
+ expect(sales_log.frombeds).to be_nil
+ end
+ end
+
context "when inferring default answers for completed sales logs" do
context "when the armedforcesspouse is not answered" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
@@ -817,6 +971,26 @@ RSpec.describe Imports::SalesLogsImportService do
end
end
+ context "when the savings is given not to the nearest 10" do
+ let(:sales_log_id) { "discounted_ownership_sales_log" }
+
+ before do
+ sales_log_xml.at_xpath("//xmlns:Q3Savings").content = "10013"
+ allow(logger).to receive(:warn).and_return(nil)
+ end
+
+ it "does not error" do
+ expect { sales_log_service.send(:create_log, sales_log_xml) }.not_to raise_error
+ end
+
+ it "sets savings to the nearest 10" do
+ sales_log_service.send(:create_log, sales_log_xml)
+
+ sales_log = SalesLog.find_by(old_id: sales_log_id)
+ expect(sales_log&.savings).to be(10_010)
+ end
+ end
+
context "when inferring age known" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
diff --git a/webpack.config.js b/webpack.config.js
index c027f2dd2..d2f1d8993 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,7 +23,6 @@ module.exports = {
path.resolve(__dirname, 'node_modules/@hotwired/stimulus'),
path.resolve(__dirname, 'node_modules/@stimulus/polyfills'),
path.resolve(__dirname, 'node_modules/@rails/actioncable'),
- path.resolve(__dirname, 'node_modules/chartjs'),
path.resolve(__dirname, 'app/frontend')
],
use: ['babel-loader']
diff --git a/yarn.lock b/yarn.lock
index 1fcfee856..272885f74 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1964,11 +1964,6 @@ character-parser@^2.2.0:
dependencies:
is-regex "^1.0.3"
-chart.js@^3.6.0:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.9.1.tgz#3abf2c775169c4c71217a107163ac708515924b8"
- integrity sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==
-
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1, chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
@@ -4272,9 +4267,9 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
nunjucks@^3.2.3:
- version "3.2.3"
- resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.3.tgz#1b33615247290e94e28263b5d855ece765648a31"
- integrity sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.4.tgz#f0878eef528ce7b0aa35d67cc6898635fd74649e"
+ integrity sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==
dependencies:
a-sync-waterfall "^1.0.0"
asap "^2.0.3"
@@ -5955,10 +5950,10 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
-webpack@^5.70.0:
- version "5.74.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980"
- integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==
+webpack@^5.76.0:
+ version "5.76.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c"
+ integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==
dependencies:
"@types/eslint-scope" "^3.7.3"
"@types/estree" "^0.0.51"