diff --git a/app/components/bulk_upload_error_summary_table_component.rb b/app/components/bulk_upload_error_summary_table_component.rb index 909fb5f0d..8dddb61d2 100644 --- a/app/components/bulk_upload_error_summary_table_component.rb +++ b/app/components/bulk_upload_error_summary_table_component.rb @@ -12,7 +12,7 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base end def sorted_errors - @sorted_errors ||= bulk_upload + @sorted_errors ||= setup_errors.presence || bulk_upload .bulk_upload_errors .group(:col, :field, :error) .having("count(*) > ?", display_threshold) @@ -26,6 +26,16 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base private + def setup_errors + @setup_errors ||= bulk_upload + .bulk_upload_errors + .where(category: "setup") + .group(:col, :field, :error) + .having("count(*) > ?", display_threshold) + .count + .sort_by { |el| el[0][0].rjust(3, "0") } + end + def display_threshold DISPLAY_THRESHOLD end 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 3b4c4978a..31c3bffac 100644 --- a/app/components/check_answers_summary_list_card_component.html.erb +++ b/app/components/check_answers_summary_list_card_component.html.erb @@ -12,16 +12,22 @@ <% summary_list.row do |row| %> <% row.key { get_question_label(question) } %> <% row.value do %> - <%= get_answer_label(question) %> + <%= simple_format( + get_answer_label(question), + wrapper_tag: "span", + class: "govuk-!-margin-right-4", + ) %> <% extra_value = question.get_extra_check_answer_value(log) %> - <% if extra_value %> - <%= extra_value %> + <% if extra_value && question.answer_label(log).present? %> + <%= simple_format( + extra_value, + wrapper_tag: "span", + class: "govuk-!-font-weight-regular app-!-colour-muted", + ) %> <% end %> -
- <% question.get_inferred_answers(log).each do |inferred_answer| %> <%= inferred_answer %> <% end %> diff --git a/app/mailers/bulk_upload_mailer.rb b/app/mailers/bulk_upload_mailer.rb index 144acb3e1..d91842bce 100644 --- a/app/mailers/bulk_upload_mailer.rb +++ b/app/mailers/bulk_upload_mailer.rb @@ -33,19 +33,7 @@ class BulkUploadMailer < NotifyMailer ) end - def columns_with_errors(bulk_upload:) - array = bulk_upload.columns_with_errors - - if array.size > 3 - "#{array.take(3).join(', ')} and more" - else - array.join(", ") - end - end - def send_correct_and_upload_again_mail(bulk_upload:) - error_description = "We noticed that you have a lot of similar errors in column #{columns_with_errors(bulk_upload:)}. Please correct your data export and upload again." - summary_report_link = if BulkUploadErrorSummaryTableComponent.new(bulk_upload:).errors? summary_bulk_upload_lettings_result_url(bulk_upload) else @@ -60,7 +48,6 @@ class BulkUploadMailer < NotifyMailer upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time), year_combo: bulk_upload.year_combo, lettings_or_sales: bulk_upload.log_type, - error_description:, summary_report_link:, }, ) diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index ff334b968..0952b60af 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -30,14 +30,6 @@ class BulkUpload < ApplicationRecord end end - def columns_with_errors - bulk_upload_errors - .select(:col) - .distinct(:col) - .pluck(:col) - .sort_by { |col| col.rjust(2, "0") } - end - def general_needs? needstype == 1 end diff --git a/app/models/derived_variables/lettings_log_variables.rb b/app/models/derived_variables/lettings_log_variables.rb index d42fb3903..aae49422d 100644 --- a/app/models/derived_variables/lettings_log_variables.rb +++ b/app/models/derived_variables/lettings_log_variables.rb @@ -94,6 +94,17 @@ module DerivedVariables::LettingsLogVariables self.vacdays = property_vacant_days set_housingneeds_fields if housingneeds? + + if uprn_known&.zero? + self.uprn = nil + end + + if uprn_confirmed&.zero? + self.uprn = nil + self.uprn_known = 0 + end + + reset_address_fields! if is_supported_housing? end private @@ -229,4 +240,14 @@ private self.housingneeds_g = 0 self.housingneeds_h = 0 end + + def reset_address_fields! + self.uprn = nil + self.uprn_known = nil + self.uprn_confirmed = nil + self.address_line1 = nil + self.address_line2 = nil + self.town_or_city = nil + self.county = nil + end end diff --git a/app/models/form.rb b/app/models/form.rb index c7bb4f2b0..8f9dc47f9 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -7,9 +7,9 @@ class Form if sales_or_start_year_after_2022?(type, start_year) @start_date = Time.zone.local(start_year, 4, 1) @end_date = if start_year && start_year.to_i > 2022 - Time.zone.local(start_year + 1, 7, 9) + Time.zone.local(start_year + 1, 6, 9) else - Time.zone.local(start_year + 1, 7, 7) + Time.zone.local(start_year + 1, 6, 7) end @setup_sections = type == "sales" ? [Form::Sales::Sections::Setup.new(nil, nil, self)] : [Form::Lettings::Sections::Setup.new(nil, nil, self)] @form_sections = sections_in_form.map { |sec| sec.new(nil, nil, self) } @@ -111,8 +111,8 @@ class Form when :in_progress "#{next_subsection.id}/check_answers".dasherize when :not_started - first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(log, nil) }.id - first_question_in_subsection.to_s.dasherize + first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(log, nil) } + first_question_in_subsection ? first_question_in_subsection.id.to_s.dasherize : next_incomplete_section_redirect_path(next_subsection, log) else "error" end diff --git a/app/models/form/lettings/pages/address.rb b/app/models/form/lettings/pages/address.rb new file mode 100644 index 000000000..cf6f73036 --- /dev/null +++ b/app/models/form/lettings/pages/address.rb @@ -0,0 +1,24 @@ +class Form::Lettings::Pages::Address < ::Form::Page + def initialize(id, hsh, subsection) + super + @id = "address" + @header = "Q12 - What is the property's address?" + end + + def questions + @questions ||= [ + Form::Lettings::Questions::AddressLine1.new(nil, nil, self), + Form::Lettings::Questions::AddressLine2.new(nil, nil, self), + Form::Lettings::Questions::TownOrCity.new(nil, nil, self), + Form::Lettings::Questions::County.new(nil, nil, self), + Form::Lettings::Questions::PostcodeForFullAddress.new(nil, nil, self), + ] + end + + def routed_to?(log, _current_user = nil) + return false if log.uprn_known.nil? + return false if log.is_supported_housing? + + log.uprn_confirmed != 1 || log.uprn_known.zero? + end +end 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 new file mode 100644 index 000000000..32468e364 --- /dev/null +++ b/app/models/form/lettings/pages/care_home_charges_value_check.rb @@ -0,0 +1,15 @@ +class Form::Lettings::Pages::CareHomeChargesValueCheck < ::Form::Page + def initialize(id, hsh, subsection) + super + @id = "care_home_charges_value_check" + @depends_on = [{ "care_home_charge_expected_not_provided?" => true }] + @title_text = { + "translation" => "soft_validations.care_home_charges.title_text", + } + @informative_text = "" + end + + def questions + @questions ||= [Form::Lettings::Questions::CareHomeChargesValueCheck.new(nil, nil, self)] + end +end diff --git a/app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb b/app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb index fc65488e2..eafb145b5 100644 --- a/app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb +++ b/app/models/form/lettings/pages/first_time_property_let_as_social_housing.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::FirstTimePropertyLetAsSocialHousing < ::Form::Page def initialize(id, hsh, subsection) super @id = "first_time_property_let_as_social_housing" - @depends_on = [{ "renewal" => 0 }] + @depends_on = [{ "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/new_build_handover_date.rb b/app/models/form/lettings/pages/new_build_handover_date.rb index 7b13c7727..e7cb2e5d9 100644 --- a/app/models/form/lettings/pages/new_build_handover_date.rb +++ b/app/models/form/lettings/pages/new_build_handover_date.rb @@ -2,11 +2,7 @@ class Form::Lettings::Pages::NewBuildHandoverDate < ::Form::Page def initialize(id, hsh, subsection) super @id = "new_build_handover_date" - @depends_on = [ - { "renewal" => 0, "rsnvac" => 15 }, - { "renewal" => 0, "rsnvac" => 16 }, - { "renewal" => 0, "rsnvac" => 17 }, - ] + @depends_on = [{ "is_renewal?" => false, "has_first_let_vacancy_reason?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_building_type.rb b/app/models/form/lettings/pages/property_building_type.rb index aec9fa4a9..ff3d76e0b 100644 --- a/app/models/form/lettings/pages/property_building_type.rb +++ b/app/models/form/lettings/pages/property_building_type.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyBuildingType < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_building_type" - @depends_on = [{ "needstype" => 1 }] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_let_type.rb b/app/models/form/lettings/pages/property_let_type.rb index f4d629b9e..6bdb94803 100644 --- a/app/models/form/lettings/pages/property_let_type.rb +++ b/app/models/form/lettings/pages/property_let_type.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyLetType < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_let_type" - @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0, "needstype" => 1 }] + @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/property_local_authority.rb b/app/models/form/lettings/pages/property_local_authority.rb index 711d908d8..7692fd376 100644 --- a/app/models/form/lettings/pages/property_local_authority.rb +++ b/app/models/form/lettings/pages/property_local_authority.rb @@ -2,10 +2,18 @@ class Form::Lettings::Pages::PropertyLocalAuthority < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_local_authority" - @depends_on = [{ "is_la_inferred" => false, "needstype" => 1 }] + @depends_on = [{ "is_la_inferred" => false, "is_general_needs?" => true }] end def questions @questions ||= [Form::Lettings::Questions::La.new(nil, nil, self)] end + + def routed_to?(log, _current_user = nil) + return false if log.uprn_known.nil? && form.start_date.year >= 2023 + return false if log.is_la_inferred? + return false if log.is_supported_housing? + + true + end end diff --git a/app/models/form/lettings/pages/property_major_repairs.rb b/app/models/form/lettings/pages/property_major_repairs.rb index 54a32a1ad..985b5dce1 100644 --- a/app/models/form/lettings/pages/property_major_repairs.rb +++ b/app/models/form/lettings/pages/property_major_repairs.rb @@ -2,18 +2,7 @@ class Form::Lettings::Pages::PropertyMajorRepairs < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_major_repairs" - @depends_on = [ - { "renewal" => 0, "rsnvac" => 5 }, - { "renewal" => 0, "rsnvac" => 6 }, - { "renewal" => 0, "rsnvac" => 8 }, - { "renewal" => 0, "rsnvac" => 9 }, - { "renewal" => 0, "rsnvac" => 10 }, - { "renewal" => 0, "rsnvac" => 11 }, - { "renewal" => 0, "rsnvac" => 12 }, - { "renewal" => 0, "rsnvac" => 13 }, - { "renewal" => 0, "rsnvac" => 18 }, - { "renewal" => 0, "rsnvac" => 19 }, - ] + @depends_on = [{ "is_renewal?" => false, "vacancy_reason_not_renewal_or_first_let?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_number_of_bedrooms.rb b/app/models/form/lettings/pages/property_number_of_bedrooms.rb index 89c056e00..c3a1a2365 100644 --- a/app/models/form/lettings/pages/property_number_of_bedrooms.rb +++ b/app/models/form/lettings/pages/property_number_of_bedrooms.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfBedrooms < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_number_of_bedrooms" - @depends_on = [{ "needstype" => 1 }] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb b/app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb index 6061fcaaa..b82a4757e 100644 --- a/app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb +++ b/app/models/form/lettings/pages/property_number_of_times_relet_not_social_let.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfTimesReletNotSocialLet < ::Form::Pa def initialize(id, hsh, subsection) super @id = "property_number_of_times_relet_not_social_let" - @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0 }] + @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb b/app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb index f1a136249..5785a2961 100644 --- a/app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb +++ b/app/models/form/lettings/pages/property_number_of_times_relet_social_let.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyNumberOfTimesReletSocialLet < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_number_of_times_relet_social_let" - @depends_on = [{ "first_time_property_let_as_social_housing" => 1, "renewal" => 0 }] + @depends_on = [{ "first_time_property_let_as_social_housing" => 1, "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/property_postcode.rb b/app/models/form/lettings/pages/property_postcode.rb index 720cd3106..a40d4140f 100644 --- a/app/models/form/lettings/pages/property_postcode.rb +++ b/app/models/form/lettings/pages/property_postcode.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyPostcode < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_postcode" - @depends_on = [{ "needstype" => 1 }] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_unit_type.rb b/app/models/form/lettings/pages/property_unit_type.rb index 6db4db4e4..727e740cd 100644 --- a/app/models/form/lettings/pages/property_unit_type.rb +++ b/app/models/form/lettings/pages/property_unit_type.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyUnitType < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_unit_type" - @depends_on = [{ "needstype" => 1 }] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/pages/property_vacancy_reason_first_let.rb b/app/models/form/lettings/pages/property_vacancy_reason_first_let.rb index 3a14827de..85dd5d690 100644 --- a/app/models/form/lettings/pages/property_vacancy_reason_first_let.rb +++ b/app/models/form/lettings/pages/property_vacancy_reason_first_let.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyVacancyReasonFirstLet < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_vacancy_reason_first_let" - @depends_on = [{ "first_time_property_let_as_social_housing" => 1, "renewal" => 0 }] + @depends_on = [{ "first_time_property_let_as_social_housing" => 1, "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb b/app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb index 1b2c147ed..4fdf7fef5 100644 --- a/app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb +++ b/app/models/form/lettings/pages/property_vacancy_reason_not_first_let.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyVacancyReasonNotFirstLet < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_vacancy_reason_not_first_let" - @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "renewal" => 0 }] + @depends_on = [{ "first_time_property_let_as_social_housing" => 0, "is_renewal?" => false }] end def questions diff --git a/app/models/form/lettings/pages/property_wheelchair_accessible.rb b/app/models/form/lettings/pages/property_wheelchair_accessible.rb index e5d673ef0..3b2b226b6 100644 --- a/app/models/form/lettings/pages/property_wheelchair_accessible.rb +++ b/app/models/form/lettings/pages/property_wheelchair_accessible.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::PropertyWheelchairAccessible < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_wheelchair_accessible" - @depends_on = [{ "is_supported_housing?" => false }] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/pages/uprn.rb b/app/models/form/lettings/pages/uprn.rb new file mode 100644 index 000000000..7b6b90f1a --- /dev/null +++ b/app/models/form/lettings/pages/uprn.rb @@ -0,0 +1,28 @@ +class Form::Lettings::Pages::Uprn < ::Form::Page + def initialize(id, hsh, subsection) + super + @id = "uprn" + end + + def questions + @questions ||= [ + Form::Lettings::Questions::Uprn.new(nil, nil, self), + ] + end + + def routed_to?(log, _current_user = nil) + return false if log.is_supported_housing? + + log.uprn_known == 1 + end + + def skip_text + "Enter address instead" + end + + def skip_href(log = nil) + return unless log + + "/#{log.model_name.param_key.dasherize}s/#{log.id}/address" + end +end diff --git a/app/models/form/lettings/pages/uprn_confirmation.rb b/app/models/form/lettings/pages/uprn_confirmation.rb new file mode 100644 index 000000000..26cde2d97 --- /dev/null +++ b/app/models/form/lettings/pages/uprn_confirmation.rb @@ -0,0 +1,17 @@ +class Form::Lettings::Pages::UprnConfirmation < ::Form::Page + def initialize(id, hsh, subsection) + super + @id = "uprn_confirmation" + @header = "We found an address that might be this property" + end + + def questions + @questions ||= [ + Form::Lettings::Questions::UprnConfirmation.new(nil, nil, self), + ] + end + + def routed_to?(log, _current_user = nil) + log.uprn.present? && log.uprn_known == 1 + end +end diff --git a/app/models/form/lettings/pages/uprn_known.rb b/app/models/form/lettings/pages/uprn_known.rb new file mode 100644 index 000000000..1ded1ba82 --- /dev/null +++ b/app/models/form/lettings/pages/uprn_known.rb @@ -0,0 +1,16 @@ +class Form::Lettings::Pages::UprnKnown < ::Form::Page + def initialize(id, hsh, subsection) + super + @id = "uprn_known" + end + + def questions + @questions ||= [ + Form::Lettings::Questions::UprnKnown.new(nil, nil, self), + ] + end + + def routed_to?(log, _current_user = nil) + !log.is_supported_housing? + end +end diff --git a/app/models/form/lettings/pages/void_or_renewal_date.rb b/app/models/form/lettings/pages/void_or_renewal_date.rb index 1ea4ea982..0905f1058 100644 --- a/app/models/form/lettings/pages/void_or_renewal_date.rb +++ b/app/models/form/lettings/pages/void_or_renewal_date.rb @@ -2,18 +2,7 @@ class Form::Lettings::Pages::VoidOrRenewalDate < ::Form::Page def initialize(id, hsh, subsection) super @id = "void_or_renewal_date" - @depends_on = [ - { "renewal" => 0, "rsnvac" => 5 }, - { "renewal" => 0, "rsnvac" => 6 }, - { "renewal" => 0, "rsnvac" => 8 }, - { "renewal" => 0, "rsnvac" => 9 }, - { "renewal" => 0, "rsnvac" => 10 }, - { "renewal" => 0, "rsnvac" => 11 }, - { "renewal" => 0, "rsnvac" => 12 }, - { "renewal" => 0, "rsnvac" => 13 }, - { "renewal" => 0, "rsnvac" => 18 }, - { "renewal" => 0, "rsnvac" => 19 }, - ] + @depends_on = [{ "is_renewal?" => false, "vacancy_reason_not_renewal_or_first_let?" => true }] end def questions diff --git a/app/models/form/lettings/questions/address_line1.rb b/app/models/form/lettings/questions/address_line1.rb new file mode 100644 index 000000000..b3288c82c --- /dev/null +++ b/app/models/form/lettings/questions/address_line1.rb @@ -0,0 +1,38 @@ +class Form::Lettings::Questions::AddressLine1 < ::Form::Question + def initialize(id, hsh, page) + super + @id = "address_line1" + @check_answer_label = "Address" + @header = "Address line 1" + @type = "text" + @plain_label = true + @check_answer_label = "Q12 - Address" + end + + def hidden_in_check_answers?(log, _current_user = nil) + return true if log.uprn_known.nil? + return false if log.uprn_known&.zero? + return true if log.uprn_confirmed.nil? && log.uprn.present? + return true if log.uprn_known == 1 && log.uprn.blank? + + log.uprn_confirmed == 1 + end + + def answer_label(log, _current_user = nil) + [ + log.address_line1, + log.address_line2, + log.postcode_full, + log.town_or_city, + log.county, + ].select(&:present?).join("\n") + end + + def get_extra_check_answer_value(log) + return unless log.is_la_inferred? + + la = LocalAuthority.find_by(code: log.la)&.name + + la.presence + end +end diff --git a/app/models/form/lettings/questions/address_line2.rb b/app/models/form/lettings/questions/address_line2.rb new file mode 100644 index 000000000..16f7c8336 --- /dev/null +++ b/app/models/form/lettings/questions/address_line2.rb @@ -0,0 +1,13 @@ +class Form::Lettings::Questions::AddressLine2 < ::Form::Question + def initialize(id, hsh, page) + super + @id = "address_line2" + @header = "Address line 2 (optional)" + @type = "text" + @plain_label = true + end + + def hidden_in_check_answers?(_log = nil, _current_user = nil) + true + end +end diff --git a/app/models/form/lettings/questions/care_home_charges_value_check.rb b/app/models/form/lettings/questions/care_home_charges_value_check.rb new file mode 100644 index 000000000..fdb5aabbd --- /dev/null +++ b/app/models/form/lettings/questions/care_home_charges_value_check.rb @@ -0,0 +1,14 @@ +class Form::Lettings::Questions::CareHomeChargesValueCheck < ::Form::Question + def initialize(id, hsh, page) + super + @id = "carehome_charges_value_check" + @check_answer_label = "Care home charges confirmation" + @header = "Are you sure there are no care home charges?" + @type = "interruption_screen" + @check_answers_card_number = 0 + @answer_options = ANSWER_OPTIONS + @hidden_in_check_answers = { "depends_on" => [{ "carehome_charges_value_check" => 0 }, { "carehome_charges_value_check" => 1 }] } + end + + ANSWER_OPTIONS = { "0" => { "value" => "Yes" }, "1" => { "value" => "No" } }.freeze +end diff --git a/app/models/form/lettings/questions/county.rb b/app/models/form/lettings/questions/county.rb new file mode 100644 index 000000000..360c0966c --- /dev/null +++ b/app/models/form/lettings/questions/county.rb @@ -0,0 +1,13 @@ +class Form::Lettings::Questions::County < ::Form::Question + def initialize(id, hsh, page) + super + @id = "county" + @header = "County (optional)" + @type = "text" + @plain_label = true + end + + def hidden_in_check_answers?(_log = nil, _current_user = nil) + true + end +end diff --git a/app/models/form/lettings/questions/ethnic_black.rb b/app/models/form/lettings/questions/ethnic_black.rb index c6f0c81d5..8ae04982f 100644 --- a/app/models/form/lettings/questions/ethnic_black.rb +++ b/app/models/form/lettings/questions/ethnic_black.rb @@ -19,7 +19,7 @@ class Form::Lettings::Questions::EthnicBlack < ::Form::Question "value" => "Caribbean", }, "14" => { - "value" => "Any other Black, African or Caribbean background", + "value" => "Any other Black, African, Caribbean or Black British background", }, }.freeze end diff --git a/app/models/form/lettings/questions/la.rb b/app/models/form/lettings/questions/la.rb index 3cafda054..b70e7590b 100644 --- a/app/models/form/lettings/questions/la.rb +++ b/app/models/form/lettings/questions/la.rb @@ -13,4 +13,8 @@ class Form::Lettings::Questions::La < ::Form::Question def answer_options { "" => "Select an option" }.merge(LocalAuthority.active(form.start_date).england.map { |la| [la.code, la.name] }.to_h) end + + def hidden_in_check_answers?(log, _current_user = nil) + log.startdate && log.startdate.year >= 2023 && log.is_la_inferred? + end end diff --git a/app/models/form/lettings/questions/postcode_for_full_address.rb b/app/models/form/lettings/questions/postcode_for_full_address.rb new file mode 100644 index 000000000..015abc2e8 --- /dev/null +++ b/app/models/form/lettings/questions/postcode_for_full_address.rb @@ -0,0 +1,25 @@ +class Form::Lettings::Questions::PostcodeForFullAddress < ::Form::Question + def initialize(id, hsh, page) + super + @id = "postcode_full" + @header = "Postcode" + @type = "text" + @width = 5 + @inferred_check_answers_value = [{ + "condition" => { + "pcodenk" => 1, + }, + "value" => "Not known", + }] + @inferred_answers = { + "la" => { + "is_la_inferred" => true, + }, + } + @plain_label = true + end + + def hidden_in_check_answers?(_log = nil, _current_user = nil) + true + end +end diff --git a/app/models/form/lettings/questions/rsnvac_first_let.rb b/app/models/form/lettings/questions/rsnvac_first_let.rb index 8d7da0433..df66b57cd 100644 --- a/app/models/form/lettings/questions/rsnvac_first_let.rb +++ b/app/models/form/lettings/questions/rsnvac_first_let.rb @@ -12,11 +12,8 @@ class Form::Lettings::Questions::RsnvacFirstLet < ::Form::Question end ANSWER_OPTIONS = { - "16" => - { "value" => "First let of conversion, rehabilitation or acquired property" }, - "17" => - { "value" => "First let of leased property" }, - "15" => - { "value" => "First let of new-build property" }, + "16" => { "value" => "First let of conversion, rehabilitation or acquired property" }, + "17" => { "value" => "First let of leased property" }, + "15" => { "value" => "First let of new-build property" }, }.freeze end diff --git a/app/models/form/lettings/questions/town_or_city.rb b/app/models/form/lettings/questions/town_or_city.rb new file mode 100644 index 000000000..f1eac8dff --- /dev/null +++ b/app/models/form/lettings/questions/town_or_city.rb @@ -0,0 +1,13 @@ +class Form::Lettings::Questions::TownOrCity < ::Form::Question + def initialize(id, hsh, page) + super + @id = "town_or_city" + @header = "Town or city" + @type = "text" + @plain_label = true + end + + def hidden_in_check_answers?(_log = nil, _current_user = nil) + true + end +end diff --git a/app/models/form/lettings/questions/uprn.rb b/app/models/form/lettings/questions/uprn.rb new file mode 100644 index 000000000..efe9a4ea4 --- /dev/null +++ b/app/models/form/lettings/questions/uprn.rb @@ -0,0 +1,35 @@ +class Form::Lettings::Questions::Uprn < ::Form::Question + def initialize(id, hsh, page) + super + @id = "uprn" + @check_answer_label = "UPRN" + @header = "What is the property's UPRN" + @type = "text" + @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355." + @width = 10 + @question_number = 11 + end + + def unanswered_error_message + I18n.t("validations.property.uprn.invalid") + end + + def get_extra_check_answer_value(log) + value = [ + log.address_line1, + log.address_line2, + log.town_or_city, + log.county, + log.postcode_full, + (LocalAuthority.find_by(code: log.la)&.name if log.la.present?), + ].select(&:present?) + + return unless value.any? + + "\n\n#{value.join("\n")}" + end + + def hidden_in_check_answers?(log, _current_user = nil) + log.uprn_known != 1 + end +end diff --git a/app/models/form/lettings/questions/uprn_confirmation.rb b/app/models/form/lettings/questions/uprn_confirmation.rb new file mode 100644 index 000000000..5b7bbd535 --- /dev/null +++ b/app/models/form/lettings/questions/uprn_confirmation.rb @@ -0,0 +1,34 @@ +class Form::Lettings::Questions::UprnConfirmation < ::Form::Question + def initialize(id, hsh, page) + super + @id = "uprn_confirmed" + @header = "Is this the property address?" + @type = "radio" + @answer_options = ANSWER_OPTIONS + @check_answer_label = "Is this the right address?" + end + + ANSWER_OPTIONS = { + "1" => { "value" => "Yes" }, + "0" => { "value" => "No, I want to enter the address manually" }, + }.freeze + + def notification_banner(log = nil) + return unless log&.uprn + + { + title: "UPRN: #{log.uprn}", + heading: [ + log.address_line1, + log.address_line2, + log.postcode_full, + log.town_or_city, + log.county, + ].select(&:present?).join("\n"), + } + end + + def hidden_in_check_answers?(log, _current_user = nil) + log.uprn_known != 1 || log.uprn_confirmed.present? + end +end diff --git a/app/models/form/lettings/questions/uprn_known.rb b/app/models/form/lettings/questions/uprn_known.rb new file mode 100644 index 000000000..d206885fb --- /dev/null +++ b/app/models/form/lettings/questions/uprn_known.rb @@ -0,0 +1,21 @@ +class Form::Lettings::Questions::UprnKnown < ::Form::Question + def initialize(id, hsh, page) + super + @id = "uprn_known" + @check_answer_label = "UPRN known?" + @header = "Do you know the property's UPRN?" + @type = "radio" + @answer_options = ANSWER_OPTIONS + @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.

+ You can continue without the UPRN, but it means we will need you to enter the address of the property." + end + + ANSWER_OPTIONS = { + "1" => { "value" => "Yes" }, + "0" => { "value" => "No" }, + }.freeze + + def unanswered_error_message + I18n.t("validations.property.uprn_known.invalid") + end +end diff --git a/app/models/form/lettings/subsections/income_and_benefits.rb b/app/models/form/lettings/subsections/income_and_benefits.rb index 92adf3c5e..30ba3a7e0 100644 --- a/app/models/form/lettings/subsections/income_and_benefits.rb +++ b/app/models/form/lettings/subsections/income_and_benefits.rb @@ -19,6 +19,7 @@ class Form::Lettings::Subsections::IncomeAndBenefits < ::Form::Subsection Form::Lettings::Pages::CareHomeBiWeekly.new(nil, nil, self), Form::Lettings::Pages::CareHome4Weekly.new(nil, nil, self), Form::Lettings::Pages::CareHomeMonthly.new(nil, nil, self), + Form::Lettings::Pages::CareHomeChargesValueCheck.new(nil, nil, self), Form::Lettings::Pages::RentWeekly.new(nil, nil, self), Form::Lettings::Pages::RentBiWeekly.new(nil, nil, self), Form::Lettings::Pages::Rent4Weekly.new(nil, nil, self), diff --git a/app/models/form/lettings/subsections/property_information.rb b/app/models/form/lettings/subsections/property_information.rb index cc07535ae..c20c2b27c 100644 --- a/app/models/form/lettings/subsections/property_information.rb +++ b/app/models/form/lettings/subsections/property_information.rb @@ -8,7 +8,7 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection def pages @pages ||= [ - Form::Lettings::Pages::PropertyPostcode.new(nil, nil, self), + uprn_questions, Form::Lettings::Pages::PropertyLocalAuthority.new(nil, nil, self), Form::Lettings::Pages::FirstTimePropertyLetAsSocialHousing.new(nil, nil, self), Form::Lettings::Pages::PropertyLetType.new(nil, nil, self), @@ -25,6 +25,25 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection Form::Lettings::Pages::NewBuildHandoverDate.new(nil, nil, self), Form::Lettings::Pages::PropertyMajorRepairs.new(nil, nil, self), Form::Lettings::Pages::PropertyMajorRepairsValueCheck.new(nil, nil, self), - ].compact + ].flatten.compact + end + + def uprn_questions + if form.start_date.year >= 2023 + [ + Form::Lettings::Pages::UprnKnown.new(nil, nil, self), + Form::Lettings::Pages::Uprn.new(nil, nil, self), + Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self), + Form::Lettings::Pages::Address.new(nil, nil, self), + ] + else + [ + Form::Lettings::Pages::PropertyPostcode.new(nil, nil, self), + ] + end + end + + def displayed_in_tasklist?(log) + !(log.is_supported_housing? && log.is_renewal?) end end diff --git a/app/models/form/sales/pages/address.rb b/app/models/form/sales/pages/address.rb index aa8ab7e0d..ca686d1b1 100644 --- a/app/models/form/sales/pages/address.rb +++ b/app/models/form/sales/pages/address.rb @@ -2,7 +2,7 @@ class Form::Sales::Pages::Address < ::Form::Page def initialize(id, hsh, subsection) super @id = "address" - @header = "What is the property's address?" + @header = "Q15 - What is the property's address?" end def questions diff --git a/app/models/form/sales/pages/discounted_sale_value_check.rb b/app/models/form/sales/pages/discounted_sale_value_check.rb new file mode 100644 index 000000000..8ff48a0bd --- /dev/null +++ b/app/models/form/sales/pages/discounted_sale_value_check.rb @@ -0,0 +1,26 @@ +class Form::Sales::Pages::DiscountedSaleValueCheck < ::Form::Page + def initialize(id, hsh, subsection, person_index = nil) + super(id, hsh, subsection) + @depends_on = depends_on + @title_text = { + "translation" => "soft_validations.discounted_sale_value.title_text", + "arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }], + } + @informative_text = { + "translation" => "soft_validations.discounted_sale_value.informative_text", + "arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }], + } + @person_index = person_index + @depends_on = [ + { + "discounted_ownership_value_invalid?" => true, + }, + ] + end + + def questions + @questions ||= [ + Form::Sales::Questions::DiscountedSaleValueCheck.new(nil, nil, self), + ] + end +end diff --git a/app/models/form/sales/pages/mortgage_amount.rb b/app/models/form/sales/pages/mortgage_amount.rb index 793570b46..73e306c2a 100644 --- a/app/models/form/sales/pages/mortgage_amount.rb +++ b/app/models/form/sales/pages/mortgage_amount.rb @@ -3,9 +3,7 @@ class Form::Sales::Pages::MortgageAmount < ::Form::Page super(id, hsh, subsection) @ownershipsch = ownershipsch @header = "Mortgage Amount" - @depends_on = [{ - "mortgageused" => 1, - }] + @depends_on = [{ "mortgage_used?" => true }] end def questions diff --git a/app/models/form/sales/pages/number_of_others_in_property.rb b/app/models/form/sales/pages/number_of_others_in_property.rb index ebf9817bd..4c6b9e621 100644 --- a/app/models/form/sales/pages/number_of_others_in_property.rb +++ b/app/models/form/sales/pages/number_of_others_in_property.rb @@ -4,11 +4,11 @@ class Form::Sales::Pages::NumberOfOthersInProperty < ::Form::Page @depends_on = [ { "privacynotice" => 1, - "jointpur" => joint_purchase ? 1 : 2, + "joint_purchase?" => joint_purchase, }, { - "noint" => 1, - "jointpur" => joint_purchase ? 1 : 2, + "buyer_not_interviewed?" => true, + "joint_purchase?" => joint_purchase, }, ] @joint_purchase = joint_purchase diff --git a/app/models/form/sales/questions/address_line1.rb b/app/models/form/sales/questions/address_line1.rb index e8ccb17c0..a71229970 100644 --- a/app/models/form/sales/questions/address_line1.rb +++ b/app/models/form/sales/questions/address_line1.rb @@ -6,6 +6,7 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question @header = "Address line 1" @type = "text" @plain_label = true + @check_answer_label = "Q15 - Address" end def hidden_in_check_answers?(log, _current_user = nil) diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_black.rb b/app/models/form/sales/questions/buyer1_ethnic_background_black.rb index 16e341a5a..f12185a67 100644 --- a/app/models/form/sales/questions/buyer1_ethnic_background_black.rb +++ b/app/models/form/sales/questions/buyer1_ethnic_background_black.rb @@ -14,6 +14,6 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundBlack < ::Form::Question ANSWER_OPTIONS = { "13" => { "value" => "African" }, "12" => { "value" => "Caribbean" }, - "14" => { "value" => "Any other Black, African or Caribbean background" }, + "14" => { "value" => "Any other Black, African, Caribbean or Black British background" }, }.freeze end diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_black.rb b/app/models/form/sales/questions/buyer2_ethnic_background_black.rb index 8442e9431..09dd7cae7 100644 --- a/app/models/form/sales/questions/buyer2_ethnic_background_black.rb +++ b/app/models/form/sales/questions/buyer2_ethnic_background_black.rb @@ -13,6 +13,6 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundBlack < ::Form::Question ANSWER_OPTIONS = { "13" => { "value" => "African" }, "12" => { "value" => "Caribbean" }, - "14" => { "value" => "Any other Black, African or Caribbean background" }, + "14" => { "value" => "Any other Black, African, Caribbean or Black British background" }, }.freeze end diff --git a/app/models/form/sales/questions/discounted_sale_value_check.rb b/app/models/form/sales/questions/discounted_sale_value_check.rb new file mode 100644 index 000000000..1d86b2f32 --- /dev/null +++ b/app/models/form/sales/questions/discounted_sale_value_check.rb @@ -0,0 +1,23 @@ +class Form::Sales::Questions::DiscountedSaleValueCheck < ::Form::Question + def initialize(id, hsh, page) + super + @id = "discounted_sale_value_check" + @check_answer_label = "Discounted sale value confirmation" + @header = "Are you sure this is correct?" + @type = "interruption_screen" + @answer_options = { + "0" => { "value" => "Yes" }, + "1" => { "value" => "No" }, + } + @hidden_in_check_answers = { + "depends_on" => [ + { + "discounted_sale_value_check" => 0, + }, + { + "discounted_sale_value_check" => 1, + }, + ], + } + end +end diff --git a/app/models/form/sales/questions/mortgage_amount.rb b/app/models/form/sales/questions/mortgage_amount.rb index 12959709a..9b199b2aa 100644 --- a/app/models/form/sales/questions/mortgage_amount.rb +++ b/app/models/form/sales/questions/mortgage_amount.rb @@ -5,7 +5,7 @@ class Form::Sales::Questions::MortgageAmount < ::Form::Question @check_answer_label = "Mortgage amount" @header = "What is the mortgage amount?" @type = "numeric" - @min = 0 + @min = 1 @width = 5 @prefix = "£" @hint_text = "Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments. Numeric in pounds. Rounded to the nearest pound." diff --git a/app/models/form/sales/questions/mortgage_lender.rb b/app/models/form/sales/questions/mortgage_lender.rb index 1fee10b8b..ad584aab5 100644 --- a/app/models/form/sales/questions/mortgage_lender.rb +++ b/app/models/form/sales/questions/mortgage_lender.rb @@ -56,8 +56,55 @@ class Form::Sales::Questions::MortgageLender < ::Form::Question "38" => "West Bromwich Building Society", "39" => "Yorkshire Building Society", "40" => "Other", + "0" => "Don’t know", }.freeze + def displayed_answer_options(_log, _user = nil) + { + "" => "Select an option", + "1" => "Atom Bank", + "2" => "Barclays Bank PLC", + "3" => "Bath Building Society", + "4" => "Buckinghamshire Building Society", + "5" => "Cambridge Building Society", + "6" => "Coventry Building Society", + "7" => "Cumberland Building Society", + "8" => "Darlington Building Society", + "9" => "Dudley Building Society", + "10" => "Ecology Building Society", + "11" => "Halifax", + "12" => "Hanley Economic Building Society", + "13" => "Hinckley and Rugby Building Society", + "14" => "Holmesdale Building Society", + "15" => "Ipswich Building Society", + "16" => "Leeds Building Society", + "17" => "Lloyds Bank", + "18" => "Mansfield Building Society", + "19" => "Market Harborough Building Society", + "20" => "Melton Mowbray Building Society", + "21" => "Nationwide Building Society", + "22" => "Natwest", + "23" => "Nedbank Private Wealth", + "24" => "Newbury Building Society", + "25" => "OneSavings Bank", + "26" => "Parity Trust", + "27" => "Penrith Building Society", + "28" => "Pepper Homeloans", + "29" => "Royal Bank of Scotland", + "30" => "Santander", + "31" => "Skipton Building Society", + "32" => "Teachers Building Society", + "33" => "The Co-operative Bank", + "34" => "Tipton & Coseley Building Society", + "35" => "TSB", + "36" => "Ulster Bank", + "37" => "Virgin Money", + "38" => "West Bromwich Building Society", + "39" => "Yorkshire Building Society", + "40" => "Other", + } + end + def question_number case @ownershipsch when 1 diff --git a/app/models/form/sales/questions/number_of_others_in_property.rb b/app/models/form/sales/questions/number_of_others_in_property.rb index 44e7e5563..556ddf837 100644 --- a/app/models/form/sales/questions/number_of_others_in_property.rb +++ b/app/models/form/sales/questions/number_of_others_in_property.rb @@ -3,12 +3,12 @@ class Form::Sales::Questions::NumberOfOthersInProperty < ::Form::Question super(id, hsh, page) @id = "hholdcount" @check_answer_label = "Number of other people living in the property" - @header = "Besides the buyer(s), how many other people live or will live in the property?" + @header = "Besides the #{'buyer'.pluralize(joint_purchase ? 2 : 1)}, how many other people live or will live in the property?" @type = "numeric" @hint_text = hint(joint_purchase) @width = 2 @min = 0 - @max = joint_purchase ? 4 : 5 + @max = 15 @question_number = 35 end diff --git a/app/models/form/sales/questions/uprn.rb b/app/models/form/sales/questions/uprn.rb index 2c0b66dc8..7967a2035 100644 --- a/app/models/form/sales/questions/uprn.rb +++ b/app/models/form/sales/questions/uprn.rb @@ -7,6 +7,7 @@ class Form::Sales::Questions::Uprn < ::Form::Question @type = "text" @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355." @width = 10 + @question_number = 14 end def unanswered_error_message diff --git a/app/models/form/sales/questions/uprn_known.rb b/app/models/form/sales/questions/uprn_known.rb index 9f192f7de..b07b0b7d7 100644 --- a/app/models/form/sales/questions/uprn_known.rb +++ b/app/models/form/sales/questions/uprn_known.rb @@ -3,7 +3,7 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question super @id = "uprn_known" @check_answer_label = "UPRN known?" - @header = "Do you know the property UPRN?" + @header = "Do you know the property's UPRN?" @type = "radio" @answer_options = ANSWER_OPTIONS @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.

diff --git a/app/models/form/sales/subsections/discounted_ownership_scheme.rb b/app/models/form/sales/subsections/discounted_ownership_scheme.rb index f9292b6d6..cab732bc7 100644 --- a/app/models/form/sales/subsections/discounted_ownership_scheme.rb +++ b/app/models/form/sales/subsections/discounted_ownership_scheme.rb @@ -14,12 +14,15 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self), Form::Sales::Pages::GrantValueCheck.new(nil, nil, self), Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2), + Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_grant_value_check", nil, self), Form::Sales::Pages::AboutPriceValueCheck.new("about_price_discounted_ownership_value_check", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_used_mortgage_value_check", nil, self), + Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_used_value_check", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_amount_mortgage_value_check", nil, self), + Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_value_check", nil, self), Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_mortgage_value_check", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_mortgage", nil, self), Form::Sales::Pages::MortgageLender.new("mortgage_lender_discounted_ownership", nil, self, ownershipsch: 2), @@ -31,6 +34,7 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_deposit", nil, self), + Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_deposit_value_check", nil, self), Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_discounted_ownership_value_check", nil, self), ] diff --git a/app/models/form/sales/subsections/setup.rb b/app/models/form/sales/subsections/setup.rb index aa3c498fc..d1bb9dd6b 100644 --- a/app/models/form/sales/subsections/setup.rb +++ b/app/models/form/sales/subsections/setup.rb @@ -18,6 +18,7 @@ class Form::Sales::Subsections::Setup < ::Form::Subsection Form::Sales::Pages::OutrightOwnershipType.new(nil, nil, self), Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self), Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self), + Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_type_value_check", nil, self), Form::Sales::Pages::BuyerCompany.new(nil, nil, self), Form::Sales::Pages::BuyerLive.new(nil, nil, self), Form::Sales::Pages::JointPurchase.new(nil, nil, self), diff --git a/app/models/form/subsection.rb b/app/models/form/subsection.rb index 3f5827c92..f38ecc327 100644 --- a/app/models/form/subsection.rb +++ b/app/models/form/subsection.rb @@ -7,6 +7,7 @@ class Form::Subsection if hsh @label = hsh["label"] @depends_on = hsh["depends_on"] + @displayed_in_tasklist_from_json = hsh["displayed_in_tasklist"] @pages = hsh["pages"].map { |s_id, p| Form::Page.new(s_id, p, self) } end end @@ -48,7 +49,13 @@ class Form::Subsection end end - def displayed_in_tasklist?(_log) - true + def displayed_in_tasklist?(log) + return true unless @displayed_in_tasklist_from_json + + @displayed_in_tasklist_from_json.any? do |conditions| + conditions.all? do |method, expected_return_value| + log.send(method) == expected_return_value + end + end end end diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb index 12ae4473b..b2d9168b2 100644 --- a/app/models/form_handler.rb +++ b/app/models/form_handler.rb @@ -47,7 +47,7 @@ class FormHandler form = Form.new(form_path) form_to_set = form_name_from_start_year(form.start_date.year, "lettings") - forms[form_to_set] = form if forms[form_to_set].blank? + forms[form_to_set] = form if form_to_set && forms[form_to_set].blank? end end diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb index 4524ead12..f96c41c88 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -32,6 +32,7 @@ class LettingsLog < Log before_validation :reset_location_fields!, unless: :postcode_known? before_validation :reset_previous_location_fields!, unless: :previous_postcode_known? before_validation :set_derived_fields! + after_validation :process_uprn_change!, if: :should_process_uprn_change? belongs_to :scheme, optional: true belongs_to :location, optional: true @@ -53,7 +54,7 @@ class LettingsLog < Log scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org).or(where(managing_organisation: org)) } AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze - OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenancycode propcode].freeze + OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenancycode propcode chcharge].freeze RENT_TYPE_MAPPING_LABELS = { 1 => "Social Rent", 2 => "Affordable Rent", 3 => "Intermediate Rent" }.freeze HAS_BENEFITS_OPTIONS = [1, 6, 8, 7].freeze NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52 }.freeze @@ -287,6 +288,10 @@ class LettingsLog < Log [15, 16, 17].include?(rsnvac) end + def vacancy_reason_not_renewal_or_first_let? + [5, 6, 8, 9, 10, 11, 12, 13, 18, 19].include? rsnvac + end + def previous_tenancy_was_temporary? # 4: Tied housing or renting with job # 6: Supported housing @@ -501,6 +506,10 @@ class LettingsLog < Log update!(created_by: nil) end + def care_home_charge_expected_not_provided? + is_carehome == 1 && chcharge.blank? + end + private def reset_derived_questions @@ -671,4 +680,8 @@ private def unknown_housingneeds? housingneeds == 3 end + + def should_process_uprn_change? + uprn_changed? && startdate && startdate.year >= 2023 + end end diff --git a/app/models/location.rb b/app/models/location.rb index b96517e17..b463374df 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -23,6 +23,7 @@ class Location < ApplicationRecord scope :search_by, ->(param) { search_by_name(param).or(search_by_postcode(param)) } scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) } scope :active, -> { where(confirmed: true).and(started) } + scope :confirmed, -> { where(confirmed: true) } LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h diff --git a/app/models/log.rb b/app/models/log.rb index 34c920bd5..3ecc02754 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -45,6 +45,7 @@ class Log < ApplicationRecord self.address_line2 = presenter.address_line2 self.town_or_city = presenter.town_or_city self.postcode_full = presenter.postcode + self.county = nil process_postcode_changes! end end diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb index 7385d8b43..2a6e1a6d3 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -42,7 +42,7 @@ class SalesLog < Log } scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) } - OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check mortgagelender othtype].freeze + OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check].freeze RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze def lettings? @@ -243,6 +243,10 @@ class SalesLog < Log ownershipsch == 2 end + def mortgage_used? + mortgageused == 1 + end + def mortgage_not_used? mortgageused == 2 end @@ -330,4 +334,19 @@ class SalesLog < Log def should_process_uprn_change? uprn_changed? && saledate && saledate.year >= 2023 end + + def value_with_discount + return if value.blank? + + discount_amount = discount ? value * discount / 100 : 0 + value - discount_amount + end + + def mortgage_deposit_and_grant_total + return if deposit.blank? + + grant_amount = grant || 0 + mortgage_amount = mortgage || 0 + mortgage_amount + deposit + grant_amount + end end diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 364809955..740729749 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -235,7 +235,7 @@ class Scheme < ApplicationRecord end def status_at(date) - return :incomplete unless confirmed + return :incomplete unless confirmed && locations.confirmed.any? return :deactivated if open_deactivation&.deactivation_date.present? && date >= open_deactivation.deactivation_date return :deactivating_soon if open_deactivation&.deactivation_date.present? && date < open_deactivation.deactivation_date return :reactivating_soon if recent_deactivation&.reactivation_date.present? && date < recent_deactivation.reactivation_date diff --git a/app/models/validations/date_validations.rb b/app/models/validations/date_validations.rb index ee7789171..ae5d7ee19 100644 --- a/app/models/validations/date_validations.rb +++ b/app/models/validations/date_validations.rb @@ -33,17 +33,10 @@ module Validations::DateValidations def validate_startdate(record) return unless record.startdate && date_valid?("startdate", record) - if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14 + if FeatureToggle.startdate_two_week_validation_enabled? && record.startdate > Time.zone.today + 14.days record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after") end - if record.scheme_id.present? - scheme_end_date = record.scheme.end_date - if scheme_end_date.present? && record.startdate > scheme_end_date - record.errors.add :startdate, I18n.t("validations.setup.startdate.before_scheme_end_date") - end - end - if record["voiddate"].present? && record.startdate < record["voiddate"] record.errors.add :startdate, I18n.t("validations.setup.startdate.after_void_date") end diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb index 6179d05aa..fc1c44585 100644 --- a/app/models/validations/financial_validations.rb +++ b/app/models/validations/financial_validations.rb @@ -25,6 +25,7 @@ module Validations::FinancialValidations if record.ecstat1 && record.weekly_net_income if record.weekly_net_income > record.applicable_income_range.hard_max record.errors.add :earnings, :over_hard_max, message: I18n.t("validations.financial.earnings.over_hard_max", hard_max: record.applicable_income_range.hard_max) + record.errors.add :ecstat1, :over_hard_max, message: I18n.t("validations.financial.ecstat.over_hard_max", hard_max: record.applicable_income_range.hard_max) end if record.weekly_net_income < record.applicable_income_range.hard_min @@ -132,12 +133,12 @@ private CHARGE_MAXIMUMS = { scharge: { private_registered_provider: { - general_needs: 55, - supported_housing: 280, + general_needs: 155, + supported_housing: 480, }, local_authority: { - general_needs: 45, - supported_housing: 165, + general_needs: 155, + supported_housing: 365, }, }, pscharge: { @@ -187,7 +188,12 @@ private collection_year = record.collection_start_year - rent_range = LaRentRange.find_by(start_year: collection_year, la: record.la, beds: record.beds_for_la_rent_range, lettype: record.lettype) + rent_range = LaRentRange.find_by( + start_year: collection_year, + la: record.la, + beds: record.beds_for_la_rent_range, + lettype: record.lettype, + ) if rent_range.present? && !weekly_value_in_range(record, "brent", rent_range.hard_min, rent_range.hard_max) && record.brent.present? && record.period.present? if record.weekly_value(record["brent"]) < rent_range.hard_min @@ -200,7 +206,9 @@ private record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.below_hard_min") record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.below_hard_min") record.errors.add :period, I18n.t("validations.financial.brent.period.below_hard_min") - elsif record.beds.blank? || record.beds < LaRentRange::MAX_BEDS + end + + if record.weekly_value(record["brent"]) > rent_range.hard_max record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max") record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max") record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max") diff --git a/app/models/validations/household_validations.rb b/app/models/validations/household_validations.rb index afa7867ff..e56a16783 100644 --- a/app/models/validations/household_validations.rb +++ b/app/models/validations/household_validations.rb @@ -35,12 +35,6 @@ module Validations::HouseholdValidations end end - def validate_pregnancy(record) - if (record.has_pregnancy? || record.pregnancy_refused?) && women_in_household(record) && !women_of_child_bearing_age_in_household(record) - record.errors.add :preg_occ, I18n.t("validations.household.preg_occ.no_female") - end - end - def validate_household_number_of_other_members(record) (2..8).each do |n| validate_person_age_matches_economic_status(record, n) @@ -63,7 +57,7 @@ module Validations::HouseholdValidations def validate_previous_housing_situation(record) if record.is_relet_to_temp_tenant? && !record.previous_tenancy_was_temporary? - record.errors.add :prevten, I18n.t("validations.household.prevten.non_temp_accommodation") + record.errors.add :prevten, :non_temp_accommodation, message: I18n.t("validations.household.prevten.non_temp_accommodation") end if record.age1.present? && record.age1 > 19 && record.previous_tenancy_was_foster_care? diff --git a/app/models/validations/property_validations.rb b/app/models/validations/property_validations.rb index 2e53b8385..dafe6f6dd 100644 --- a/app/models/validations/property_validations.rb +++ b/app/models/validations/property_validations.rb @@ -16,7 +16,7 @@ module Validations::PropertyValidations end if record.offered.negative? || record.offered > 20 - record.errors.add :offered, I18n.t("validations.property.offered.relet_number") + record.errors.add :offered, :over_20, message: I18n.t("validations.property.offered.relet_number") end end diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb index faf436afa..8f81aa117 100644 --- a/app/models/validations/sales/financial_validations.rb +++ b/app/models/validations/sales/financial_validations.rb @@ -36,6 +36,10 @@ module Validations::Sales::FinancialValidations end end + def validate_mortgage(record) + record.errors.add :mortgage, I18n.t("validations.financial.mortgage") if record.mortgage_used? && record.mortgage&.zero? + end + def validate_cash_discount(record) return unless record.cashdis @@ -94,10 +98,10 @@ module Validations::Sales::FinancialValidations if record.equity < range.min record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min) - record.errors.add :equity, I18n.t("validations.financial.equity.under_min", min_equity: range.min) + record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min) elsif record.equity > range.max record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max) - record.errors.add :equity, I18n.t("validations.financial.equity.over_max", max_equity: range.max) + record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max) end end diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index ae3bbfe8f..fcd1854f4 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -1,4 +1,6 @@ module Validations::Sales::SaleInformationValidations + include CollectionTimeHelper + def validate_practical_completion_date_before_saledate(record) return if record.saledate.blank? || record.hodate.blank? @@ -45,17 +47,14 @@ module Validations::Sales::SaleInformationValidations end def validate_discounted_ownership_value(record) + return unless record.saledate && collection_start_year(record.saledate) >= 2024 return unless record.value && record.deposit && record.ownershipsch return unless record.mortgage || record.mortgageused == 2 return unless record.discount || record.grant || record.type == 29 - discount_amount = record.discount ? record.value * record.discount / 100 : 0 - grant_amount = record.grant || 0 - mortgage_amount = record.mortgage || 0 - value_with_discount = (record.value - discount_amount) - if mortgage_amount + record.deposit + grant_amount != value_with_discount && record.discounted_ownership_sale? + if record.mortgage_deposit_and_grant_total != record.value_with_discount && record.discounted_ownership_sale? %i[mortgage deposit grant value discount ownershipsch].each do |field| - record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", value_with_discount)) + record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", record.value_with_discount)) end end end diff --git a/app/models/validations/sales/setup_validations.rb b/app/models/validations/sales/setup_validations.rb index e76993907..1618ac3d9 100644 --- a/app/models/validations/sales/setup_validations.rb +++ b/app/models/validations/sales/setup_validations.rb @@ -2,7 +2,7 @@ module Validations::Sales::SetupValidations include Validations::SharedValidations include CollectionTimeHelper - def validate_saledate(record) + def validate_saledate_collection_year(record) return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_collection_window_validation_enabled? unless record.saledate.between?(active_collection_start_date, current_collection_end_date) @@ -10,6 +10,14 @@ module Validations::Sales::SetupValidations end end + def validate_saledate_two_weeks(record) + return unless record.saledate && date_valid?("saledate", record) && FeatureToggle.saledate_two_week_validation_enabled? + + if record.saledate > Time.zone.today + 14.days + record.errors.add :saledate, I18n.t("validations.setup.saledate.later_than_14_days_after") + end + end + private def active_collection_start_date diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb index 5819b0fe1..886716343 100644 --- a/app/models/validations/sales/soft_validations.rb +++ b/app/models/validations/sales/soft_validations.rb @@ -114,6 +114,15 @@ module Validations::Sales::SoftValidations end end + def discounted_ownership_value_invalid? + return unless saledate && collection_start_year <= 2023 + return unless value && deposit && ownershipsch + return unless mortgage || mortgageused == 2 + return unless discount || grant || type == 29 + + mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale? + end + private def sale_range diff --git a/app/models/validations/shared_validations.rb b/app/models/validations/shared_validations.rb index 32a8b22bd..e0f93515c 100644 --- a/app/models/validations/shared_validations.rb +++ b/app/models/validations/shared_validations.rb @@ -38,7 +38,7 @@ module Validations::SharedValidations postcode = record.postcode_full if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP)) error_message = I18n.t("validations.postcode") - record.errors.add :postcode_full, error_message + record.errors.add :postcode_full, :wrong_format, message: error_message end end diff --git a/app/models/validations/soft_validations.rb b/app/models/validations/soft_validations.rb index fc2c469ca..fbc5ab3b9 100644 --- a/app/models/validations/soft_validations.rb +++ b/app/models/validations/soft_validations.rb @@ -53,11 +53,11 @@ module Validations::SoftValidations end def no_females_in_a_pregnant_household? - !females_in_the_household? && all_tenants_age_and_gender_information_completed? && preg_occ == 1 + !females_in_the_household? && all_tenants_gender_information_completed? && preg_occ == 1 end def female_in_pregnant_household_in_soft_validation_range? - all_tenants_age_and_gender_information_completed? && (females_in_age_range(11, 15) || females_in_age_range(51, 65)) && !females_in_age_range(16, 50) && preg_occ == 1 + all_tenants_age_and_gender_information_completed? && females_in_the_household? && !females_in_age_range(16, 50) && preg_occ == 1 end def all_tenants_age_and_gender_information_completed? @@ -66,6 +66,12 @@ module Validations::SoftValidations end end + def all_tenants_gender_information_completed? + (1..hhmemb).all? do |n| + public_send("sex#{n}").present? && details_known_or_lead_tenant?(n) + end + end + TWO_YEARS_IN_DAYS = 730 TEN_YEARS_IN_DAYS = 3650 diff --git a/app/models/validations/tenancy_validations.rb b/app/models/validations/tenancy_validations.rb index e2ea108cf..5e1ec4a3c 100644 --- a/app/models/validations/tenancy_validations.rb +++ b/app/models/validations/tenancy_validations.rb @@ -43,7 +43,7 @@ module Validations::TenancyValidations return unless record.collection_start_year && record.joint if record.hhmemb == 1 && record.joint != 2 && record.collection_start_year >= 2022 - record.errors.add :joint, I18n.t("validations.tenancy.not_joint") + record.errors.add :joint, :not_joint_tenancy, message: I18n.t("validations.tenancy.not_joint") record.errors.add :hhmemb, I18n.t("validations.tenancy.joint_more_than_one_member") end end diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb index 11e65a402..d9e9027fd 100644 --- a/app/services/bulk_upload/lettings/year2022/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb @@ -282,13 +282,13 @@ class BulkUpload::Lettings::Year2022::RowParser validates :field_4, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_1) } } validates :field_12, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" } - validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" } - validates :field_14, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" } - validates :field_15, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" } - validates :field_16, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" } - validates :field_17, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" } - validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" } - validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" } + validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true + validates :field_14, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, allow_blank: true + validates :field_15, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, allow_blank: true + validates :field_16, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, allow_blank: true + validates :field_17, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, allow_blank: true + validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true + validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true validates :field_96, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") } validates :field_97, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") } @@ -308,14 +308,14 @@ class BulkUpload::Lettings::Year2022::RowParser validate :validate_dont_know_disabled_needs_conjunction validate :validate_no_and_dont_know_disabled_needs_conjunction - validate :validate_owning_org_permitted - validate :validate_owning_org_owns_stock - validate :validate_owning_org_exists validate :validate_owning_org_data_given + validate :validate_owning_org_exists + validate :validate_owning_org_owns_stock + validate :validate_owning_org_permitted - validate :validate_managing_org_related - validate :validate_managing_org_exists validate :validate_managing_org_data_given + validate :validate_managing_org_exists + validate :validate_managing_org_related validate :validate_scheme_related validate :validate_scheme_exists @@ -436,19 +436,26 @@ private def validate_managing_org_related if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) block_log_creation! - errors.add(:field_113, "This managing organisation does not have a relationship with the owning organisation") + + if errors[:field_113].blank? + errors.add(:field_113, "This managing organisation does not have a relationship with the owning organisation") + end end end def validate_managing_org_exists if managing_organisation.nil? - errors.delete(:field_113) - errors.add(:field_113, "The managing organisation code is incorrect") + block_log_creation! + + if errors[:field_113].blank? + errors.add(:field_113, "The managing organisation code is incorrect") + end end end def validate_managing_org_data_given if field_113.blank? + block_log_creation! errors.add(:field_113, "The managing organisation code is incorrect", category: :setup) end end @@ -456,29 +463,40 @@ private def validate_owning_org_owns_stock if owning_organisation && !owning_organisation.holds_own_stock? block_log_creation! - errors.delete(:field_111) - errors.add(:field_111, "The owning organisation code provided is for an organisation that does not own stock") + + if errors[:field_111].blank? + errors.add(:field_111, "The owning organisation code provided is for an organisation that does not own stock") + end end end def validate_owning_org_exists if owning_organisation.nil? - errors.delete(:field_111) - errors.add(:field_111, "The owning organisation code is incorrect") + block_log_creation! + + if errors[:field_111].blank? + errors.add(:field_111, "The owning organisation code is incorrect") + end end end def validate_owning_org_data_given if field_111.blank? - errors.add(:field_111, "The owning organisation code is incorrect", category: :setup) + block_log_creation! + + if errors[:field_111].blank? + errors.add(:field_111, "The owning organisation code is incorrect", category: :setup) + end end end def validate_owning_org_permitted if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation) block_log_creation! - errors.delete(:field_111) - errors.add(:field_111, "You do not have permission to add logs for this owning organisation") + + if errors[:field_111].blank? + errors.add(:field_111, "You do not have permission to add logs for this owning organisation") + end end end @@ -502,7 +520,7 @@ private end def validate_only_one_housing_needs_type - if [field_55, field_56, field_57].compact.count.positive? + if [field_55, field_56, field_57].compact.count > 1 errors.add(:field_55, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) errors.add(:field_56, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) errors.add(:field_57, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) @@ -848,28 +866,28 @@ private attributes["tenancylength"] = field_11 attributes["declaration"] = field_132 - attributes["age1_known"] = field_12 == "R" ? 1 : 0 + attributes["age1_known"] = age1_known? attributes["age1"] = field_12 if attributes["age1_known"].zero? && field_12&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age2_known"] = field_13 == "R" ? 1 : 0 + attributes["age2_known"] = age2_known? attributes["age2"] = field_13 if attributes["age2_known"].zero? && field_13&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age3_known"] = field_14 == "R" ? 1 : 0 + attributes["age3_known"] = age3_known? attributes["age3"] = field_14 if attributes["age3_known"].zero? && field_14&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age4_known"] = field_15 == "R" ? 1 : 0 + attributes["age4_known"] = age4_known? attributes["age4"] = field_15 if attributes["age4_known"].zero? && field_15&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age5_known"] = field_16 == "R" ? 1 : 0 + attributes["age5_known"] = age5_known? attributes["age5"] = field_16 if attributes["age5_known"].zero? && field_16&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age6_known"] = field_17 == "R" ? 1 : 0 + attributes["age6_known"] = age6_known? attributes["age6"] = field_17 if attributes["age6_known"].zero? && field_17&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age7_known"] = field_18 == "R" ? 1 : 0 + attributes["age7_known"] = age7_known? attributes["age7"] = field_18 if attributes["age7_known"].zero? && field_18&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age8_known"] = field_19 == "R" ? 1 : 0 + attributes["age8_known"] = age8_known? attributes["age8"] = field_19 if attributes["age8_known"].zero? && field_19&.match(/\A\d{1,3}\z|\AR\z/) attributes["sex1"] = field_20 @@ -902,13 +920,13 @@ private attributes["ecstat7"] = field_41 attributes["ecstat8"] = field_42 - attributes["details_known_2"] = details_known(2) - attributes["details_known_3"] = details_known(3) - attributes["details_known_4"] = details_known(4) - attributes["details_known_5"] = details_known(5) - attributes["details_known_6"] = details_known(6) - attributes["details_known_7"] = details_known(7) - attributes["details_known_8"] = details_known(8) + attributes["details_known_2"] = details_known?(2) + attributes["details_known_3"] = details_known?(3) + attributes["details_known_4"] = details_known?(4) + attributes["details_known_5"] = details_known?(5) + attributes["details_known_6"] = details_known?(6) + attributes["details_known_7"] = details_known?(7) + attributes["details_known_8"] = details_known?(8) attributes["armedforces"] = field_45 attributes["leftreg"] = leftreg @@ -1094,7 +1112,32 @@ private end end - def details_known(person_n) + def age1_known? + return 1 if field_12 == "R" + return 1 if field_12.blank? + + 0 + end + + [ + { person: 2, field: :field_13 }, + { person: 3, field: :field_14 }, + { person: 4, field: :field_15 }, + { person: 5, field: :field_16 }, + { person: 6, field: :field_17 }, + { person: 7, field: :field_18 }, + { person: 8, field: :field_19 }, + ].each do |hash| + define_method("age#{hash[:person]}_known?") do + return 1 if public_send(hash[:field]) == "R" + return 0 if send("person_#{hash[:person]}_present?") + return 1 if public_send(hash[:field]).blank? + + 0 + end + end + + def details_known?(person_n) send("person_#{person_n}_present?") ? 0 : 1 end @@ -1111,31 +1154,31 @@ private end def person_2_present? - field_13.present? && field_21.present? && field_28.present? + field_13.present? || field_21.present? || field_28.present? end def person_3_present? - field_14.present? && field_22.present? && field_29.present? + field_14.present? || field_22.present? || field_29.present? end def person_4_present? - field_15.present? && field_23.present? && field_30.present? + field_15.present? || field_23.present? || field_30.present? end def person_5_present? - field_16.present? && field_24.present? && field_31.present? + field_16.present? || field_24.present? || field_31.present? end def person_6_present? - field_17.present? && field_25.present? && field_32.present? + field_17.present? || field_25.present? || field_32.present? end def person_7_present? - field_18.present? && field_26.present? && field_33.present? + field_18.present? || field_26.present? || field_33.present? end def person_8_present? - field_19.present? && field_27.present? && field_34.present? + field_19.present? || field_27.present? || field_34.present? end def tshortfall_known diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index 17c5a88b5..61a4408c3 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -284,13 +284,13 @@ class BulkUpload::Lettings::Year2023::RowParser validates :field_16, presence: { if: proc { [2, 4, 6, 8, 10, 12].include?(field_5) } } validates :field_46, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" } - validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" } - validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" } - validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" } - validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" } - validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" } - validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" } - validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" } + validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true + validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, allow_blank: true + validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, allow_blank: true + validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, allow_blank: true + validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, allow_blank: true + validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true + validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true validates :field_7, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") } validates :field_8, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") } @@ -311,14 +311,14 @@ class BulkUpload::Lettings::Year2023::RowParser validate :validate_dont_know_disabled_needs_conjunction validate :validate_no_and_dont_know_disabled_needs_conjunction - validate :validate_owning_org_permitted - validate :validate_owning_org_owns_stock - validate :validate_owning_org_exists validate :validate_owning_org_data_given + validate :validate_owning_org_exists + validate :validate_owning_org_owns_stock + validate :validate_owning_org_permitted - validate :validate_managing_org_related - validate :validate_managing_org_exists validate :validate_managing_org_data_given + validate :validate_managing_org_exists + validate :validate_managing_org_related validate :validate_scheme_related validate :validate_scheme_exists @@ -419,7 +419,7 @@ private end def validate_only_one_housing_needs_type - if [field_83, field_84, field_85].compact.count.positive? + if [field_83, field_84, field_85].compact.count > 1 errors.add(:field_83, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) errors.add(:field_84, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) errors.add(:field_85, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) @@ -551,19 +551,26 @@ private def validate_managing_org_related if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) block_log_creation! - errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation") + + if errors[:field_2].blank? + errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation") + end end end def validate_managing_org_exists if managing_organisation.nil? - errors.delete(:field_2) - errors.add(:field_2, "The managing organisation code is incorrect") + block_log_creation! + + if errors[:field_2].blank? + errors.add(:field_2, "The managing organisation code is incorrect") + end end end def validate_managing_org_data_given if field_2.blank? + block_log_creation! errors.add(:field_2, "The managing organisation code is incorrect", category: :setup) end end @@ -571,20 +578,26 @@ private def validate_owning_org_owns_stock if owning_organisation && !owning_organisation.holds_own_stock? block_log_creation! - errors.delete(:field_1) - errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock") + + if errors[:field_1].blank? + errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock") + end end end def validate_owning_org_exists if owning_organisation.nil? - errors.delete(:field_1) - errors.add(:field_1, "The owning organisation code is incorrect") + block_log_creation! + + if errors[:field_1].blank? + errors.add(:field_1, "The owning organisation code is incorrect") + end end end def validate_owning_org_data_given if field_1.blank? + block_log_creation! errors.add(:field_1, "The owning organisation code is incorrect", category: :setup) end end @@ -592,8 +605,10 @@ private def validate_owning_org_permitted if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation) block_log_creation! - errors.delete(:field_1) - errors.add(:field_1, "You do not have permission to add logs for this owning organisation") + + if errors[:field_1].blank? + errors.add(:field_1, "You do not have permission to add logs for this owning organisation") + end end end @@ -751,6 +766,12 @@ private mrcdate: %i[field_36 field_37 field_38], voiddate: %i[field_33 field_34 field_35], + + uprn: [:field_18], + address_line1: [:field_19], + address_line2: [:field_20], + town_or_city: [:field_21], + county: [:field_22], } end @@ -790,28 +811,28 @@ private attributes["tenancylength"] = field_43 attributes["declaration"] = field_45 - attributes["age1_known"] = field_46 == "R" ? 1 : 0 + attributes["age1_known"] = age1_known? attributes["age1"] = field_46 if attributes["age1_known"].zero? && field_46&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age2_known"] = field_52 == "R" ? 1 : 0 + attributes["age2_known"] = age2_known? attributes["age2"] = field_52 if attributes["age2_known"].zero? && field_52&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age3_known"] = field_56 == "R" ? 1 : 0 + attributes["age3_known"] = age3_known? attributes["age3"] = field_56 if attributes["age3_known"].zero? && field_56&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age4_known"] = field_60 == "R" ? 1 : 0 + attributes["age4_known"] = age4_known? attributes["age4"] = field_60 if attributes["age4_known"].zero? && field_60&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age5_known"] = field_64 == "R" ? 1 : 0 + attributes["age5_known"] = age5_known? attributes["age5"] = field_64 if attributes["age5_known"].zero? && field_64&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age6_known"] = field_68 == "R" ? 1 : 0 + attributes["age6_known"] = age6_known? attributes["age6"] = field_68 if attributes["age6_known"].zero? && field_68&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age7_known"] = field_72 == "R" ? 1 : 0 + attributes["age7_known"] = age7_known? attributes["age7"] = field_72 if attributes["age7_known"].zero? && field_72&.match(/\A\d{1,3}\z|\AR\z/) - attributes["age8_known"] = field_76 == "R" ? 1 : 0 + attributes["age8_known"] = age8_known? attributes["age8"] = field_76 if attributes["age8_known"].zero? && field_76&.match(/\A\d{1,3}\z|\AR\z/) attributes["sex1"] = field_47 @@ -844,13 +865,13 @@ private attributes["ecstat7"] = field_74 attributes["ecstat8"] = field_78 - attributes["details_known_2"] = details_known(2) - attributes["details_known_3"] = details_known(3) - attributes["details_known_4"] = details_known(4) - attributes["details_known_5"] = details_known(5) - attributes["details_known_6"] = details_known(6) - attributes["details_known_7"] = details_known(7) - attributes["details_known_8"] = details_known(8) + attributes["details_known_2"] = details_known?(2) + attributes["details_known_3"] = details_known?(3) + attributes["details_known_4"] = details_known?(4) + attributes["details_known_5"] = details_known?(5) + attributes["details_known_6"] = details_known?(6) + attributes["details_known_7"] = details_known?(7) + attributes["details_known_8"] = details_known?(8) attributes["armedforces"] = field_79 attributes["leftreg"] = leftreg @@ -939,6 +960,13 @@ private attributes["first_time_property_let_as_social_housing"] = first_time_property_let_as_social_housing + attributes["uprn_known"] = field_18.present? ? 1 : 0 + attributes["uprn"] = field_18 + attributes["address_line1"] = field_19 + attributes["address_line2"] = field_20 + attributes["town_or_city"] = field_21 + attributes["county"] = field_22 + attributes end @@ -1055,36 +1083,61 @@ private end end - def details_known(person_n) + def age1_known? + return 1 if field_46 == "R" + return 1 if field_46.blank? + + 0 + end + + [ + { person: 2, field: :field_52 }, + { person: 3, field: :field_56 }, + { person: 4, field: :field_60 }, + { person: 5, field: :field_64 }, + { person: 6, field: :field_68 }, + { person: 7, field: :field_72 }, + { person: 8, field: :field_76 }, + ].each do |hash| + define_method("age#{hash[:person]}_known?") do + return 1 if public_send(hash[:field]) == "R" + return 0 if send("person_#{hash[:person]}_present?") + return 1 if public_send(hash[:field]).blank? + + 0 + end + end + + def details_known?(person_n) send("person_#{person_n}_present?") ? 0 : 1 end def person_2_present? - field_51.present? && field_52.present? && field_53.present? + field_51.present? || field_52.present? || field_53.present? end def person_3_present? - field_55.present? && field_56.present? && field_57.present? + field_55.present? || field_56.present? || field_57.present? end def person_4_present? - field_59.present? && field_60.present? && field_61.present? + field_59.present? || field_60.present? || field_61.present? end def person_5_present? - field_63.present? && field_64.present? && field_65.present? + field_63.present? || field_64.present? || field_65.present? end def person_6_present? - field_67.present? && field_68.present? && field_69.present? + field_67.present? || field_68.present? || field_69.present? end def person_7_present? - field_71.present? && field_72.present? && field_73.present? + field_71.present? || field_72.present? || field_73.present? end def person_8_present? - field_75.present? && field_76.present? && field_77.present? + field_75.present? || field_76.present? || field_77.present? end def leftreg diff --git a/app/services/imports/lettings_logs_import_service.rb b/app/services/imports/lettings_logs_import_service.rb index 34582091d..ecd32c51d 100644 --- a/app/services/imports/lettings_logs_import_service.rb +++ b/app/services/imports/lettings_logs_import_service.rb @@ -235,6 +235,7 @@ module Imports attributes["retirement_value_check"] = 0 attributes["rent_value_check"] = 0 attributes["net_income_value_check"] = 0 + attributes["carehome_charges_value_check"] = 0 # Sets the log creator owner_id = meta_field_value(xml_doc, "owner-user-id").strip @@ -310,6 +311,27 @@ module Imports attributes.delete("prevten") attributes.delete("age1") save_lettings_log(attributes, previous_status) + elsif lettings_log.errors.of_kind?(:prevten, :non_temp_accommodation) + @logger.warn("Log #{lettings_log.old_id}: Removing vacancy reason and previous tenancy since this accommodation is not temporary") + @logs_overridden << lettings_log.old_id + attributes.delete("prevten") + attributes.delete("rsnvac") + save_lettings_log(attributes, previous_status) + elsif lettings_log.errors.of_kind?(:joint, :not_joint_tenancy) + @logger.warn("Log #{lettings_log.old_id}: Removing joint tenancy as there is only 1 person in the household") + @logs_overridden << lettings_log.old_id + attributes.delete("joint") + save_lettings_log(attributes, previous_status) + elsif lettings_log.errors.of_kind?(:offered, :over_20) + @logger.warn("Log #{lettings_log.old_id}: Removing offered as the value is above the maximum of 20") + @logs_overridden << lettings_log.old_id + attributes.delete("offered") + save_lettings_log(attributes, previous_status) + elsif lettings_log.errors.of_kind?(:earnings, :over_hard_max) + @logger.warn("Log #{lettings_log.old_id}: Removing working situation because income is too high for it") + @logs_overridden << lettings_log.old_id + attributes.delete("ecstat1") + save_lettings_log(attributes, previous_status) else @logger.error("Log #{lettings_log.old_id}: Failed to import") lettings_log.errors.each do |error| @@ -339,7 +361,7 @@ module Imports end def fields_not_present_in_softwire_data - %w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other created_by] + %w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check carehome_charges_value_check housingneeds_type housingneeds_other created_by] end def check_status_completed(lettings_log, previous_status) diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index d7a3c8534..e6f735b3e 100644 --- a/app/services/imports/sales_logs_import_service.rb +++ b/app/services/imports/sales_logs_import_service.rb @@ -38,7 +38,7 @@ module Imports attributes["ownershipsch"] = ownership_from_type(attributes) if attributes["ownershipsch"].blank? # sometimes Ownership is missing, but type is set attributes["othtype"] = string_or_nil(xml_doc, "Q38OtherSale") attributes["jointpur"] = unsafe_string_as_integer(xml_doc, "joint") - attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore") if attributes["jointpur"] == 1 + attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore") || 3 if attributes["jointpur"] == 1 attributes["beds"] = safe_string_as_integer(xml_doc, "Q11Bedrooms") attributes["companybuy"] = unsafe_string_as_integer(xml_doc, "company") if attributes["ownershipsch"] == 3 attributes["hholdcount"] = other_household_members(xml_doc, attributes) @@ -153,6 +153,7 @@ module Imports attributes["income2_value_check"] = 0 attributes["monthly_charges_value_check"] = 0 attributes["student_not_child_value_check"] = 0 + attributes["discounted_sale_value_check"] = 0 # Sets the log creator owner_id = meta_field_value(xml_doc, "owner-user-id").strip @@ -188,8 +189,12 @@ module Imports def rescue_validation_or_raise(sales_log, attributes, previous_status, exception) if %w[saved submitted-invalid].include?(previous_status) sales_log.errors.each do |error| - @logger.warn("Log #{sales_log.old_id}: Removing field #{error.attribute} from log triggering validation: #{error.type}") - attributes.delete(error.attribute.to_s) + unless error.attribute == :type || error.attribute == :ownershipsch + @logger.warn("Log #{sales_log.old_id}: Removing field #{error.attribute} from log triggering validation: #{error.type}") + attributes.delete(error.attribute.to_s) + end + attributes.delete("pcodenk") if error.attribute == :postcode_full + attributes.delete("ppcodenk") if error.attribute == :ppostcode_full end @logs_overridden << sales_log.old_id save_sales_log(attributes, previous_status) @@ -209,6 +214,17 @@ module Imports @logs_overridden << sales_log.old_id attributes.delete("income1") save_sales_log(attributes, previous_status) + elsif sales_log.errors.of_kind?(:equity, :over_max) || sales_log.errors.of_kind?(:equity, :under_min) + @logger.warn("Log #{sales_log.old_id}: Removing equity as the equity is invalid") + @logs_overridden << sales_log.old_id + attributes.delete("equity") + save_sales_log(attributes, previous_status) + elsif sales_log.errors.of_kind?(:postcode_full, :wrong_format) + @logger.warn("Log #{sales_log.old_id}: Removing postcode as the postcode is invalid") + @logs_overridden << sales_log.old_id + attributes.delete("postcode_full") + attributes["pcodenk"] = attributes["la"].present? ? 1 : nil + save_sales_log(attributes, previous_status) else @logger.error("Log #{sales_log.old_id}: Failed to import") sales_log.errors.each do |error| @@ -255,7 +271,8 @@ module Imports monthly_charges_value_check hodate_check saledate_check - student_not_child_value_check] + student_not_child_value_check + discounted_sale_value_check] end def check_status_completed(sales_log, previous_status) @@ -500,12 +517,12 @@ module Imports def set_default_values(attributes) attributes["armedforcesspouse"] ||= 7 attributes["hhregres"] ||= 8 + attributes["hhregresstill"] ||= 7 if attributes["hhregres"] == 1 attributes["disabled"] ||= 3 attributes["wheel"] ||= 3 attributes["hb"] ||= 4 attributes["prevown"] ||= 3 attributes["savingsnk"] ||= attributes["savings"].present? ? 0 : 1 - attributes["jointmore"] ||= 3 if attributes["jointpur"] == 1 attributes["inc1mort"] ||= 3 if [attributes["pregyrha"], attributes["pregla"], attributes["pregghb"], attributes["pregother"]].all?(&:blank?) attributes["pregblank"] = 1 @@ -515,6 +532,7 @@ module Imports attributes["extrabor"] ||= 3 if attributes["mortgageused"] == 1 attributes["socprevten"] ||= 10 if attributes["ownershipsch"] == 1 attributes["fromprop"] ||= 0 if attributes["ownershipsch"] == 1 + attributes["mortgagelender"] ||= 0 if attributes["mortgageused"] == 1 # buyer 1 characteristics attributes["age1_known"] ||= 1 @@ -537,7 +555,7 @@ module Imports end # other household members characteristics - (2..attributes["hhmemb"]).each do |index| + (2..[attributes["hhmemb"], 6].min).each do |index| attributes["age#{index}_known"] ||= 1 attributes["sex#{index}"] ||= "R" attributes["ecstat#{index}"] ||= 10 diff --git a/app/services/imports/scheme_location_import_service.rb b/app/services/imports/scheme_location_import_service.rb index ab5faad27..a26139aec 100644 --- a/app/services/imports/scheme_location_import_service.rb +++ b/app/services/imports/scheme_location_import_service.rb @@ -35,7 +35,6 @@ module Imports primary_client_group: attributes["primary_client_group"], secondary_client_group: attributes["secondary_client_group"], sensitive: attributes["sensitive"], - end_date: attributes["end_date"], # These values were set by the scheme import (management groups) owning_organisation_id: source_scheme.owning_organisation_id, service_name: source_scheme.service_name, @@ -43,7 +42,7 @@ module Imports old_id: source_scheme.old_id, old_visible_id: source_scheme.old_visible_id, ) - confirm_scheme(scheme) + confirm_scheme_or_location(scheme) scheme.save! && scheme rescue ActiveRecord::RecordInvalid @logger.error("Scheme #{source_scheme.old_visible_id}: Failed to import") @@ -59,18 +58,17 @@ module Imports primary_client_group: attributes["primary_client_group"], secondary_client_group: attributes["secondary_client_group"], sensitive: attributes["sensitive"], - end_date: attributes["end_date"], } - confirm_scheme(scheme) + confirm_scheme_or_location(scheme) scheme.save! && scheme end - def confirm_scheme(scheme) - scheme.confirmed = true - scheme.validate_confirmed - unless scheme.errors.empty? - scheme.confirmed = false - scheme.errors.clear + def confirm_scheme_or_location(obj) + obj.confirmed = true + obj.validate_confirmed + unless obj.errors.empty? + obj.confirmed = false + obj.errors.clear end end @@ -99,7 +97,7 @@ module Imports end def add_location(scheme, attributes) - Location.create!( + location = Location.create!( name: attributes["location_name"], postcode: attributes["postcode"], mobility_type: attributes["mobility_type"], @@ -110,6 +108,10 @@ module Imports startdate: attributes["start_date"], scheme:, ) + if attributes["end_date"] + location.location_deactivation_periods.create!(deactivation_date: attributes["end_date"]) + end + location rescue ActiveRecord::RecordNotUnique @logger.warn("Location is already present with legacy ID #{attributes['location_old_id']}, skipping") rescue ActiveRecord::RecordInvalid diff --git a/app/views/form/_check_answers_summary_list.html.erb b/app/views/form/_check_answers_summary_list.html.erb index 71fe9cd97..653cd610d 100644 --- a/app/views/form/_check_answers_summary_list.html.erb +++ b/app/views/form/_check_answers_summary_list.html.erb @@ -9,7 +9,7 @@ class: "govuk-!-margin-right-4", ) %> <% extra_value = question.get_extra_check_answer_value(@log) %> - <% if extra_value && question.answer_label(lettings_log, current_user).present? %> + <% if extra_value && question.answer_label(@log, current_user).present? %> <%= simple_format( extra_value, wrapper_tag: "span", diff --git a/app/views/form/check_answers.html.erb b/app/views/form/check_answers.html.erb index 46a945017..3da071be5 100644 --- a/app/views/form/check_answers.html.erb +++ b/app/views/form/check_answers.html.erb @@ -1,9 +1,9 @@ <% content_for :title, "#{subsection.id.humanize} - Check your answers" %> <% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: { - "Logs" => "/logs", - "Log #{@log.id}" => send("#{@log.class.name.underscore}_path", @log), + "Logs" => url_for(@log.class), + "Log #{@log.id}" => url_for(@log), subsection.label => "", - }) %> +}) %>
diff --git a/app/views/form/review.html.erb b/app/views/form/review.html.erb index bc46c89d8..0e63875d9 100644 --- a/app/views/form/review.html.erb +++ b/app/views/form/review.html.erb @@ -1,18 +1,10 @@ -<% if @log.sales? %> - <% content_for :title, "Review sales log" %> - <% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: { - "Logs" => "/logs", - "Log #{@log.id}" => "/sales-logs/#{@log.id}", - "Review sales log" => "", - }) %> -<% else %> - <% content_for :title, "Review lettings log" %> - <% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: { - "Logs" => "/logs", - "Log #{@log.id}" => "/lettings-logs/#{@log.id}", - "Review lettings log" => "", - }) %> -<% end %> +<% class_name = @log.class.model_name.human.downcase %> +<% content_for :title, "Review #{class_name}" %> +<% content_for :breadcrumbs, govuk_breadcrumbs(breadcrumbs: { + "Logs" => url_for(@log.class), + "Log #{@log.id}" => url_for(@log), + "Review #{class_name}" => "", +}) %>
diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index 49931ee05..dfcf83fb6 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -1639,7 +1639,7 @@ "value": "Caribbean" }, "14": { - "value": "Any other Black, African or Caribbean background" + "value": "Any other Black, African, Caribbean or Black British background" } } } @@ -7812,6 +7812,42 @@ } ] }, + "care_home_charges_value_check": { + "depends_on": [ + { + "care_home_charge_expected_not_provided?": true + } + ], + "title_text": { + "translation": "soft_validations.care_home_charges.title_text" + }, + "informative_text": {}, + "questions": { + "carehome_charges_value_check": { + "check_answer_label": "Care home charges confirmation", + "hidden_in_check_answers": { + "depends_on": [ + { + "carehome_charges_value_check": 0 + }, + { + "carehome_charges_value_check": 1 + } + ] + }, + "header": "Are you sure there are no care home charges?", + "type": "interruption_screen", + "answer_options": { + "0": { + "value": "Yes" + }, + "1": { + "value": "No" + } + } + } + } + }, "rent_weekly": { "header": "Household rent and charges", "description": "", diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index eeed6c3c7..3162a2b36 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -1,7 +1,7 @@ { "form_type": "lettings", "start_date": "2022-04-01T00:00:00.000+01:00", - "end_date": "2023-07-09T00:00:00.000+01:00", + "end_date": "2023-06-09T00:00:00.000+01:00", "unresolved_log_redirect_page_id": "tenancy_start_date", "sections": { "tenancy_and_property": { @@ -939,7 +939,15 @@ } } } - } + }, + "displayed_in_tasklist": [ + { + "is_supported_housing?": false + }, + { + "is_renewal?": false + } + ] }, "tenancy_information": { "label": "Tenancy information", @@ -1671,7 +1679,7 @@ "value": "Caribbean" }, "14": { - "value": "Any other Black, African or Caribbean background" + "value": "Any other Black, African, Caribbean or Black British background" } } } @@ -7774,6 +7782,42 @@ } ] }, + "care_home_charges_value_check": { + "depends_on": [ + { + "care_home_charge_expected_not_provided?": true + } + ], + "title_text": { + "translation": "soft_validations.care_home_charges.title_text" + }, + "informative_text": {}, + "questions": { + "carehome_charges_value_check": { + "check_answer_label": "Care home charges confirmation", + "hidden_in_check_answers": { + "depends_on": [ + { + "carehome_charges_value_check": 0 + }, + { + "carehome_charges_value_check": 1 + } + ] + }, + "header": "Are you sure there are no care home charges?", + "type": "interruption_screen", + "answer_options": { + "0": { + "value": "Yes" + }, + "1": { + "value": "No" + } + } + } + } + }, "rent_weekly": { "header": "Household rent and charges", "description": "", diff --git a/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb index e00a7190b..de1c11fbd 100644 --- a/config/initializers/feature_toggle.rb +++ b/config/initializers/feature_toggle.rb @@ -5,13 +5,17 @@ class FeatureToggle end def self.startdate_collection_window_validation_enabled? - Rails.env.production? || Rails.env.test? || Rails.env.staging? + Rails.env.production? || Rails.env.test? end def self.startdate_two_week_validation_enabled? Rails.env.production? || Rails.env.test? || Rails.env.staging? end + def self.saledate_two_week_validation_enabled? + Rails.env.production? || Rails.env.test? || Rails.env.staging? || Rails.env.review? + end + def self.sales_log_enabled? true end diff --git a/config/locales/en.yml b/config/locales/en.yml index 8c9cd12c1..7e514b17f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -155,6 +155,7 @@ en: intermediate_rent_product_name: blank: "Enter name of other intermediate rent product" saledate: + later_than_14_days_after: "Sale completion date must not be later than 14 days from today’s date" current_collection_year: Enter a date within the %{current_start_year_short}/%{current_end_year_short} collection year, which is between %{current_start_year_long} and %{current_end_year_long} previous_and_current_collection_year: @@ -253,11 +254,11 @@ en: less_than_shortfall: "Enter an amount that is more than the shortfall in basic rent" scharge: private_registered_provider: - general_needs: "Enter a value for the service charge between £0 and £55 per week if the landlord is a private registered provider and it is a general needs letting" - supported_housing: "Enter a value for the service charge between £0 and £280 per week if the landlord is a private registered provider and it is a supported housing letting" + general_needs: "Enter a value for the service charge between £0 and £155 per week if the landlord is a private registered provider and it is a general needs letting" + supported_housing: "Enter a value for the service charge between £0 and £480 per week if the landlord is a private registered provider and it is a supported housing letting" local_authority: - general_needs: "Enter a value for the service charge between £0 and £45 per week if the landlord is a local authority and it is a general needs letting" - supported_housing: "Enter a value for the service charge between £0 and £165 per week if the landlord is a local authority and it is a supported housing letting" + general_needs: "Enter a value for the service charge between £0 and £155 per week if the landlord is a local authority and it is a general needs letting" + supported_housing: "Enter a value for the service charge between £0 and £365 per week if the landlord is a local authority and it is a supported housing letting" pscharge: private_registered_provider: general_needs: "Enter a value for the personal service charge between £0 and £30 per week if the landlord is a private registered provider and it is a general needs letting" @@ -272,6 +273,8 @@ en: local_authority: general_needs: "Enter a value for the support charge between £0 and £60 per week if the landlord is a local authority and it is a general needs letting" supported_housing: "Enter a value for the support charge between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting" + ecstat: + over_hard_max: "Net income of £%{hard_max} per week is too high for given the tenant’s working situation" brent: below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms" above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms" @@ -316,6 +319,7 @@ en: equity: under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%" over_max: "The maximum initial equity stake is %{max_equity}%" + mortgage: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property" household: reasonpref: @@ -331,8 +335,6 @@ en: leftreg: question_required: "Tell us whether the person is still serving in the UK armed forces as you told us they’re a current or former regular" question_not_required: "You cannot answer whether the person is still serving in the UK armed forces as you told us they’re not a current or former regular" - preg_occ: - no_female: "Enter ‘no’ as there are no female tenants aged 11-65 in the household" age: retired_male: "A male tenant who is retired must be 65 or over" retired_female: "A female tenant who is retired must be 60 or over" @@ -467,16 +469,16 @@ en: social_homebuy: "Social HomeBuy buyers should not have lived here before" rent_to_buy: "Rent to Buy buyers should not have lived here before" hodate: - must_be_before_saledate: "Practical completion or handover date must be before exchange date" - must_be_less_than_3_years_from_saledate: "You told us practical completion or handover date is more than 3 years before completion date" + must_be_before_saledate: "Practical completion or handover date must be before sale completion date" + must_be_less_than_3_years_from_saledate: "You told us practical completion or handover date is more than 3 years before sale completion date" exdate: - must_be_before_saledate: "Contract exchange date must be before completion date" - must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before completion date" + must_be_before_saledate: "Contract exchange date must be before sale completion date" + must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before sale completion date" saledate: - must_be_after_exdate: "Completion date must be after contract exchange date" - must_be_less_than_1_year_from_exdate: "Completion date must be less than 1 year after contract exchange date" - must_be_less_than_3_years_from_hodate: "You told us completion date is more than 3 years after practical completion or handover date" - must_be_after_hodate: "Completion date must be after practical completion or handover date" + must_be_after_exdate: "Sale completion date must be after contract exchange date" + must_be_less_than_1_year_from_exdate: "Sale completion date must be less than 1 year after contract exchange date" + must_be_less_than_3_years_from_hodate: "You told us sale completion date is more than 3 years after practical completion or handover date" + must_be_after_hodate: "Sale completion date must be after practical completion or handover date" previous_property_type: property_type_bedsit: "A bedsit cannot have more than 1 bedroom" discounted_ownership_value: "Mortgage, deposit, and grant total must equal £%{value_with_discount}" @@ -512,7 +514,7 @@ en: pregnancy: title: "You told us somebody in the household is pregnant" no_females: "You also told us there are no female tenants living at the property." - females_not_in_soft_age_range: "You also told us that any female tenants living at the property are in the following age ranges:
  • 11 to 16
  • 50 to 65
" + 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" void_date: @@ -525,6 +527,11 @@ en: title_text: "The amount of monthly charges is high for this type of property and sale type" student_not_child: title_text: "You told us this person is a student aged beween 16 and 19" + discounted_sale_value: + title_text: "Mortgage, deposit, and grant total must equal £%{value_with_discount}" + informative_text: "Your given mortgage, deposit and grant total is £%{mortgage_deposit_and_grant_total}" + care_home_charges: + title_text: "Care home charges should be provided if this is a care home accommodation" devise: two_factor_authentication: diff --git a/db/migrate/20230313124749_add_carehome_charges_value_check.rb b/db/migrate/20230313124749_add_carehome_charges_value_check.rb new file mode 100644 index 000000000..5ba9e64ea --- /dev/null +++ b/db/migrate/20230313124749_add_carehome_charges_value_check.rb @@ -0,0 +1,5 @@ +class AddCarehomeChargesValueCheck < ActiveRecord::Migration[7.0] + def change + add_column :lettings_logs, :carehome_charges_value_check, :integer + end +end diff --git a/db/migrate/20230316162737_add_discounted_sale_value_check.rb b/db/migrate/20230316162737_add_discounted_sale_value_check.rb new file mode 100644 index 000000000..fa6fdb0ce --- /dev/null +++ b/db/migrate/20230316162737_add_discounted_sale_value_check.rb @@ -0,0 +1,5 @@ +class AddDiscountedSaleValueCheck < ActiveRecord::Migration[7.0] + def change + add_column :sales_logs, :discounted_sale_value_check, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 0de1c29a0..fce5a4db6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -286,6 +286,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do t.string "address_line2" t.string "town_or_city" t.string "county" + t.integer "carehome_charges_value_check" t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id" t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id" t.index ["location_id"], name: "index_lettings_logs_on_location_id" @@ -568,6 +569,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do t.string "address_line2" t.string "town_or_city" t.string "county" + t.integer "nationalbuy2" + t.integer "discounted_sale_value_check" t.integer "student_not_child_value_check" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" diff --git a/spec/components/bulk_upload_error_summary_table_component_spec.rb b/spec/components/bulk_upload_error_summary_table_component_spec.rb index 4c307515c..32da38119 100644 --- a/spec/components/bulk_upload_error_summary_table_component_spec.rb +++ b/spec/components/bulk_upload_error_summary_table_component_spec.rb @@ -9,87 +9,114 @@ RSpec.describe BulkUploadErrorSummaryTableComponent, type: :component do stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 0) end - context "when no errors" do - it "does not renders any tables" do - result = render_inline(component) - expect(result).not_to have_selector("table") + describe "#sorted_errors" do + context "when no errors" do + it "does not renders any tables" do + result = render_inline(component) + expect(result).not_to have_selector("table") + end end - end - context "when below threshold" do - before do - stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 16) + context "when below threshold" do + before do + stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 16) - create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) - end + create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) + end - it "does not render tables" do - result = render_inline(component) - expect(result).to have_selector("table", count: 0) + it "does not render tables" do + result = render_inline(component) + expect(result).to have_selector("table", count: 0) + end end - end - context "when there are 2 independent errors" do - let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) } - let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) } + context "when there are 2 independent errors" do + let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) } + let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) } - it "renders table for each error" do - result = render_inline(component) - expect(result).to have_selector("table", count: 2) - end + it "renders table for each error" do + result = render_inline(component) + expect(result).to have_selector("table", count: 2) + end - it "renders by col order" do - result = render_inline(component) - order = result.css("table thead th:nth-of-type(2)").map(&:content) - expect(order).to eql(["Column A", "Column B"]) - end + it "renders by col order" do + result = render_inline(component) + order = result.css("table thead th:nth-of-type(2)").map(&:content) + expect(order).to eql(["Column A", "Column B"]) + end - it "render correct data" do - result = render_inline(component) + it "render correct data" do + result = render_inline(component) - table_1 = result.css("table").first.css("th, td").map(&:content) + table_1 = result.css("table").first.css("th, td").map(&:content) - expect(table_1).to eql([ - bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s, - "Column A", - error_1.error, - "1 error", - ]) + expect(table_1).to eql([ + bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s, + "Column A", + error_1.error, + "1 error", + ]) - table_2 = result.css("table")[1].css("th, td").map(&:content) + table_2 = result.css("table")[1].css("th, td").map(&:content) - expect(table_2).to eql([ - bulk_upload.prefix_namespace::RowParser.question_for_field(error_2.field.to_sym).to_s, - "Column B", - error_2.error, - "1 error", - ]) + expect(table_2).to eql([ + bulk_upload.prefix_namespace::RowParser.question_for_field(error_2.field.to_sym).to_s, + "Column B", + error_2.error, + "1 error", + ]) + end end - end - context "when there are 2 grouped errors" do - let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, field: "field_1") } + context "when there are 2 grouped errors" do + let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, field: "field_1") } - before do - create(:bulk_upload_error, bulk_upload:, col: "A", row: 2, field: "field_1") - end + before do + create(:bulk_upload_error, bulk_upload:, col: "A", row: 2, field: "field_1") + end + + it "renders 1 table combining the errors" do + result = render_inline(component) + expect(result).to have_selector("table", count: 1) + end - it "renders 1 table combining the errors" do - result = render_inline(component) - expect(result).to have_selector("table", count: 1) + it "render correct data" do + result = render_inline(component) + + table_1 = result.css("table").css("th, td").map(&:content) + + expect(table_1).to eql([ + bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s, + "Column A", + error_1.error, + "2 errors", + ]) + end end - it "render correct data" do - result = render_inline(component) + context "when mix of setup and other errors" do + let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1, category: "setup") } - table_1 = result.css("table").css("th, td").map(&:content) + before do + create(:bulk_upload_error, bulk_upload:, col: "B", row: 2, category: nil) + end + + it "only returns the setup errors" do + result = render_inline(component) + + tables = result.css("table") - expect(table_1).to eql([ - bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s, - "Column A", - error_1.error, - "2 errors", - ]) + expect(tables.size).to be(1) + + table = result.css("table").css("th, td").map(&:content) + + expect(table).to eql([ + bulk_upload.prefix_namespace::RowParser.question_for_field(error_1.field.to_sym).to_s, + "Column A", + error_1.error, + "1 error", + ]) + end end end diff --git a/spec/factories/lettings_log.rb b/spec/factories/lettings_log.rb index b0667b817..994b69c33 100644 --- a/spec/factories/lettings_log.rb +++ b/spec/factories/lettings_log.rb @@ -30,7 +30,7 @@ FactoryBot.define do age1 { 34 } sex1 { "M" } ethnic { 2 } - national { 4 } + national { 18 } ecstat1 { 2 } hhmemb { 1 } end @@ -43,7 +43,7 @@ FactoryBot.define do sex1 { "F" } ethnic_group { 0 } ethnic { 2 } - national { 4 } + national { 13 } prevten { 6 } ecstat1 { 0 } hhmemb { 2 } @@ -79,7 +79,7 @@ FactoryBot.define do supcharg { 35 } tcharge { 325 } layear { 2 } - waityear { 1 } + waityear { 7 } postcode_known { 1 } postcode_full { Faker::Address.postcode } reasonpref { 1 } diff --git a/spec/features/form/page_routing_spec.rb b/spec/features/form/page_routing_spec.rb index 312e0752b..0ba8ece6e 100644 --- a/spec/features/form/page_routing_spec.rb +++ b/spec/features/form/page_routing_spec.rb @@ -16,7 +16,6 @@ RSpec.describe "Form Page Routing" do before do allow(lettings_log.form).to receive(:end_date).and_return(Time.zone.today + 1.day) - allow(validator).to receive(:validate_pregnancy).and_return(true) sign_in user end diff --git a/spec/features/lettings_log_spec.rb b/spec/features/lettings_log_spec.rb index 483924f0f..b8ff6885a 100644 --- a/spec/features/lettings_log_spec.rb +++ b/spec/features/lettings_log_spec.rb @@ -94,6 +94,32 @@ RSpec.describe "Lettings Log Features" do end end + context "when visiting a subsection check answers page" do + let(:lettings_log) { FactoryBot.create(:lettings_log, :about_completed) } + + it "has the correct breadcrumbs with the correct links" do + visit lettings_log_setup_check_answers_path(lettings_log) + breadcrumbs = page.find_all(".govuk-breadcrumbs__link") + expect(breadcrumbs.first.text).to eq "Logs" + expect(breadcrumbs.first[:href]).to eq lettings_logs_path + expect(breadcrumbs[1].text).to eq "Log #{lettings_log.id}" + expect(breadcrumbs[1][:href]).to eq lettings_log_path(lettings_log) + end + end + + context "when reviewing a complete log" do + let(:lettings_log) { FactoryBot.create(:lettings_log, :completed) } + + it "has the correct breadcrumbs with the correct links" do + visit review_lettings_log_path(lettings_log) + breadcrumbs = page.find_all(".govuk-breadcrumbs__link") + expect(breadcrumbs.first.text).to eq "Logs" + expect(breadcrumbs.first[:href]).to eq lettings_logs_path + expect(breadcrumbs[1].text).to eq "Log #{lettings_log.id}" + expect(breadcrumbs[1][:href]).to eq lettings_log_path(lettings_log) + end + end + context "when the owning organisation question isn't answered" do it "doesn't show the managing agent question" do visit("/lettings-logs") diff --git a/spec/features/sales_log_spec.rb b/spec/features/sales_log_spec.rb index 04331d824..759b298f3 100644 --- a/spec/features/sales_log_spec.rb +++ b/spec/features/sales_log_spec.rb @@ -28,7 +28,7 @@ RSpec.describe "Sales Log Features" do click_link("Logs") end - it "navigates you to the lettings logs page" do + it "navigates you to the sales logs page" do expect(page).to have_current_path("/sales-logs") end end @@ -65,4 +65,48 @@ RSpec.describe "Sales Log Features" do end end end + + context "when signed in as a support user" do + let(:devise_notify_mailer) { DeviseNotifyMailer.new } + let(:notify_client) { instance_double(Notifications::Client) } + let(:otp) { "999111" } + let(:organisation) { FactoryBot.create(:organisation, name: "Big ORG") } + let(:user) { FactoryBot.create(:user, :support, last_sign_in_at: Time.zone.now, organisation:) } + let(:sales_log) { FactoryBot.create(:sales_log, :completed) } + + before do + allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) + allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) + allow(notify_client).to receive(:send_email).and_return(true) + allow(SecureRandom).to receive(:random_number).and_return(otp) + visit("/sales-logs") + fill_in("user[email]", with: user.email) + fill_in("user[password]", with: user.password) + click_button("Sign in") + fill_in("code", with: otp) + click_button("Submit") + end + + context "when visiting a subsection check answers page as a support user" do + it "has the correct breadcrumbs with the correct links" do + visit sales_log_setup_check_answers_path(sales_log.id) + breadcrumbs = page.find_all(".govuk-breadcrumbs__link") + expect(breadcrumbs.first.text).to eq "Logs" + expect(breadcrumbs.first[:href]).to eq sales_logs_path + expect(breadcrumbs[1].text).to eq "Log #{sales_log.id}" + expect(breadcrumbs[1][:href]).to eq sales_log_path(sales_log.id) + end + end + + context "when reviewing a complete log" do + it "has the correct breadcrumbs with the correct links" do + visit review_sales_log_path(sales_log.id, sales_log: true) + breadcrumbs = page.find_all(".govuk-breadcrumbs__link") + expect(breadcrumbs.first.text).to eq "Logs" + expect(breadcrumbs.first[:href]).to eq sales_logs_path + expect(breadcrumbs[1].text).to eq "Log #{sales_log.id}" + expect(breadcrumbs[1][:href]).to eq sales_log_path(sales_log.id) + end + end + end end diff --git a/spec/fixtures/exports/general_needs_log.csv b/spec/fixtures/exports/general_needs_log.csv index 0185f54e0..37ee27089 100644 --- a/spec/fixtures/exports/general_needs_log.csv +++ b/spec/fixtures/exports/general_needs_log.csv @@ -1,2 +1,2 @@ status,tenancycode,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,ppcodenk,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,hhtype,new_old,vacdays,formid,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate -2,BZ737,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,1,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00 +2,BZ737,35,F,2,13,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,4,1,1,1,2,1,5,1,SE2 6RT,6,7,3,2,1,68,1,1,2,2,7,NW1 5TY,1,2,1,2,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05T10:36:49+01:00,0,2022-02-02T10:36:49+00:00,1,2,1,2019-11-03T00:00:00+00:00,2,1,7,0,0,2,0,2,200.0,50.0,40.0,35.0,325.0,12.0,,1,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,,4,2,638,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-05-01T00:00:00+01:00,2022-05-01T00:00:00+01:00 diff --git a/spec/fixtures/exports/general_needs_log.xml b/spec/fixtures/exports/general_needs_log.xml index f05de09e3..11c50ed4e 100644 --- a/spec/fixtures/exports/general_needs_log.xml +++ b/spec/fixtures/exports/general_needs_log.xml @@ -6,7 +6,7 @@ 35 F 2 - 4 + 13 6 0 2 @@ -51,7 +51,7 @@ 1 2 2 - 1 + 7 NW1 5TY 1 2 diff --git a/spec/fixtures/exports/supported_housing_logs.xml b/spec/fixtures/exports/supported_housing_logs.xml index 0a0ed0981..3b535c226 100644 --- a/spec/fixtures/exports/supported_housing_logs.xml +++ b/spec/fixtures/exports/supported_housing_logs.xml @@ -6,7 +6,7 @@ 35 F 2 - 4 + 13 6 0 2 @@ -50,7 +50,7 @@ 1 2 2 - 1 + 7 SW1A 2AA 1 2 diff --git a/spec/fixtures/files/lettings_logs_download.csv b/spec/fixtures/files/lettings_logs_download.csv index 394c3b920..463f81d3c 100644 --- a/spec/fixtures/files/lettings_logs_download.csv +++ b/spec/fixtures/files/lettings_logs_download.csv @@ -1,2 +1,2 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} +id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} diff --git a/spec/fixtures/files/lettings_logs_download_codes_only.csv b/spec/fixtures/files/lettings_logs_download_codes_only.csv index 423675c5b..6d15538ef 100644 --- a/spec/fixtures/files/lettings_logs_download_codes_only.csv +++ b/spec/fixtures/files/lettings_logs_download_codes_only.csv @@ -1,2 +1,2 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate} +id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate} diff --git a/spec/fixtures/files/lettings_logs_download_non_support.csv b/spec/fixtures/files/lettings_logs_download_non_support.csv index a2fa80f4f..cc89d6bfb 100644 --- a/spec/fixtures/files/lettings_logs_download_non_support.csv +++ b/spec/fixtures/files/lettings_logs_download_non_support.csv @@ -1,2 +1,2 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,renewal,startdate,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,relat2,age2,sex2,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,prevloc_label,illness_type_1,illness_type_2,la_label,postcode_full,wchair,preg_occ,cbl,earnings,incfreq,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,unitletas,builtype,voiddate,lettype,nocharge,household_charge,referral,tshortfall,chcharge,ppcodenk,ethnic_group,has_benefits,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,2 October 2021,,,,,,,,,,,,,,,,,,,,,Westminster,SE1 1TE,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,0,,,,,,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} +id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,renewal,startdate,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,relat2,age2,sex2,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,prevloc_label,illness_type_1,illness_type_2,la_label,postcode_full,wchair,preg_occ,cbl,earnings,incfreq,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,unitletas,builtype,voiddate,lettype,nocharge,household_charge,referral,tshortfall,chcharge,ppcodenk,ethnic_group,has_benefits,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,scheme_code,scheme_service_name,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,2 October 2021,,,,,,,,,,,,,,,,,,,,,Westminster,SE1 1TE,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,0,,,,,,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} diff --git a/spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml b/spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml index c43bcf0bf..15f97ce5b 100644 --- a/spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml +++ b/spec/fixtures/imports/logs/0ead17cb-1668-442d-898c-0d52879ff592.xml @@ -119,6 +119,7 @@ Yes 2 No + 2 No diff --git a/spec/helpers/schemes_helper_spec.rb b/spec/helpers/schemes_helper_spec.rb index 77f178f62..6ab283eca 100644 --- a/spec/helpers/schemes_helper_spec.rb +++ b/spec/helpers/schemes_helper_spec.rb @@ -110,166 +110,213 @@ RSpec.describe SchemesHelper do let(:support_user) { FactoryBot.create(:user, :support) } let(:coordinator_user) { FactoryBot.create(:user, :data_coordinator) } - it "returns correct display attributes for a support user" do - attributes = [ - { name: "Scheme code", value: "S#{scheme.id}" }, - { name: "Name", value: "Test service_name", edit: true }, - { name: "Confidential information", value: "No", edit: true }, - { name: "Type of scheme", value: "Housing for older people" }, - { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, - { name: "Housing stock owned by", value: "Acme LTD Owning", edit: true }, - { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, - { name: "Primary client group", value: "Rough sleepers" }, - { name: "Has another client group", value: "Yes" }, - { name: "Secondary client group", value: "Refugees (permanent)" }, - { name: "Level of support given", value: "High level" }, - { name: "Intended length of stay", value: "Permanent" }, - { name: "Availability", value: "Active from 1 April 2022" }, - { name: "Status", value: status_tag(:active) }, - ] - expect(display_scheme_attributes(scheme, support_user)).to eq(attributes) - end + context "when scheme has no locations" do + it "returns correct display attributes for a support user" do + attributes = [ + { name: "Scheme code", value: "S#{scheme.id}" }, + { name: "Name", value: "Test service_name", edit: true }, + { name: "Confidential information", value: "No", edit: true }, + { name: "Type of scheme", value: "Housing for older people" }, + { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, + { name: "Housing stock owned by", value: "Acme LTD Owning", edit: true }, + { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, + { name: "Primary client group", value: "Rough sleepers" }, + { name: "Has another client group", value: "Yes" }, + { name: "Secondary client group", value: "Refugees (permanent)" }, + { name: "Level of support given", value: "High level" }, + { name: "Intended length of stay", value: "Permanent" }, + { name: "Availability", value: "Active from 1 April 2022" }, + { name: "Status", value: status_tag(:incomplete) }, + ] + expect(display_scheme_attributes(scheme, support_user)).to eq(attributes) + end - it "returns correct display attributes for a coordinator user" do - attributes = [ - { name: "Scheme code", value: "S#{scheme.id}" }, - { name: "Name", value: "Test service_name", edit: true }, - { name: "Confidential information", value: "No", edit: true }, - { name: "Type of scheme", value: "Housing for older people" }, - { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, - { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, - { name: "Primary client group", value: "Rough sleepers" }, - { name: "Has another client group", value: "Yes" }, - { name: "Secondary client group", value: "Refugees (permanent)" }, - { name: "Level of support given", value: "High level" }, - { name: "Intended length of stay", value: "Permanent" }, - { name: "Availability", value: "Active from 1 April 2022" }, - { name: "Status", value: status_tag(:active) }, - ] - expect(display_scheme_attributes(scheme, coordinator_user)).to eq(attributes) + it "returns correct display attributes for a coordinator user" do + attributes = [ + { name: "Scheme code", value: "S#{scheme.id}" }, + { name: "Name", value: "Test service_name", edit: true }, + { name: "Confidential information", value: "No", edit: true }, + { name: "Type of scheme", value: "Housing for older people" }, + { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, + { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, + { name: "Primary client group", value: "Rough sleepers" }, + { name: "Has another client group", value: "Yes" }, + { name: "Secondary client group", value: "Refugees (permanent)" }, + { name: "Level of support given", value: "High level" }, + { name: "Intended length of stay", value: "Permanent" }, + { name: "Availability", value: "Active from 1 April 2022" }, + { name: "Status", value: status_tag(:incomplete) }, + ] + expect(display_scheme_attributes(scheme, coordinator_user)).to eq(attributes) + end end - context "when the scheme toggle is disabled" do - it "doesn't show the scheme status" do - allow(FeatureToggle).to receive(:scheme_toggle_enabled?).and_return(false) - attributes = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Status" } - expect(attributes).to be_nil + context "when scheme has a location" do + before do + FactoryBot.create(:location, scheme:) end - end - context "when the managing organisation is the owning organisation" do - it "doesn't show the organisation providing support" do - attributes = display_scheme_attributes(scheme_where_managing_organisation_is_owning_organisation, support_user).find { |x| x[:name] == "Organisation providing support" } - expect(attributes).to be_nil + it "returns correct display attributes for a support user" do + attributes = [ + { name: "Scheme code", value: "S#{scheme.id}" }, + { name: "Name", value: "Test service_name", edit: true }, + { name: "Confidential information", value: "No", edit: true }, + { name: "Type of scheme", value: "Housing for older people" }, + { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, + { name: "Housing stock owned by", value: "Acme LTD Owning", edit: true }, + { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, + { name: "Primary client group", value: "Rough sleepers" }, + { name: "Has another client group", value: "Yes" }, + { name: "Secondary client group", value: "Refugees (permanent)" }, + { name: "Level of support given", value: "High level" }, + { name: "Intended length of stay", value: "Permanent" }, + { name: "Availability", value: "Active from 1 April 2022" }, + { name: "Status", value: status_tag(:active) }, + ] + expect(display_scheme_attributes(scheme, support_user)).to eq(attributes) end - end - context "when viewing availability" do - context "with no deactivations" do - it "displays created_at as availability date" do - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + it "returns correct display attributes for a coordinator user" do + attributes = [ + { name: "Scheme code", value: "S#{scheme.id}" }, + { name: "Name", value: "Test service_name", edit: true }, + { name: "Confidential information", value: "No", edit: true }, + { name: "Type of scheme", value: "Housing for older people" }, + { name: "Registered under Care Standards Act 2000", value: "Yes – registered care home providing personal care" }, + { name: "Support services provided by", value: "A registered charity or voluntary organisation" }, + { name: "Primary client group", value: "Rough sleepers" }, + { name: "Has another client group", value: "Yes" }, + { name: "Secondary client group", value: "Refugees (permanent)" }, + { name: "Level of support given", value: "High level" }, + { name: "Intended length of stay", value: "Permanent" }, + { name: "Availability", value: "Active from 1 April 2022" }, + { name: "Status", value: status_tag(:active) }, + ] + expect(display_scheme_attributes(scheme, coordinator_user)).to eq(attributes) + end - expect(availability_attribute).to eq("Active from #{scheme.created_at.to_formatted_s(:govuk_date)}") + context "when the scheme toggle is disabled" do + it "doesn't show the scheme status" do + allow(FeatureToggle).to receive(:scheme_toggle_enabled?).and_return(false) + attributes = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Status" } + expect(attributes).to be_nil end + end - it "displays current collection start date as availability date if created_at is later than collection start date" do - scheme.update!(created_at: Time.zone.local(2022, 4, 16)) - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - - expect(availability_attribute).to eq("Active from 1 April 2022") + context "when the managing organisation is the owning organisation" do + it "doesn't show the organisation providing support" do + attributes = display_scheme_attributes(scheme_where_managing_organisation_is_owning_organisation, support_user).find { |x| x[:name] == "Organisation providing support" } + expect(attributes).to be_nil end end - context "with previous deactivations" do - context "and all reactivated deactivations" do - before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) - scheme.reload + context "when viewing availability" do + context "with no deactivations" do + it "displays created_at as availability date" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from #{scheme.created_at.to_formatted_s(:govuk_date)}") end - it "displays the timeline of availability" do + it "displays current collection start date as availability date if created_at is later than collection start date" do + scheme.update!(created_at: Time.zone.local(2022, 4, 16)) availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022\nActive from 28 September 2022") + expect(availability_attribute).to eq("Active from 1 April 2022") end end - context "and non reactivated deactivation" do - before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, scheme:) - scheme.reload + context "with previous deactivations" do + context "and all reactivated deactivations" do + before do + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) + scheme.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022\nActive from 28 September 2022") + end end - it "displays the timeline of availability" do - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + context "and non reactivated deactivation" do + before do + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 8, 10), reactivation_date: Time.zone.local(2022, 9, 1), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 15), reactivation_date: nil, scheme:) + scheme.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022") + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 August 2022\nDeactivated on 10 August 2022\nActive from 1 September 2022 to 14 September 2022\nDeactivated on 15 September 2022") + end end end - end - context "with out of order deactivations" do - context "and all reactivated deactivations" do - before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: Time.zone.local(2022, 6, 18), scheme:) - scheme.reload + context "with out of order deactivations" do + context "and all reactivated deactivations" do + before do + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: Time.zone.local(2022, 6, 18), scheme:) + scheme.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 18 June 2022 to 23 September 2022\nDeactivated on 24 September 2022\nActive from 28 September 2022") + end end - it "displays the timeline of availability" do - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + context "and one non reactivated deactivation" do + before do + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, scheme:) + scheme.reload + end + + it "displays the timeline of availability" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 18 June 2022 to 23 September 2022\nDeactivated on 24 September 2022\nActive from 28 September 2022") + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022") + end end end - context "and one non reactivated deactivation" do - before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, scheme:) - scheme.reload - end + context "with multiple out of order deactivations" do + context "and one non reactivated deactivation" do + before do + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 24), reactivation_date: Time.zone.local(2022, 10, 28), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, scheme:) + scheme.reload + end - it "displays the timeline of availability" do - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] + it "displays the timeline of availability" do + availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022") + expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022 to 23 October 2022\nDeactivated on 24 October 2022\nActive from 28 October 2022") + end end end - end - context "with multiple out of order deactivations" do - context "and one non reactivated deactivation" do + context "with intersecting deactivations" do before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 9, 24), reactivation_date: Time.zone.local(2022, 9, 28), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 24), reactivation_date: Time.zone.local(2022, 10, 28), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 15), reactivation_date: nil, scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 10), reactivation_date: Time.zone.local(2022, 12, 1), scheme:) + FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 11, 11), reactivation_date: Time.zone.local(2022, 12, 11), scheme:) scheme.reload end it "displays the timeline of availability" do availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - expect(availability_attribute).to eq("Active from 1 April 2022 to 14 June 2022\nDeactivated on 15 June 2022\nActive from 28 September 2022 to 23 October 2022\nDeactivated on 24 October 2022\nActive from 28 October 2022") + expect(availability_attribute).to eq("Active from 1 April 2022 to 9 October 2022\nDeactivated on 10 October 2022\nActive from 11 December 2022") end end end - - context "with intersecting deactivations" do - before do - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 10, 10), reactivation_date: Time.zone.local(2022, 12, 1), scheme:) - FactoryBot.create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 11, 11), reactivation_date: Time.zone.local(2022, 12, 11), scheme:) - scheme.reload - end - - it "displays the timeline of availability" do - availability_attribute = display_scheme_attributes(scheme, support_user).find { |x| x[:name] == "Availability" }[:value] - - expect(availability_attribute).to eq("Active from 1 April 2022 to 9 October 2022\nDeactivated on 10 October 2022\nActive from 11 December 2022") - end - end end end end diff --git a/spec/helpers/tasklist_helper_spec.rb b/spec/helpers/tasklist_helper_spec.rb index 5d75616ec..bd1bdb61f 100644 --- a/spec/helpers/tasklist_helper_spec.rb +++ b/spec/helpers/tasklist_helper_spec.rb @@ -81,18 +81,18 @@ RSpec.describe TasklistHelper do context "with sales log" do context "when collection_period_open? == true" do let(:now) { Time.utc(2022, 6, 1) } - let(:sales_log) { create(:sales_log, :completed) } + let(:sales_log) { create(:sales_log, :completed, saledate: now) } it "returns relevant text" do expect(review_log_text(sales_log)).to eq( - "You can #{govuk_link_to 'review and make changes to this log', review_sales_log_path(id: sales_log, sales_log: true)} until 7 July 2023.".html_safe, + "You can #{govuk_link_to 'review and make changes to this log', review_sales_log_path(id: sales_log, sales_log: true)} until 7 June 2023.".html_safe, ) end end context "when collection_period_open? == false" do let(:now) { Time.utc(2022, 6, 1) } - let!(:sales_log) { create(:sales_log, :completed) } + let!(:sales_log) { create(:sales_log, :completed, saledate: now) } it "returns relevant text" do Timecop.freeze(now + 1.year) do @@ -121,7 +121,7 @@ RSpec.describe TasklistHelper do it "returns relevant text" do expect(review_log_text(lettings_log)).to eq( - "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 July 2024.".html_safe, + "You can #{govuk_link_to 'review and make changes to this log', review_lettings_log_path(lettings_log)} until 9 June 2024.".html_safe, ) end end diff --git a/spec/mailers/bulk_upload_mailer_spec.rb b/spec/mailers/bulk_upload_mailer_spec.rb index 9f59de365..2e4337328 100644 --- a/spec/mailers/bulk_upload_mailer_spec.rb +++ b/spec/mailers/bulk_upload_mailer_spec.rb @@ -116,7 +116,7 @@ RSpec.describe BulkUploadMailer do create(:bulk_upload_error, bulk_upload:, col: "B") end - it "sends correctly formed email with A, B" do + it "sends correctly formed email" do expect(notify_client).to receive(:send_email).with( email_address: user.email, template_id: described_class::BULK_UPLOAD_FAILED_CSV_ERRORS_TEMPLATE_ID, @@ -125,7 +125,6 @@ RSpec.describe BulkUploadMailer do upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time), year_combo: bulk_upload.year_combo, lettings_or_sales: bulk_upload.log_type, - error_description: "We noticed that you have a lot of similar errors in column A, B. Please correct your data export and upload again.", summary_report_link: "http://localhost:3000/lettings-logs/bulk-upload-results/#{bulk_upload.id}", }, ) @@ -133,33 +132,5 @@ RSpec.describe BulkUploadMailer do mailer.send_correct_and_upload_again_mail(bulk_upload:) end end - - context "when 4 columns with errors" do - before do - stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 0) - - create(:bulk_upload_error, bulk_upload:, col: "A") - create(:bulk_upload_error, bulk_upload:, col: "B") - create(:bulk_upload_error, bulk_upload:, col: "C") - create(:bulk_upload_error, bulk_upload:, col: "D") - end - - it "sends correctly formed email with A, B, C and more" do - expect(notify_client).to receive(:send_email).with( - email_address: user.email, - template_id: described_class::BULK_UPLOAD_FAILED_CSV_ERRORS_TEMPLATE_ID, - personalisation: { - filename: bulk_upload.filename, - upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time), - year_combo: bulk_upload.year_combo, - lettings_or_sales: bulk_upload.log_type, - error_description: "We noticed that you have a lot of similar errors in column A, B, C and more. Please correct your data export and upload again.", - summary_report_link: "http://localhost:3000/lettings-logs/bulk-upload-results/#{bulk_upload.id}/summary", - }, - ) - - mailer.send_correct_and_upload_again_mail(bulk_upload:) - end - end end end diff --git a/spec/models/form/lettings/pages/address_spec.rb b/spec/models/form/lettings/pages/address_spec.rb new file mode 100644 index 000000000..230d6964f --- /dev/null +++ b/spec/models/form/lettings/pages/address_spec.rb @@ -0,0 +1,73 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::Address, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection) } + + let(:page_id) { nil } + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[address_line1 address_line2 town_or_city county postcode_full]) + end + + it "has the correct id" do + expect(page.id).to eq("address") + end + + it "has the correct header" do + expect(page.header).to eq("Q12 - What is the property's address?") + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + it "has correct depends_on" do + expect(page.depends_on).to be_nil + end + + describe "has correct routed_to?" do + context "when uprn_known == nil" do + let(:log) { create(:lettings_log, uprn_known: nil) } + + it "returns false" do + expect(page.routed_to?(log)).to eq(false) + end + end + + context "when uprn_confirmed != 1" do + let(:log) do + create(:lettings_log, uprn_known: 1, uprn_confirmed: 0) + end + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when uprn_known == 0" do + let(:log) do + create(:lettings_log, uprn_known: 0, uprn_confirmed: 0) + end + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when uprn_confirmed == 1 && uprn_known != 0" do + let(:log) do + create(:lettings_log, uprn_known: 1, uprn_confirmed: 1) + end + + it "returns true" do + expect(page.routed_to?(log)).to eq(false) + end + end + end +end 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 new file mode 100644 index 000000000..c81538146 --- /dev/null +++ b/spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::CareHomeChargesValueCheck, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection) } + + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has the correct header" do + expect(page.header).to be nil + end + + it "has the correct description" do + expect(page.description).to be nil + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[carehome_charges_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("care_home_charges_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [{ "care_home_charge_expected_not_provided?" => true }], + ) + end + + it "has the correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.care_home_charges.title_text", + }) + end + + it "has the correct informative_text" do + expect(page.informative_text).to eq("") + end +end diff --git a/spec/models/form/lettings/pages/property_local_authority_spec.rb b/spec/models/form/lettings/pages/property_local_authority_spec.rb new file mode 100644 index 000000000..5b5ee95eb --- /dev/null +++ b/spec/models/form/lettings/pages/property_local_authority_spec.rb @@ -0,0 +1,77 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::PropertyLocalAuthority, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection) } + + let(:page_id) { nil } + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) } + let(:start_date) { Time.utc(2022, 4, 1) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq( + %w[ + la + ], + ) + end + + it "has the correct id" do + expect(page.id).to eq("property_local_authority") + end + + it "has the correct header" do + expect(page.header).to be_nil + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + it "has the correct depends_on" do + expect(page.depends_on).to match([{ "is_general_needs?" => true, "is_la_inferred" => false }]) + end + + describe "has correct routed_to?" do + context "when start_date < 2023" do + let(:log) { create(:lettings_log, uprn_known: 1) } + let(:start_date) { Time.utc(2022, 2, 8) } + + it "returns false" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when start_date >= 2023" do + let(:log) { create(:lettings_log, uprn_known: 1) } + let(:start_date) { Time.utc(2023, 2, 8) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when start_date < 2023 and uprn_known: nil" do + let(:log) { create(:lettings_log, uprn_known: nil) } + let(:start_date) { Time.utc(2023, 2, 8) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(false) + end + + context "when is_la_inferred: true" do + before do + allow(log).to receive(:is_la_inferred?).and_return(true) + end + + it "returns true" do + expect(page.routed_to?(log)).to eq(false) + end + end + end + end +end diff --git a/spec/models/form/lettings/pages/property_wheelchair_accessible_spec.rb b/spec/models/form/lettings/pages/property_wheelchair_accessible_spec.rb index 4e487e239..b96a55feb 100644 --- a/spec/models/form/lettings/pages/property_wheelchair_accessible_spec.rb +++ b/spec/models/form/lettings/pages/property_wheelchair_accessible_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Form::Lettings::Pages::PropertyWheelchairAccessible, type: :model let(:subsection) { instance_double(Form::Subsection) } it "has correct subsection" do - expect(page.subsection).to eq(subsection) + expect(page.subsection).to be(subsection) end it "has correct questions" do @@ -26,6 +26,6 @@ RSpec.describe Form::Lettings::Pages::PropertyWheelchairAccessible, type: :model end it "has the correct depends_on" do - expect(page.depends_on).to eq([{ "is_supported_housing?" => false }]) + expect(page.depends_on).to eq([{ "is_general_needs?" => true }]) end end diff --git a/spec/models/form/lettings/pages/uprn_confirmation_spec.rb b/spec/models/form/lettings/pages/uprn_confirmation_spec.rb new file mode 100644 index 000000000..e1c6a587d --- /dev/null +++ b/spec/models/form/lettings/pages/uprn_confirmation_spec.rb @@ -0,0 +1,59 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::UprnConfirmation, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection) } + + let(:page_id) { nil } + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[uprn_confirmed]) + end + + it "has the correct id" do + expect(page.id).to eq("uprn_confirmation") + end + + it "has the correct header" do + expect(page.header).to eq("We found an address that might be this property") + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + it "has correct depends_on" do + expect(page.depends_on).to be_nil + end + + describe "has correct routed_to?" do + context "when uprn present && uprn_known == 1 " do + let(:log) { create(:lettings_log, uprn_known: 1, uprn: "123456789") } + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when uprn = nil" do + let(:log) { create(:lettings_log, uprn_known: 1, uprn: nil) } + + it "returns false" do + expect(page.routed_to?(log)).to eq(false) + end + end + + context "when uprn_known == 0" do + let(:log) { create(:lettings_log, uprn_known: 0, uprn: "123456789") } + + it "returns false" do + expect(page.routed_to?(log)).to eq(false) + end + end + end +end diff --git a/spec/models/form/lettings/pages/uprn_known_spec.rb b/spec/models/form/lettings/pages/uprn_known_spec.rb new file mode 100644 index 000000000..27b893a5c --- /dev/null +++ b/spec/models/form/lettings/pages/uprn_known_spec.rb @@ -0,0 +1,51 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::UprnKnown, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection) } + + let(:page_id) { nil } + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[uprn_known]) + end + + it "has the correct id" do + expect(page.id).to eq("uprn_known") + end + + it "has the correct header" do + expect(page.header).to be_nil + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + it "has correct depends_on" do + expect(page.depends_on).to be_nil + end + + describe "has correct routed_to?" do + context "when needstype != 2" do + let(:log) { create(:lettings_log, needstype: nil) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when needstype == 2" do + let(:log) { create(:lettings_log, needstype: 2) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(false) + end + end + end +end diff --git a/spec/models/form/lettings/pages/uprn_spec.rb b/spec/models/form/lettings/pages/uprn_spec.rb new file mode 100644 index 000000000..7b480b6b2 --- /dev/null +++ b/spec/models/form/lettings/pages/uprn_spec.rb @@ -0,0 +1,81 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::Uprn, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection) } + + let(:page_id) { nil } + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[uprn]) + end + + it "has the correct id" do + expect(page.id).to eq("uprn") + end + + it "has the correct header" do + expect(page.header).to be_nil + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + it "has correct depends_on" do + expect(page.depends_on).to be_nil + end + + it "has correct skip_text" do + expect(page.skip_text).to eq("Enter address instead") + end + + describe "has correct routed_to?" do + context "when uprn_known != 1" do + let(:log) { create(:lettings_log, uprn_known: 0) } + + it "returns false" do + expect(page.routed_to?(log)).to eq(false) + end + end + + context "when uprn_known == 1" do + let(:log) { create(:lettings_log, uprn_known: 1) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(true) + end + end + + context "when needstype == 2" do + let(:log) { create(:lettings_log, uprn_known: 1, needstype: 2) } + + it "returns true" do + expect(page.routed_to?(log)).to eq(false) + end + end + end + + describe "has correct skip_href" do + context "when log is nil" do + it "is nil" do + expect(page.skip_href).to be_nil + end + end + + context "when log is present" do + let(:log) { create(:lettings_log) } + + it "points to address page" do + expect(page.skip_href(log)).to eq( + "/lettings-logs/#{log.id}/address", + ) + end + end + end +end diff --git a/spec/models/form/lettings/questions/address_line1_spec.rb b/spec/models/form/lettings/questions/address_line1_spec.rb new file mode 100644 index 000000000..e2600f0cc --- /dev/null +++ b/spec/models/form/lettings/questions/address_line1_spec.rb @@ -0,0 +1,79 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::AddressLine1, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("address_line1") + end + + it "has the correct header" do + expect(question.header).to eq("Address line 1") + end + + it "has the correct question_number" do + expect(question.question_number).to be_nil + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Q12 - Address") + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct inferred check answers value" do + expect(question.inferred_check_answers_value).to be_nil + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to be_nil + end + + describe "has the correct get_extra_check_answer_value" do + context "when la is not present" do + let(:log) { create(:lettings_log, la: nil) } + + it "returns nil" do + expect(question.get_extra_check_answer_value(log)).to be_nil + end + end + + context "when la is present but not inferred" do + let(:log) { create(:lettings_log, la: "E09000003", is_la_inferred: false) } + + it "returns nil" do + expect(question.get_extra_check_answer_value(log)).to be_nil + end + end + + context "when la is present but inferred" do + let(:log) { create(:lettings_log, la: "E09000003") } + + before do + allow(log).to receive(:is_la_inferred?).and_return(true) + end + + it "returns the la" do + expect(question.get_extra_check_answer_value(log)).to eq("Barnet") + end + end + end +end diff --git a/spec/models/form/lettings/questions/address_line2_spec.rb b/spec/models/form/lettings/questions/address_line2_spec.rb new file mode 100644 index 000000000..4ac51a231 --- /dev/null +++ b/spec/models/form/lettings/questions/address_line2_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::AddressLine2, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("address_line2") + end + + it "has the correct header" do + expect(question.header).to eq("Address line 2 (optional)") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to be_nil + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct inferred check answers value" do + expect(question.inferred_check_answers_value).to be_nil + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to be_nil + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers?).to eq(true) + end +end diff --git a/spec/models/form/lettings/questions/care_home_charges_value_check_spec.rb b/spec/models/form/lettings/questions/care_home_charges_value_check_spec.rb new file mode 100644 index 000000000..d31891c5d --- /dev/null +++ b/spec/models/form/lettings/questions/care_home_charges_value_check_spec.rb @@ -0,0 +1,56 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::CareHomeChargesValueCheck, type: :model do + subject(:question) { described_class.new(nil, question_definition, page) } + + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("carehome_charges_value_check") + end + + it "has the correct header" do + expect(question.header).to eq("Are you sure there are no care home charges?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Care home charges confirmation") + end + + it "has the correct type" do + expect(question.type).to eq("interruption_screen") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "0" => { "value" => "Yes" }, + "1" => { "value" => "No" }, + }) + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers).to eq({ + "depends_on" => [ + { + "carehome_charges_value_check" => 0, + }, + { + "carehome_charges_value_check" => 1, + }, + ], + }) + end +end diff --git a/spec/models/form/lettings/questions/county_spec.rb b/spec/models/form/lettings/questions/county_spec.rb new file mode 100644 index 000000000..cf8f814e4 --- /dev/null +++ b/spec/models/form/lettings/questions/county_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::County, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("county") + end + + it "has the correct header" do + expect(question.header).to eq("County (optional)") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to be_nil + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct inferred check answers value" do + expect(question.inferred_check_answers_value).to be_nil + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to be_nil + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers?).to eq(true) + end +end diff --git a/spec/models/form/lettings/questions/la_spec.rb b/spec/models/form/lettings/questions/la_spec.rb index f73a29660..3b5e30977 100644 --- a/spec/models/form/lettings/questions/la_spec.rb +++ b/spec/models/form/lettings/questions/la_spec.rb @@ -315,4 +315,34 @@ RSpec.describe Form::Lettings::Questions::La, type: :model do "E06000065" => "North Yorkshire", }) end + + describe "has the correct hidden_in_check_answers" do + context "when saledate.year before 2023" do + let(:log) { build(:lettings_log, startdate: Time.zone.parse("2022-07-01")) } + + it "returns false" do + expect(question.hidden_in_check_answers?(log)).to eq(false) + end + end + + context "when saledate.year >= 2023" do + let(:log) { build(:lettings_log, startdate: Time.zone.parse("2023-07-01")) } + + it "returns true" do + expect(question.hidden_in_check_answers?(log)).to eq(false) + end + end + + context "when saledate.year >= 2023 and la inferred" do + let(:log) { build(:lettings_log, startdate: Time.zone.parse("2023-07-01")) } + + before do + allow(log).to receive(:is_la_inferred?).and_return(true) + end + + it "returns true" do + expect(question.hidden_in_check_answers?(log)).to eq(true) + end + end + end end diff --git a/spec/models/form/lettings/questions/postcode_for_full_address_spec.rb b/spec/models/form/lettings/questions/postcode_for_full_address_spec.rb new file mode 100644 index 000000000..ccb02ef07 --- /dev/null +++ b/spec/models/form/lettings/questions/postcode_for_full_address_spec.rb @@ -0,0 +1,62 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::PostcodeForFullAddress, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("postcode_full") + end + + it "has the correct header" do + expect(question.header).to eq("Postcode") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to be_nil + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct width" do + expect(question.width).to eq(5) + end + + it "has the correct inferred_answers" do + expect(question.inferred_answers).to eq({ + "la" => { + "is_la_inferred" => true, + }, + }) + end + + it "has the correct inferred_check_answers_value" do + expect(question.inferred_check_answers_value).to eq([{ + "condition" => { + "pcodenk" => 1, + }, + "value" => "Not known", + }]) + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers?).to eq(true) + end +end diff --git a/spec/models/form/lettings/questions/town_or_city_spec.rb b/spec/models/form/lettings/questions/town_or_city_spec.rb new file mode 100644 index 000000000..8741fb058 --- /dev/null +++ b/spec/models/form/lettings/questions/town_or_city_spec.rb @@ -0,0 +1,49 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::TownOrCity, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("town_or_city") + end + + it "has the correct header" do + expect(question.header).to eq("Town or city") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to be_nil + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct inferred check answers value" do + expect(question.inferred_check_answers_value).to be_nil + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to be_nil + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers?).to eq(true) + end +end diff --git a/spec/models/form/lettings/questions/uprn_confirmation_spec.rb b/spec/models/form/lettings/questions/uprn_confirmation_spec.rb new file mode 100644 index 000000000..3c409641d --- /dev/null +++ b/spec/models/form/lettings/questions/uprn_confirmation_spec.rb @@ -0,0 +1,90 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::UprnConfirmation, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("uprn_confirmed") + end + + it "has the correct header" do + expect(question.header).to eq("Is this the property address?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Is this the right address?") + end + + it "has the correct type" do + expect(question.type).to eq("radio") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct unanswered_error_message" do + expect(question.unanswered_error_message).to eq("You must answer is this the right address?") + end + + describe "notification_banner" do + context "when address is not present" do + it "returns nil" do + log = create(:lettings_log) + + expect(question.notification_banner(log)).to be_nil + end + end + + context "when address is present" do + it "returns formatted value" do + log = create(:lettings_log, address_line1: "1, Test Street", town_or_city: "Test Town", county: "Test County", postcode_full: "AA1 1AA", uprn: "1234") + + expect(question.notification_banner(log)).to eq( + { + heading: "1, Test Street\nAA1 1AA\nTest Town\nTest County", + title: "UPRN: 1234", + }, + ) + end + end + end + + describe "has the correct hidden_in_check_answers" do + context "when uprn_known != 1 && uprn_confirmed == nil" do + let(:log) { create(:lettings_log, uprn_known: 0, uprn_confirmed: nil) } + + it "returns true" do + expect(question.hidden_in_check_answers?(log)).to eq(true) + end + end + + context "when uprn_known == 1 && uprn_confirmed == nil" do + let(:log) { create(:lettings_log, uprn_known: 1, uprn_confirmed: nil) } + + it "returns false" do + expect(question.hidden_in_check_answers?(log)).to eq(false) + end + end + + context "when uprn_known != 1 && uprn_confirmed == 1" do + let(:log) { create(:lettings_log, uprn_known: 1, uprn_confirmed: 1) } + + it "returns true" do + expect(question.hidden_in_check_answers?(log)).to eq(true) + end + end + end +end diff --git a/spec/models/form/lettings/questions/uprn_known_spec.rb b/spec/models/form/lettings/questions/uprn_known_spec.rb new file mode 100644 index 000000000..07eb72f8d --- /dev/null +++ b/spec/models/form/lettings/questions/uprn_known_spec.rb @@ -0,0 +1,59 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::UprnKnown, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("uprn_known") + end + + it "has the correct header" do + expect(question.header).to eq("Do you know the property's UPRN?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("UPRN known?") + end + + it "has the correct type" do + expect(question.type).to eq("radio") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "0" => { "value" => "No" }, + "1" => { "value" => "Yes" }, + }) + end + + it "has correct conditional for" do + expect(question.conditional_for).to be_nil + end + + it "has the correct unanswered_error_message" do + expect(question.unanswered_error_message).to eq("You must answer UPRN known?") + end + + it "has the correct hint" do + expect(question.hint_text).to eq( + "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.

+ You can continue without the UPRN, but it means we will need you to enter the address of the property.", + ) + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers).to be_nil + end +end diff --git a/spec/models/form/lettings/questions/uprn_spec.rb b/spec/models/form/lettings/questions/uprn_spec.rb new file mode 100644 index 000000000..8f6ba047a --- /dev/null +++ b/spec/models/form/lettings/questions/uprn_spec.rb @@ -0,0 +1,92 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::Uprn, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("uprn") + end + + it "has the correct header" do + expect(question.header).to eq("What is the property's UPRN") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("UPRN") + end + + it "has the correct type" do + expect(question.type).to eq("text") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct question_number" do + expect(question.question_number).to eq(11) + end + + it "has the correct hint" do + expect(question.hint_text).to eq("The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.") + end + + it "has the correct unanswered_error_message" do + expect(question.unanswered_error_message).to eq("UPRN must be 12 digits or less") + end + + describe "get_extra_check_answer_value" do + context "when address is not present" do + let(:log) { create(:lettings_log) } + + it "returns nil" do + expect(question.get_extra_check_answer_value(log)).to be_nil + end + end + + context "when address is present" do + let(:log) do + create( + :lettings_log, + address_line1: "1, Test Street", + town_or_city: "Test Town", + county: "Test County", + postcode_full: "AA1 1AA", + la: "E09000003", + ) + end + + it "returns formatted value" do + expect(question.get_extra_check_answer_value(log)).to eq( + "\n\n1, Test Street\nTest Town\nTest County\nAA1 1AA\nWestminster", + ) + end + end + end + + describe "has the correct hidden_in_check_answers" do + context "when uprn_known == 1" do + let(:log) { create(:lettings_log, uprn_known: 1) } + + it "returns false" do + expect(question.hidden_in_check_answers?(log)).to eq(false) + end + end + + context "when uprn_known != 1" do + let(:log) { create(:lettings_log, uprn_known: 0) } + + it "returns false" do + expect(question.hidden_in_check_answers?(log)).to eq(true) + end + end + end +end diff --git a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb index 2c4310d5b..8dd4f88a3 100644 --- a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb +++ b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb @@ -25,6 +25,7 @@ RSpec.describe Form::Lettings::Subsections::IncomeAndBenefits, type: :model do care_home_bi_weekly care_home_4_weekly care_home_monthly + care_home_charges_value_check rent_weekly rent_bi_weekly rent_4_weekly diff --git a/spec/models/form/lettings/subsections/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb index 227773487..2e7e58deb 100644 --- a/spec/models/form/lettings/subsections/property_information_spec.rb +++ b/spec/models/form/lettings/subsections/property_information_spec.rb @@ -1,38 +1,75 @@ require "rails_helper" RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do - subject(:property_information) { described_class.new(subsection_id, subsection_definition, section) } + subject(:property_information) { described_class.new(nil, nil, section) } - let(:subsection_id) { nil } - let(:subsection_definition) { nil } let(:section) { instance_double(Form::Lettings::Sections::TenancyAndProperty) } it "has correct section" do expect(property_information.section).to eq(section) end - it "has correct pages" do - expect(property_information.pages.map(&:id)).to eq( - %w[ - property_postcode - property_local_authority - first_time_property_let_as_social_housing - property_let_type - property_vacancy_reason_not_first_let - property_vacancy_reason_first_let - property_number_of_times_relet_not_social_let - property_number_of_times_relet_social_let - property_unit_type - property_building_type - property_wheelchair_accessible - property_number_of_bedrooms - void_or_renewal_date - void_date_value_check - new_build_handover_date - property_major_repairs - property_major_repairs_value_check - ], - ) + describe "pages" do + let(:section) { instance_double(Form::Sales::Sections::Household, form: instance_double(Form, start_date:)) } + + context "when 2022" do + let(:start_date) { Time.utc(2022, 2, 8) } + + it "has correct pages" do + expect(property_information.pages.compact.map(&:id)).to eq( + %w[ + property_postcode + property_local_authority + first_time_property_let_as_social_housing + property_let_type + property_vacancy_reason_not_first_let + property_vacancy_reason_first_let + property_number_of_times_relet_not_social_let + property_number_of_times_relet_social_let + property_unit_type + property_building_type + property_wheelchair_accessible + property_number_of_bedrooms + void_or_renewal_date + void_date_value_check + new_build_handover_date + property_major_repairs + property_major_repairs_value_check + ], + ) + end + end + + context "when 2023" do + let(:start_date) { Time.utc(2023, 2, 8) } + + it "has correct pages" do + expect(property_information.pages.map(&:id)).to eq( + %w[ + uprn_known + uprn + uprn_confirmation + address + property_local_authority + first_time_property_let_as_social_housing + property_let_type + property_vacancy_reason_not_first_let + property_vacancy_reason_first_let + property_number_of_times_relet_not_social_let + property_number_of_times_relet_social_let + property_unit_type + property_building_type + property_wheelchair_accessible + property_number_of_bedrooms + void_or_renewal_date + void_date_value_check + new_build_handover_date + property_major_repairs + property_major_repairs_value_check + ], + ) + end + end end it "has the correct id" do @@ -44,10 +81,6 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do end it "has the correct depends_on" do - expect(property_information.depends_on).to eq([ - { - "non_location_setup_questions_completed?" => true, - }, - ]) + expect(property_information.depends_on).to eq([{ "non_location_setup_questions_completed?" => true }]) end end diff --git a/spec/models/form/sales/pages/address_spec.rb b/spec/models/form/sales/pages/address_spec.rb index d6979b6b4..43a054a1e 100644 --- a/spec/models/form/sales/pages/address_spec.rb +++ b/spec/models/form/sales/pages/address_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Form::Sales::Pages::Address, type: :model do end it "has the correct header" do - expect(page.header).to eq("What is the property's address?") + expect(page.header).to eq("Q15 - What is the property's address?") end it "has the correct description" do 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 new file mode 100644 index 000000000..ddd4bc33c --- /dev/null +++ b/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb @@ -0,0 +1,52 @@ +require "rails_helper" + +RSpec.describe Form::Sales::Pages::DiscountedSaleValueCheck, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection, index) } + + let(:page_id) { "discounted_sale_value_check" } + let(:page_definition) { nil } + let(:index) { 1 } + let(:subsection) { instance_double(Form::Subsection) } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[discounted_sale_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("discounted_sale_value_check") + end + + it "has the correct header" do + expect(page.header).to be_nil + end + + it "has the correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.discounted_sale_value.title_text", + "arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }], + }) + end + + it "has the correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.discounted_sale_value.informative_text", + "arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }], + }) + end + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([ + { + "discounted_ownership_value_invalid?" => true, + }, + ]) + end +end diff --git a/spec/models/form/sales/pages/mortgage_amount_spec.rb b/spec/models/form/sales/pages/mortgage_amount_spec.rb index 551788fbb..c6f6f924e 100644 --- a/spec/models/form/sales/pages/mortgage_amount_spec.rb +++ b/spec/models/form/sales/pages/mortgage_amount_spec.rb @@ -28,8 +28,6 @@ RSpec.describe Form::Sales::Pages::MortgageAmount, type: :model do end it "has correct depends_on" do - expect(page.depends_on).to eq([{ - "mortgageused" => 1, - }]) + expect(page.depends_on).to eq([{ "mortgage_used?" => true }]) end end diff --git a/spec/models/form/sales/pages/number_of_others_in_property_spec.rb b/spec/models/form/sales/pages/number_of_others_in_property_spec.rb index 3503a1b9f..9a0adaafb 100644 --- a/spec/models/form/sales/pages/number_of_others_in_property_spec.rb +++ b/spec/models/form/sales/pages/number_of_others_in_property_spec.rb @@ -32,11 +32,11 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do expect(page.depends_on).to eq([ { "privacynotice" => 1, - "jointpur" => 2, + "joint_purchase?" => joint_purchase, }, { - "noint" => 1, - "jointpur" => 2, + "buyer_not_interviewed?" => true, + "joint_purchase?" => joint_purchase, }, ]) end @@ -53,11 +53,11 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do expect(page.depends_on).to eq([ { "privacynotice" => 1, - "jointpur" => 1, + "joint_purchase?" => joint_purchase, }, { - "noint" => 1, - "jointpur" => 1, + "buyer_not_interviewed?" => true, + "joint_purchase?" => joint_purchase, }, ]) end diff --git a/spec/models/form/sales/questions/address_line1_spec.rb b/spec/models/form/sales/questions/address_line1_spec.rb index bc65c0646..f037f41cd 100644 --- a/spec/models/form/sales/questions/address_line1_spec.rb +++ b/spec/models/form/sales/questions/address_line1_spec.rb @@ -11,6 +11,10 @@ RSpec.describe Form::Sales::Questions::AddressLine1, type: :model do expect(question.page).to eq(page) end + it "has the correct question_number" do + expect(question.question_number).to be_nil + end + it "has the correct id" do expect(question.id).to eq("address_line1") end @@ -20,7 +24,7 @@ RSpec.describe Form::Sales::Questions::AddressLine1, type: :model do end it "has the correct check_answer_label" do - expect(question.check_answer_label).to eq("Address") + expect(question.check_answer_label).to eq("Q15 - Address") end it "has the correct type" do diff --git a/spec/models/form/sales/questions/buyer1_ethnic_background_black_spec.rb b/spec/models/form/sales/questions/buyer1_ethnic_background_black_spec.rb index c4b7919c8..2722abf5b 100644 --- a/spec/models/form/sales/questions/buyer1_ethnic_background_black_spec.rb +++ b/spec/models/form/sales/questions/buyer1_ethnic_background_black_spec.rb @@ -39,7 +39,7 @@ RSpec.describe Form::Sales::Questions::Buyer1EthnicBackgroundBlack, type: :model expect(question.answer_options).to eq({ "12" => { "value" => "Caribbean" }, "13" => { "value" => "African" }, - "14" => { "value" => "Any other Black, African or Caribbean background" }, + "14" => { "value" => "Any other Black, African, Caribbean or Black British background" }, }) end diff --git a/spec/models/form/sales/questions/buyer2_ethnic_background_black_spec.rb b/spec/models/form/sales/questions/buyer2_ethnic_background_black_spec.rb index db5cbba0d..873d43069 100644 --- a/spec/models/form/sales/questions/buyer2_ethnic_background_black_spec.rb +++ b/spec/models/form/sales/questions/buyer2_ethnic_background_black_spec.rb @@ -39,7 +39,7 @@ RSpec.describe Form::Sales::Questions::Buyer2EthnicBackgroundBlack, type: :model expect(question.answer_options).to eq({ "12" => { "value" => "Caribbean" }, "13" => { "value" => "African" }, - "14" => { "value" => "Any other Black, African or Caribbean background" }, + "14" => { "value" => "Any other Black, African, Caribbean or Black British background" }, }) end diff --git a/spec/models/form/sales/questions/discounted_sale_value_check_spec.rb b/spec/models/form/sales/questions/discounted_sale_value_check_spec.rb new file mode 100644 index 000000000..8e9e4e7a7 --- /dev/null +++ b/spec/models/form/sales/questions/discounted_sale_value_check_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +RSpec.describe Form::Sales::Questions::DiscountedSaleValueCheck, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("discounted_sale_value_check") + end + + it "has the correct header" do + expect(question.header).to eq("Are you sure this is correct?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Discounted sale value confirmation") + end + + it "has the correct type" do + expect(question.type).to eq("interruption_screen") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "0" => { "value" => "Yes" }, + "1" => { "value" => "No" }, + }) + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers).to eq({ + "depends_on" => [ + { + "discounted_sale_value_check" => 0, + }, + { + "discounted_sale_value_check" => 1, + }, + ], + }) + end +end diff --git a/spec/models/form/sales/questions/mortgage_amount_spec.rb b/spec/models/form/sales/questions/mortgage_amount_spec.rb index 328406ecd..758101867 100644 --- a/spec/models/form/sales/questions/mortgage_amount_spec.rb +++ b/spec/models/form/sales/questions/mortgage_amount_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Form::Sales::Questions::MortgageAmount, type: :model do let(:page) { instance_double(Form::Page) } it "has correct page" do - expect(question.page).to eq(page) + expect(question.page).to be(page) end it "has the correct id" do @@ -36,7 +36,7 @@ RSpec.describe Form::Sales::Questions::MortgageAmount, type: :model do end it "has correct width" do - expect(question.width).to eq(5) + expect(question.width).to be(5) end it "has correct prefix" do @@ -44,6 +44,6 @@ RSpec.describe Form::Sales::Questions::MortgageAmount, type: :model do end it "has correct min" do - expect(question.min).to eq(0) + expect(question.min).to be(1) end end diff --git a/spec/models/form/sales/questions/mortgage_lender_spec.rb b/spec/models/form/sales/questions/mortgage_lender_spec.rb index 84caef701..811746dbe 100644 --- a/spec/models/form/sales/questions/mortgage_lender_spec.rb +++ b/spec/models/form/sales/questions/mortgage_lender_spec.rb @@ -42,6 +42,53 @@ RSpec.describe Form::Sales::Questions::MortgageLender, type: :model do it "has the correct answer_options" do expect(question.answer_options).to eq({ + "" => "Select an option", + "0" => "Don’t know", + "1" => "Atom Bank", + "2" => "Barclays Bank PLC", + "3" => "Bath Building Society", + "4" => "Buckinghamshire Building Society", + "5" => "Cambridge Building Society", + "6" => "Coventry Building Society", + "7" => "Cumberland Building Society", + "8" => "Darlington Building Society", + "9" => "Dudley Building Society", + "10" => "Ecology Building Society", + "11" => "Halifax", + "12" => "Hanley Economic Building Society", + "13" => "Hinckley and Rugby Building Society", + "14" => "Holmesdale Building Society", + "15" => "Ipswich Building Society", + "16" => "Leeds Building Society", + "17" => "Lloyds Bank", + "18" => "Mansfield Building Society", + "19" => "Market Harborough Building Society", + "20" => "Melton Mowbray Building Society", + "21" => "Nationwide Building Society", + "22" => "Natwest", + "23" => "Nedbank Private Wealth", + "24" => "Newbury Building Society", + "25" => "OneSavings Bank", + "26" => "Parity Trust", + "27" => "Penrith Building Society", + "28" => "Pepper Homeloans", + "29" => "Royal Bank of Scotland", + "30" => "Santander", + "31" => "Skipton Building Society", + "32" => "Teachers Building Society", + "33" => "The Co-operative Bank", + "34" => "Tipton & Coseley Building Society", + "35" => "TSB", + "36" => "Ulster Bank", + "37" => "Virgin Money", + "38" => "West Bromwich Building Society", + "39" => "Yorkshire Building Society", + "40" => "Other", + }) + end + + it "has the correct displayed_answer_options" do + expect(question.displayed_answer_options(nil, nil)).to eq({ "" => "Select an option", "1" => "Atom Bank", "2" => "Barclays Bank PLC", diff --git a/spec/models/form/sales/questions/number_of_others_in_property_spec.rb b/spec/models/form/sales/questions/number_of_others_in_property_spec.rb index 2bb50f80b..3d6e9d9c5 100644 --- a/spec/models/form/sales/questions/number_of_others_in_property_spec.rb +++ b/spec/models/form/sales/questions/number_of_others_in_property_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do let(:joint_purchase) { true } it "has correct page" do - expect(question.page).to eq(page) + expect(question.page).to be(page) end it "has the correct id" do @@ -17,7 +17,7 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do end it "has the correct header" do - expect(question.header).to eq("Besides the buyer(s), how many other people live or will live in the property?") + expect(question.header).to eq("Besides the buyers, how many other people live or will live in the property?") end it "has the correct check_answer_label" do @@ -37,11 +37,11 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do end it "has the correct min" do - expect(question.min).to eq(0) + expect(question.min).to be 0 end it "has the correct max" do - expect(question.max).to eq(4) + expect(question.max).to be 15 end context "with non joint purchase" do @@ -51,8 +51,8 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do expect(question.hint_text).to eq("You can provide details for a maximum of 5 other people if there is only one buyer.") end - it "has the correct max" do - expect(question.max).to eq(5) + it "has the correct header" do + expect(question.header).to eq("Besides the buyer, how many other people live or will live in the property?") end end end diff --git a/spec/models/form/sales/questions/uprn_known_spec.rb b/spec/models/form/sales/questions/uprn_known_spec.rb index 528e60a1f..457471568 100644 --- a/spec/models/form/sales/questions/uprn_known_spec.rb +++ b/spec/models/form/sales/questions/uprn_known_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Form::Sales::Questions::UprnKnown, type: :model do end it "has the correct header" do - expect(question.header).to eq("Do you know the property UPRN?") + expect(question.header).to eq("Do you know the property's UPRN?") end it "has the correct check_answer_label" do diff --git a/spec/models/form/sales/questions/uprn_spec.rb b/spec/models/form/sales/questions/uprn_spec.rb index 2f42c1cdd..50e575445 100644 --- a/spec/models/form/sales/questions/uprn_spec.rb +++ b/spec/models/form/sales/questions/uprn_spec.rb @@ -31,6 +31,10 @@ RSpec.describe Form::Sales::Questions::Uprn, type: :model do expect(question.derived?).to be false end + it "has the correct question_number" do + expect(question.question_number).to eq(14) + end + it "has the correct hint" do expect(question.hint_text).to eq("The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.") end diff --git a/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb b/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb index b6947661d..5c0dbfea0 100644 --- a/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb +++ b/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb @@ -20,12 +20,15 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model about_price_not_rtb grant_value_check purchase_price_discounted_ownership + discounted_sale_grant_value_check about_price_discounted_ownership_value_check discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount mortgage_used_discounted_ownership discounted_ownership_mortgage_used_mortgage_value_check + discounted_sale_mortgage_used_value_check mortgage_amount_discounted_ownership discounted_ownership_mortgage_amount_mortgage_value_check + discounted_sale_mortgage_value_check extra_borrowing_mortgage_value_check discounted_ownership_deposit_and_mortgage_value_check_after_mortgage mortgage_lender_discounted_ownership @@ -37,6 +40,7 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model extra_borrowing_deposit_value_check discounted_ownership_deposit_value_check discounted_ownership_deposit_and_mortgage_value_check_after_deposit + discounted_sale_deposit_value_check leasehold_charges_discounted_ownership monthly_charges_discounted_ownership_value_check ], diff --git a/spec/models/form/sales/subsections/setup_spec.rb b/spec/models/form/sales/subsections/setup_spec.rb index 779b9537e..92271ba25 100644 --- a/spec/models/form/sales/subsections/setup_spec.rb +++ b/spec/models/form/sales/subsections/setup_spec.rb @@ -25,6 +25,7 @@ RSpec.describe Form::Sales::Subsections::Setup, type: :model do outright_ownership_type ownership_type_old_persons_shared_ownership_value_check monthly_charges_type_value_check + discounted_sale_type_value_check buyer_company buyer_live joint_purchase diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index 417da6639..ec2ddbecc 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -9,8 +9,6 @@ RSpec.describe FormHandler do Singleton.__init__(described_class) example.run end - Timecop.return - Singleton.__init__(described_class) end context "when accessing a form in a different year" do @@ -35,6 +33,15 @@ RSpec.describe FormHandler do expect(all_forms.count).to be >= 1 expect(all_forms["current_sales"]).to be_a(Form) end + + context "when in 23/24 period or later" do + let(:now) { Time.utc(2023, 6, 7) } + + it "does not load outdated forms" do + all_forms = form_handler.forms + expect(all_forms.keys).not_to include nil + end + end end describe "Get specific form" do diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index cac779e33..a1cf650c0 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -183,6 +183,26 @@ RSpec.describe Form, type: :model do expect(form.next_incomplete_section_redirect_path(subsection, lettings_log)).to eq("declaration") end end + + context "when no pages or questions in the next subsection are routed to" do + let(:subsection) { form.get_subsection("setup") } + + around do |example| + FormHandler.instance.use_real_forms! + + example.run + + FormHandler.instance.use_fake_forms! + end + + it "finds the path to the section after" do + lettings_log.startdate = Time.zone.local(2022, 9, 1) + lettings_log.renewal = 1 + lettings_log.needstype = 2 + lettings_log.postcode_known = 0 + expect(form.next_incomplete_section_redirect_path(subsection, lettings_log)).to eq("joint") + end + end end describe "invalidated_page_questions" do @@ -227,12 +247,12 @@ RSpec.describe Form, type: :model do expect(form.sections[0].class).to eq(Form::Sales::Sections::Setup) expect(form.subsections.count).to eq(1) expect(form.subsections.first.id).to eq("setup") - expect(form.pages.count).to eq(15) + expect(form.pages.count).to eq(16) expect(form.pages.first.id).to eq("organisation") - expect(form.questions.count).to eq(16) + expect(form.questions.count).to eq(17) expect(form.questions.first.id).to eq("owning_organisation_id") expect(form.start_date).to eq(Time.zone.parse("2022-04-01")) - expect(form.end_date).to eq(Time.zone.parse("2023-07-07")) + expect(form.end_date).to eq(Time.zone.parse("2023-06-07")) expect(form.unresolved_log_redirect_page_id).to eq(nil) end diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb index 57b5de21a..9a8666eea 100644 --- a/spec/models/lettings_log_spec.rb +++ b/spec/models/lettings_log_spec.rb @@ -1,6 +1,7 @@ require "rails_helper" require "shared/shared_examples_for_derived_fields" +# rubocop:disable RSpec/AnyInstance RSpec.describe LettingsLog do let(:different_managing_organisation) { create(:organisation) } let(:created_by_user) { create(:user) } @@ -2235,6 +2236,7 @@ RSpec.describe LettingsLog do first_time_property_let_as_social_housing tenancycode propcode + chcharge tenancylength ]) end @@ -2248,6 +2250,7 @@ RSpec.describe LettingsLog do first_time_property_let_as_social_housing tenancycode propcode + chcharge tenancylength address_line2 county @@ -3008,4 +3011,60 @@ RSpec.describe LettingsLog do end end end + + describe "#process_uprn_change!" do + context "when UPRN set to a value" do + let(:lettings_log) do + create( + :lettings_log, + uprn: "123456789", + uprn_confirmed: 1, + county: "county", + ) + end + + it "updates sales log fields" do + lettings_log.uprn = "1111111" + + allow_any_instance_of(UprnClient).to receive(:call) + allow_any_instance_of(UprnClient).to receive(:result).and_return({ + "UPRN" => "UPRN", + "UDPRN" => "UDPRN", + "ADDRESS" => "full address", + "SUB_BUILDING_NAME" => "0", + "BUILDING_NAME" => "building name", + "THOROUGHFARE_NAME" => "thoroughfare", + "POST_TOWN" => "posttown", + "POSTCODE" => "postcode", + }) + + expect { lettings_log.process_uprn_change! }.to change(lettings_log, :address_line1).from(nil).to("0, Building Name, Thoroughfare") + .and change(lettings_log, :town_or_city).from(nil).to("Posttown") + .and change(lettings_log, :postcode_full).from(nil).to("POSTCODE") + .and change(lettings_log, :uprn_confirmed).from(1).to(nil) + .and change(lettings_log, :county).from("county").to(nil) + end + end + + context "when UPRN nil" do + let(:lettings_log) { create(:lettings_log, uprn: nil) } + + it "does not update sales log" do + expect { lettings_log.process_uprn_change! }.not_to change(lettings_log, :attributes) + end + end + + context "when service errors" do + let(:lettings_log) { create(:lettings_log, uprn: "123456789", uprn_confirmed: 1) } + let(:error_message) { "error" } + + it "adds error to sales log" do + allow_any_instance_of(UprnClient).to receive(:call) + allow_any_instance_of(UprnClient).to receive(:error).and_return(error_message) + + expect { lettings_log.process_uprn_change! }.to change { lettings_log.errors[:uprn] }.from([]).to([error_message]) + end + end + end end +# rubocop:enable RSpec/AnyInstance diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb index 890fa069f..511f1820b 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -59,8 +59,8 @@ RSpec.describe SalesLog, type: :model do purchid monthly_charges_value_check old_persons_shared_ownership_value_check - mortgagelender othtype + discounted_sale_value_check proplen mortlen frombeds @@ -77,8 +77,8 @@ RSpec.describe SalesLog, type: :model do purchid monthly_charges_value_check old_persons_shared_ownership_value_check - mortgagelender othtype + discounted_sale_value_check address_line2 county postcode_full @@ -302,7 +302,7 @@ RSpec.describe SalesLog, type: :model do WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/CA101AA/) .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Eden","codes":{"admin_district":"E07000030"}}}', headers: {}) - Timecop.freeze(2023, 4, 1) + Timecop.freeze(2023, 5, 2) Singleton.__init__(FormHandler) end @@ -517,7 +517,14 @@ RSpec.describe SalesLog, type: :model do describe "#process_uprn_change!" do context "when UPRN set to a value" do - let(:sales_log) { create(:sales_log, uprn: "123456789", uprn_confirmed: 1) } + let(:sales_log) do + create( + :sales_log, + uprn: "123456789", + uprn_confirmed: 1, + county: "county", + ) + end it "updates sales log fields" do sales_log.uprn = "1111111" @@ -538,6 +545,7 @@ RSpec.describe SalesLog, type: :model do .and change(sales_log, :town_or_city).from(nil).to("Posttown") .and change(sales_log, :postcode_full).from(nil).to("POSTCODE") .and change(sales_log, :uprn_confirmed).from(1).to(nil) + .and change(sales_log, :county).from("county").to(nil) end end diff --git a/spec/models/scheme_spec.rb b/spec/models/scheme_spec.rb index f59fe56c5..db824d7cd 100644 --- a/spec/models/scheme_spec.rb +++ b/spec/models/scheme_spec.rb @@ -96,6 +96,7 @@ RSpec.describe Scheme, type: :model do let(:scheme) { FactoryBot.build(:scheme) } before do + FactoryBot.create(:location, scheme:) Timecop.freeze(2022, 6, 7) end diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb index cd6e38f50..18912b1c8 100644 --- a/spec/models/validations/date_validations_spec.rb +++ b/spec/models/validations/date_validations_spec.rb @@ -21,14 +21,6 @@ RSpec.describe Validations::DateValidations do expect(record.errors["startdate"]).to be_empty end - it "validates that the tenancy start date is before the end date of the chosen scheme if it has an end date" do - record.startdate = Time.zone.today - 3.days - record.scheme = scheme - date_validator.validate_startdate(record) - expect(record.errors["startdate"]) - .to include(match I18n.t("validations.setup.startdate.before_scheme_end_date")) - end - it "validates that the tenancy start date is after the void date if it has a void date" do record.startdate = Time.zone.local(2022, 1, 1) record.voiddate = Time.zone.local(2022, 2, 1) @@ -173,6 +165,7 @@ RSpec.describe Validations::DateValidations do let(:scheme) { create(:scheme) } before do + FactoryBot.create(:location, scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:) scheme.reload end @@ -197,6 +190,7 @@ RSpec.describe Validations::DateValidations do let(:scheme) { create(:scheme) } before do + FactoryBot.create(:location, scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 2), reactivation_date: Time.zone.local(2022, 8, 3), scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 1), reactivation_date: Time.zone.local(2022, 9, 4), scheme:) diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb index c2fe3b963..8cb777029 100644 --- a/spec/models/validations/financial_validations_spec.rb +++ b/spec/models/validations/financial_validations_spec.rb @@ -263,15 +263,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 56 }, + charge: { field: "scharge", value: 156 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 300 }, + charge: { field: "scharge", value: 672 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 111 }, + charge: { field: "scharge", value: 311 }, }, { period: { label: "weekly", value: 1 }, @@ -308,15 +308,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 54 }, + charge: { field: "scharge", value: 154 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 220 }, + charge: { field: "scharge", value: 670 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 109 }, + charge: { field: "scharge", value: 309 }, }, { period: { label: "weekly", value: 1 }, @@ -357,15 +357,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 281 }, + charge: { field: "scharge", value: 481 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 1225 }, + charge: { field: "scharge", value: 2081 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 561 }, + charge: { field: "scharge", value: 961 }, }, { period: { label: "weekly", value: 1 }, @@ -402,15 +402,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 280 }, + charge: { field: "scharge", value: 366 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 1200 }, + charge: { field: "scharge", value: 1582 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 559 }, + charge: { field: "scharge", value: 731 }, }, { period: { label: "weekly", value: 1 }, @@ -455,15 +455,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 46 }, + charge: { field: "scharge", value: 156 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 200 }, + charge: { field: "scharge", value: 672 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 91 }, + charge: { field: "scharge", value: 311 }, }, { period: { label: "weekly", value: 1 }, @@ -549,15 +549,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 165.90 }, + charge: { field: "scharge", value: 365.90 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 750 }, + charge: { field: "scharge", value: 2081 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 330.50 }, + charge: { field: "scharge", value: 961 }, }, { period: { label: "weekly", value: 1 }, @@ -617,15 +617,15 @@ RSpec.describe Validations::FinancialValidations do [{ period: { label: "weekly", value: 1 }, - charge: { field: "scharge", value: 120.88 }, + charge: { field: "scharge", value: 364.88 }, }, { period: { label: "monthly", value: 4 }, - charge: { field: "scharge", value: 608 }, + charge: { field: "scharge", value: 1200 }, }, { period: { label: "every 2 weeks", value: 2 }, - charge: { field: "scharge", value: 329.99 }, + charge: { field: "scharge", value: 700.99 }, }, { period: { label: "weekly", value: 1 }, @@ -788,7 +788,7 @@ RSpec.describe Validations::FinancialValidations do LaRentRange.create!( ranges_rent_id: "1", la: "E07000223", - beds: 1, + beds: 4, lettype: 1, soft_min: 12.41, soft_max: 89.54, @@ -814,7 +814,7 @@ RSpec.describe Validations::FinancialValidations do record.lettype = 1 record.period = 1 record.la = "E07000223" - record.beds = 1 + record.beds = 4 record.startdate = Time.zone.local(2021, 9, 17) record.brent = 9.17 @@ -846,7 +846,7 @@ RSpec.describe Validations::FinancialValidations do record.lettype = 1 record.period = 1 record.la = "E07000223" - record.beds = 1 + record.beds = 4 record.startdate = Time.zone.local(2021, 9, 17) record.brent = 200 @@ -883,7 +883,7 @@ RSpec.describe Validations::FinancialValidations do record.period = 1 record.la = "E07000223" record.startdate = Time.zone.local(2022, 2, 5) - record.beds = 1 + record.beds = 4 record.brent = 200 financial_validator.validate_rent_amount(record) diff --git a/spec/models/validations/household_validations_spec.rb b/spec/models/validations/household_validations_spec.rb index daa3feef1..e1837a43d 100644 --- a/spec/models/validations/household_validations_spec.rb +++ b/spec/models/validations/household_validations_spec.rb @@ -60,73 +60,6 @@ RSpec.describe Validations::HouseholdValidations do end end - describe "pregnancy validations" do - context "when there are no female tenants" do - it "validates that pregnancy can be yes" do - record.preg_occ = 1 - record.sex1 = "M" - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]).to be_empty - end - - it "validates that pregnancy can be prefer not to say" do - record.preg_occ = 3 - record.sex1 = "M" - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]).to be_empty - end - end - - context "when there are female tenants" do - context "but they are older than 65" do - before { record.assign_attributes(sex1: "F", age1: 66, preg_occ: 1) } - - it "validates that pregnancy cannot be yes" do - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]) - .to include(match I18n.t("validations.household.preg_occ.no_female")) - end - end - - context "and they are the lead tenant and under 65" do - before { record.assign_attributes(sex1: "F", age1: 64, preg_occ: 1) } - - it "allows pregnancy to be set to yes" do - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]).to be_empty - end - end - - context "and they are another household member and under 51" do - before { record.assign_attributes(sex1: "M", age1: 25, sex3: "F", age3: 64, preg_occ: 1) } - - it "allows pregnancy to be set to yes" do - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]).to be_empty - end - end - - context "and they are another household member and under 11" do - before { record.assign_attributes(sex1: "M", age1: 25, sex3: "F", age3: 10, preg_occ: 1) } - - it "validates that pregnancy cannot be yes" do - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]) - .to include(match I18n.t("validations.household.preg_occ.no_female")) - end - end - - context "and one tenant's age is unknown" do - before { record.assign_attributes(sex1: "F", age1: nil, age1_known: 1, preg_occ: 1) } - - it "allows pregnancy to be set to yes" do - household_validator.validate_pregnancy(record) - expect(record.errors["preg_occ"]).to be_empty - end - end - end - end - describe "reason for leaving last settled home validations" do let(:field) { "validations.other_field_not_required" } let(:main_field_label) { "reason" } diff --git a/spec/models/validations/sales/financial_validations_spec.rb b/spec/models/validations/sales/financial_validations_spec.rb index b60ef5e6a..e1eb81dea 100644 --- a/spec/models/validations/sales/financial_validations_spec.rb +++ b/spec/models/validations/sales/financial_validations_spec.rb @@ -113,6 +113,24 @@ RSpec.describe Validations::Sales::FinancialValidations do end end + describe "#validate_mortgage" do + let(:record) { FactoryBot.create(:sales_log) } + + it "adds an error is the mortgage is zero" do + record.mortgageused = 1 + record.mortgage = 0 + financial_validator.validate_mortgage(record) + expect(record.errors[:mortgage]).to include I18n.t("validations.financial.mortgage") + end + + it "does not add an error is the mortgage is positive" do + record.mortgageused = 1 + record.mortgage = 234 + financial_validator.validate_mortgage(record) + expect(record.errors).to be_empty + end + end + describe "#validate_cash_discount" do let(:record) { FactoryBot.create(:sales_log) } diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index fb9500956..3a8944e79 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -115,10 +115,10 @@ RSpec.describe Validations::Sales::SaleInformationValidations do sale_information_validator.validate_exchange_date(record) expect(record.errors[:exdate]).to eq( - ["Contract exchange date must be less than 1 year before completion date"], + ["Contract exchange date must be less than 1 year before sale completion date"], ) expect(record.errors[:saledate]).to eq( - ["Completion date must be less than 1 year after contract exchange date"], + ["Sale completion date must be less than 1 year after contract exchange date"], ) end end @@ -130,10 +130,10 @@ RSpec.describe Validations::Sales::SaleInformationValidations do sale_information_validator.validate_exchange_date(record) expect(record.errors[:exdate]).to eq( - ["Contract exchange date must be before completion date"], + ["Contract exchange date must be before sale completion date"], ) expect(record.errors[:saledate]).to eq( - ["Completion date must be after contract exchange date"], + ["Sale completion date must be after contract exchange date"], ) end end @@ -226,112 +226,133 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end describe "#validate_discounted_ownership_value" do - context "when grant is routed to" do - let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8) } + context "when sale is on or after 24/25 collection window" do + context "when grant is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8, saledate: Time.zone.local(2024, 4, 3)) } - context "and not provided" do - before do - record.grant = nil - end + context "and not provided" do + before do + record.grant = nil + end - it "does not add an error" do - sale_information_validator.validate_discounted_ownership_value(record) + it "does not add an error" do + sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors).to be_empty + expect(record.errors).to be_empty + end end - end - context "and is provided" do - it "adds an error if mortgage, deposit and grant total does not equal market value" do - record.grant = 3_000 - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - end - - it "does not add an error if mortgage, deposit and grant total equals market value" do - record.grant = 15_000 - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors).to be_empty + context "and is provided" do + it "adds an error if mortgage, deposit and grant total does not equal market value" do + record.grant = 3_000 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + end + + it "does not add an error if mortgage, deposit and grant total equals market value" do + record.grant = 15_000 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors).to be_empty + end end end - end - context "when discount is routed to" do - let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9) } + context "when discount is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9, saledate: Time.zone.local(2024, 4, 3)) } - context "and not provided" do - before do - record.discount = nil - end + context "and not provided" do + before do + record.discount = nil + end - it "does not add an error" do - sale_information_validator.validate_discounted_ownership_value(record) + it "does not add an error" do + sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors).to be_empty + expect(record.errors).to be_empty + end + end + + context "and is provided" do + it "adds an error if mortgage and deposit total does not equal market value - discount" do + record.discount = 10 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + end + + it "does not add an error if mortgage and deposit total equals market value - discount" do + record.discount = 50 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors).to be_empty + end end end - context "and is provided" do - it "adds an error if mortgage and deposit total does not equal market value - discount" do - record.discount = 10 + context "when neither discount nor grant is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29, saledate: Time.zone.local(2024, 4, 3)) } + + it "adds an error if mortgage and deposit total does not equal market value" do + record.deposit = 2_000 sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) - expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) - expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) - expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) - expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) + expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) + expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) end - it "does not add an error if mortgage and deposit total equals market value - discount" do - record.discount = 50 + it "does not add an error if mortgage and deposit total equals market value" do + record.deposit = 20_000 sale_information_validator.validate_discounted_ownership_value(record) expect(record.errors).to be_empty end end - end - context "when neither discount nor grant is routed to" do - let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29) } + context "when mortgage is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2024, 4, 3)) } - it "adds an error if mortgage and deposit total does not equal market value" do - record.deposit = 2_000 - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) - end + context "and not provided" do + before do + record.mortgage = nil + end - it "does not add an error if mortgage and deposit total equals market value" do - record.deposit = 20_000 - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors).to be_empty - end - end + it "does not add an error" do + sale_information_validator.validate_discounted_ownership_value(record) - context "when mortgage is routed to" do - let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2) } - - context "and not provided" do - before do - record.mortgage = nil + expect(record.errors).to be_empty + end end - it "does not add an error" do - sale_information_validator.validate_discounted_ownership_value(record) - - expect(record.errors).to be_empty + context "and is provided" do + it "adds an error if mortgage, grant and deposit total does not equal market value - discount" do + record.mortgage = 10 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) + expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) + expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) + expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) + expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) + end + + it "does not add an error if mortgage, grant and deposit total equals market value - discount" do + record.mortgage = 10_000 + sale_information_validator.validate_discounted_ownership_value(record) + expect(record.errors).to be_empty + end end end - context "and is provided" do - it "adds an error if mortgage, grant and deposit total does not equal market value - discount" do - record.mortgage = 10 + context "when mortgage is not routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2024, 4, 3)) } + + it "adds an error if grant and deposit total does not equal market value - discount" do sale_information_validator.validate_discounted_ownership_value(record) expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) @@ -341,34 +362,25 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end it "does not add an error if mortgage, grant and deposit total equals market value - discount" do - record.mortgage = 10_000 + record.grant = 13_000 sale_information_validator.validate_discounted_ownership_value(record) expect(record.errors).to be_empty end end - end - context "when mortgage is not routed to" do - let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2) } + context "when ownership is not discounted" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1, saledate: Time.zone.local(2024, 4, 3)) } - it "adds an error if grant and deposit total does not equal market value - discount" do - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) - expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) - expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) - expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) - expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) - end + it "does not add an error" do + sale_information_validator.validate_discounted_ownership_value(record) - it "does not add an error if mortgage, grant and deposit total equals market value - discount" do - record.grant = 13_000 - sale_information_validator.validate_discounted_ownership_value(record) - expect(record.errors).to be_empty + expect(record.errors).to be_empty + end end end - context "when ownership is not discounted" do - let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1) } + context "when sale is before 24/25 collection" do + let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 4)) } it "does not add an error" do sale_information_validator.validate_discounted_ownership_value(record) diff --git a/spec/models/validations/sales/setup_validations_spec.rb b/spec/models/validations/sales/setup_validations_spec.rb index 136e239d3..a85177aab 100644 --- a/spec/models/validations/sales/setup_validations_spec.rb +++ b/spec/models/validations/sales/setup_validations_spec.rb @@ -5,13 +5,13 @@ RSpec.describe Validations::Sales::SetupValidations do let(:validator_class) { Class.new { include Validations::Sales::SetupValidations } } - describe "#validate_saledate" do + describe "#validate_saledate_collection_year" do context "with sales_in_crossover_period == false" do context "when saledate is blank" do let(:record) { build(:sales_log, saledate: nil) } it "does not add an error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors).to be_empty end @@ -21,7 +21,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2023, 1, 1)) } it "does not add an error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors).to be_empty end @@ -31,7 +31,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 1, 1)) } it "adds error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023") end @@ -41,7 +41,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) } it "adds error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors[:saledate]).to include("Enter a date within the 22/23 collection year, which is between 1st April 2022 and 31st March 2023") end @@ -61,7 +61,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: nil) } it "does not add an error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors).to be_empty end @@ -71,7 +71,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 1, 1)) } it "does not add an error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors).to be_empty end @@ -81,7 +81,7 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2020, 5, 1)) } it "adds error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025") end @@ -91,11 +91,43 @@ RSpec.describe Validations::Sales::SetupValidations do let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 4, 1)) } it "adds error" do - setup_validator.validate_saledate(record) + setup_validator.validate_saledate_collection_year(record) expect(record.errors[:saledate]).to include("Enter a date within the 23/24 or 24/25 collection years, which is between 1st April 2023 and 31st March 2025") end end end end + + describe "#validate_saledate_two_weeks" do + context "when saledate is blank" do + let(:record) { build(:sales_log, saledate: nil) } + + it "does not add an error" do + setup_validator.validate_saledate_two_weeks(record) + + expect(record.errors).to be_empty + end + end + + context "when saledate is less than 14 days after today" do + let(:record) { build(:sales_log, saledate: Time.zone.today + 10.days) } + + it "does not add an error" do + setup_validator.validate_saledate_two_weeks(record) + + expect(record.errors).to be_empty + end + end + + context "when saledate is more than 14 days after today" do + let(:record) { build(:sales_log, saledate: Time.zone.today + 15.days) } + + it "adds an error" do + setup_validator.validate_saledate_two_weeks(record) + + expect(record.errors[:saledate]).to include("Sale completion date must not be later than 14 days from today’s date") + end + end + end end diff --git a/spec/models/validations/sales/soft_validations_spec.rb b/spec/models/validations/sales/soft_validations_spec.rb index dc8bbfedd..712e53965 100644 --- a/spec/models/validations/sales/soft_validations_spec.rb +++ b/spec/models/validations/sales/soft_validations_spec.rb @@ -798,4 +798,119 @@ RSpec.describe Validations::Sales::SoftValidations do expect(record).to be_person_3_student_not_child end end + + describe "#discounted_ownership_value_invalid?" do + context "when grant is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8, saledate: Time.zone.local(2023, 4, 3)) } + + context "and not provided" do + before do + record.grant = nil + end + + it "returns false" do + expect(record).not_to be_discounted_ownership_value_invalid + end + end + + context "and is provided" do + it "returns true if mortgage, deposit and grant total does not equal market value" do + record.grant = 3_000 + expect(record).to be_discounted_ownership_value_invalid + end + + it "returns false if mortgage, deposit and grant total equals market value" do + record.grant = 15_000 + expect(record).not_to be_discounted_ownership_value_invalid + end + end + end + + context "when discount is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9, saledate: Time.zone.local(2023, 4, 3)) } + + context "and not provided" do + before do + record.discount = nil + end + + it "returns false" do + expect(record).not_to be_discounted_ownership_value_invalid + end + end + + context "and is provided" do + it "returns true if mortgage and deposit total does not equal market value - discount" do + record.discount = 10 + expect(record).to be_discounted_ownership_value_invalid + end + + it "returns false if mortgage and deposit total equals market value - discount" do + record.discount = 50 + expect(record).not_to be_discounted_ownership_value_invalid + end + end + end + + context "when neither discount nor grant is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29, saledate: Time.zone.local(2023, 4, 3)) } + + it "returns true if mortgage and deposit total does not equal market value" do + record.deposit = 2_000 + expect(record).to be_discounted_ownership_value_invalid + end + + it "returns false if mortgage and deposit total equals market value" do + record.deposit = 20_000 + expect(record).not_to be_discounted_ownership_value_invalid + end + end + + context "when mortgage is routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 3)) } + + context "and not provided" do + before do + record.mortgage = nil + end + + it "returns false" do + expect(record).not_to be_discounted_ownership_value_invalid + end + end + + context "and is provided" do + it "returns true if mortgage, grant and deposit total does not equal market value - discount" do + record.mortgage = 10 + expect(record).to be_discounted_ownership_value_invalid + end + + it "returns false if mortgage, grant and deposit total equals market value - discount" do + record.mortgage = 10_000 + expect(record).not_to be_discounted_ownership_value_invalid + end + end + end + + context "when mortgage is not routed to" do + let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 3)) } + + it "returns true if grant and deposit total does not equal market value - discount" do + expect(record).to be_discounted_ownership_value_invalid + end + + it "returns false if mortgage, grant and deposit total equals market value - discount" do + record.grant = 13_000 + expect(record).not_to be_discounted_ownership_value_invalid + end + end + + context "when ownership is not discounted" do + let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1, saledate: Time.zone.local(2023, 4, 3)) } + + it "returns false" do + expect(record).not_to be_discounted_ownership_value_invalid + end + end + end end diff --git a/spec/models/validations/setup_validations_spec.rb b/spec/models/validations/setup_validations_spec.rb index 69e22f1e2..16d52fb07 100644 --- a/spec/models/validations/setup_validations_spec.rb +++ b/spec/models/validations/setup_validations_spec.rb @@ -188,6 +188,7 @@ RSpec.describe Validations::SetupValidations do let(:scheme) { create(:scheme, created_at: Time.zone.local(2022, 4, 1)) } before do + FactoryBot.create(:location, scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:) scheme.reload end @@ -212,6 +213,7 @@ RSpec.describe Validations::SetupValidations do let(:scheme) { create(:scheme, created_at: Time.zone.local(2022, 4, 1)) } before do + FactoryBot.create(:location, scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 2), reactivation_date: Time.zone.local(2022, 8, 3), scheme:) create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 1), reactivation_date: Time.zone.local(2022, 9, 4), scheme:) diff --git a/spec/models/validations/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb index 3ce2b4527..d355f2fbd 100644 --- a/spec/models/validations/soft_validations_spec.rb +++ b/spec/models/validations/soft_validations_spec.rb @@ -175,14 +175,21 @@ RSpec.describe Validations::SoftValidations do end end - context "when female tenants are in 11-16 age range" do + context "when there are no female tenants and age of other tenants is unknown" do + it "shows the interruption screen" do + record.update!(sex1: "M", preg_occ: 1, hhmemb: 1, age1_known: 1) + expect(record.no_females_in_a_pregnant_household?).to be true + end + end + + context "when female tenants are under 16" do it "shows the interruption screen" do record.update!(age2: 14, sex2: "F", preg_occ: 1, hhmemb: 2, details_known_2: 0, age2_known: 0, age1: 18, sex1: "M", age1_known: 0) expect(record.female_in_pregnant_household_in_soft_validation_range?).to be true end end - context "when female tenants are in 50-65 age range" do + context "when female tenants are over 50" do it "shows the interruption screen" do record.update!(age1: 54, sex1: "F", preg_occ: 1, hhmemb: 1, age1_known: 0) expect(record.female_in_pregnant_household_in_soft_validation_range?).to be true @@ -327,4 +334,38 @@ RSpec.describe Validations::SoftValidations do end end end + + describe "#care_home_charge_expected_not_provided?" do + it "returns false if is_carehome is 'No'" do + record.period = 3 + record.is_carehome = 0 + record.chcharge = nil + + expect(record).not_to be_care_home_charge_expected_not_provided + end + + it "returns false if is_carehome is not given" do + record.period = 3 + record.is_carehome = nil + record.chcharge = nil + + expect(record).not_to be_care_home_charge_expected_not_provided + end + + it "returns false if chcharge is given" do + record.period = 3 + record.is_carehome = 1 + record.chcharge = 40 + + expect(record).not_to be_care_home_charge_expected_not_provided + end + + it "returns true if is_carehome is 'Yes' and chcharge is not given" do + record.period = 3 + record.is_carehome = 1 + record.chcharge = nil + + expect(record).to be_care_home_charge_expected_not_provided + end + end end diff --git a/spec/requests/form_controller_spec.rb b/spec/requests/form_controller_spec.rb index 9dce39af2..9787ce097 100644 --- a/spec/requests/form_controller_spec.rb +++ b/spec/requests/form_controller_spec.rb @@ -632,10 +632,6 @@ RSpec.describe FormController, type: :request do } end - before do - allow(validator).to receive(:validate_pregnancy).and_return(true) - end - it "routes to the appropriate conditional page based on the question answer of the current page" do post "/lettings-logs/#{lettings_log.id}/form", params: lettings_log_form_conditional_question_yes_params expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}/conditional-question-yes-page") diff --git a/spec/requests/lettings_logs_controller_spec.rb b/spec/requests/lettings_logs_controller_spec.rb index 066cd1f35..b8e7f0f78 100644 --- a/spec/requests/lettings_logs_controller_spec.rb +++ b/spec/requests/lettings_logs_controller_spec.rb @@ -891,6 +891,38 @@ RSpec.describe LettingsLogsController, type: :request do end end + context "when a lettings log is for a renewal of supported housing, so property information does not need to show" do + let(:lettings_log) do + FactoryBot.create( + :lettings_log, + owning_organisation: user.organisation, + managing_organisation: user.organisation, + created_by: user, + startdate: Time.zone.now, + renewal: 1, + needstype: 2, + rent_type: 3, + postcode_known: 0, + ) + end + + before do + sign_in user + end + + around do |example| + FormHandler.instance.use_real_forms! + example.run + FormHandler.instance.use_fake_forms! + end + + it "does not crash the app if postcode_known is not nil" do + expect { + get "/lettings-logs/#{lettings_log.id}", headers:, params: {} + }.not_to raise_error(ActionView::Template::Error) + end + end + context "with a lettings log with a single section complete" do let(:section_completed_lettings_log) do FactoryBot.create( diff --git a/spec/requests/sales_logs_controller_spec.rb b/spec/requests/sales_logs_controller_spec.rb index 0a7ca0790..14341cd33 100644 --- a/spec/requests/sales_logs_controller_spec.rb +++ b/spec/requests/sales_logs_controller_spec.rb @@ -238,17 +238,28 @@ RSpec.describe SalesLogsController, type: :request do Timecop.return end + before do + Timecop.freeze(2022, 4, 1) + sales_log_2022.update!(saledate: Time.zone.local(2022, 4, 1)) + Timecop.freeze(2023, 1, 1) + sales_log_2022.update!(saledate: Time.zone.local(2023, 1, 1)) + end + + after do + Timecop.unfreeze + end + let!(:sales_log_2022) do FactoryBot.create(:sales_log, :completed, owning_organisation: organisation, - saledate: Time.zone.local(2022, 4, 1), - created_by: user) + created_by: user, + saledate: Time.zone.today) end let!(:sales_log_2023) do FactoryBot.create(:sales_log, owning_organisation: organisation, - saledate: Time.zone.local(2023, 1, 1), - created_by: user) + created_by: user, + saledate: Time.zone.today) end it "shows sales logs for multiple selected statuses and years" do diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 431270767..fb9150940 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -7,6 +7,12 @@ RSpec.describe SchemesController, type: :request do let(:user) { FactoryBot.create(:user, :support) } let!(:schemes) { FactoryBot.create_list(:scheme, 5) } + before do + schemes.each do |scheme| + FactoryBot.create(:location, scheme:) + end + end + describe "#index" do context "when not signed in" do it "redirects to the sign in page" do @@ -260,6 +266,7 @@ RSpec.describe SchemesController, type: :request do let(:add_deactivations) { scheme.scheme_deactivation_periods << scheme_deactivation_period } before do + FactoryBot.create(:location, scheme:) Timecop.freeze(Time.utc(2022, 10, 10)) sign_in user add_deactivations 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 f03ea894b..b771cbcea 100644 --- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe BulkUpload::Lettings::Year2022::RowParser do subject(:parser) { described_class.new(attributes) } - let(:now) { Time.zone.today } + let(:now) { Time.zone.parse("01/03/2023") } let(:attributes) { { bulk_upload: } } let(:bulk_upload) { create(:bulk_upload, :lettings, user:) } @@ -446,6 +446,16 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do end end + describe "#field_14" do # age3 + context "when blank but gender given" do + let(:attributes) { valid_attributes.merge(field_14: "", field_22: "F") } + + it "returns an error" do + expect(parser.errors[:field_14]).to be_present + end + end + end + describe "#field_52" do # leaving reason context "when field_134 is 1 meaning it is a renewal" do context "when field_52 is 40" do @@ -475,6 +485,16 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do end describe "#field_55, #field_56, #field_57" do + context "when one item selected" do + let(:attributes) { { bulk_upload:, field_55: "1" } } + + it "is permitted" do + expect(parser.errors[:field_55]).to be_blank + expect(parser.errors[:field_56]).to be_blank + expect(parser.errors[:field_57]).to be_blank + end + end + context "when more than one item selected" do let(:attributes) { { bulk_upload:, field_55: "1", field_56: "1" } } @@ -634,6 +654,10 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do expect(setup_errors.find { |e| e.attribute == :field_111 }.message).to eql("The owning organisation code is incorrect") end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end end context "when cannot find owning org" do @@ -642,6 +666,10 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do it "is not permitted" do expect(parser.errors[:field_111]).to eql(["The owning organisation code is incorrect"]) end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end end context "when org is not stock owning" do @@ -674,12 +702,28 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do end describe "#field_113" do # managing org + context "when blank" do + let(:attributes) { { bulk_upload:, field_113: "" } } + + it "is not permitted" do + expect(parser.errors[:field_113]).to eql(["The managing organisation code is incorrect"]) + end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end + end + context "when cannot find managing org" do let(:attributes) { { bulk_upload:, field_113: "donotexist" } } it "is not permitted" do expect(parser.errors[:field_113]).to eql(["The managing organisation code is incorrect"]) end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end end context "when not affiliated with managing org" do @@ -742,6 +786,18 @@ RSpec.describe BulkUpload::Lettings::Year2022::RowParser do %w[age8_known age8 field_19], ].each do |known, age, field| describe "##{known} and ##{age}" do + context "when #{field} is blank" do + let(:attributes) { { bulk_upload:, field.to_s => nil } } + + it "sets ##{known} 1" do + expect(parser.log.public_send(known)).to be(1) + end + + it "sets ##{age} to nil" do + expect(parser.log.public_send(age)).to be_nil + end + end + context "when #{field} is R" do let(:attributes) { { bulk_upload:, field.to_s => "R" } } 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 80df8f54f..a7dc629c0 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe BulkUpload::Lettings::Year2023::RowParser do subject(:parser) { described_class.new(attributes) } - let(:now) { Time.zone.today } + let(:now) { Time.zone.parse("01/03/2023") } let(:attributes) { { bulk_upload: } } let(:bulk_upload) { create(:bulk_upload, :lettings, user:, needstype: nil) } @@ -63,6 +63,20 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do stub_request(:get, /api.postcodes.io/) .to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\", \"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {}) + body = { + results: [ + { + DPA: { + "POSTCODE": "EC1N 2TD", + "POST_TOWN": "Newcastle", + }, + }, + ], + }.to_json + + stub_request(:get, "https://api.os.uk/search/places/v1/uprn?key=OS_DATA_KEY&uprn=100023336956") + .to_return(status: 200, body:, headers: {}) + parser.valid? end @@ -198,6 +212,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do field_35: now.strftime("%g"), field_4: "1", + + field_18: "100023336956", } end @@ -433,6 +449,16 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do end describe "#field_83, #field_84, #field_85" do + context "when one item selected" do + let(:attributes) { { bulk_upload:, field_83: "1" } } + + it "is permitted" do + expect(parser.errors[:field_83]).to be_blank + expect(parser.errors[:field_84]).to be_blank + expect(parser.errors[:field_85]).to be_blank + end + end + context "when more than one item selected" do let(:attributes) { { bulk_upload:, field_83: "1", field_84: "1" } } @@ -580,12 +606,28 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do end describe "#field_1" do # owning org + context "when blank" do + let(:attributes) { { bulk_upload:, field_1: "" } } + + it "is not permitted" do + expect(parser.errors[:field_1]).to eql(["The owning organisation code is incorrect"]) + end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end + end + context "when cannot find owning org" do let(:attributes) { { bulk_upload:, field_1: "donotexist" } } it "is not permitted" do expect(parser.errors[:field_1]).to eql(["The owning organisation code is incorrect"]) end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end end context "when org is not stock owning" do @@ -618,12 +660,28 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do end describe "#field_2" do # managing org + context "when blank" do + let(:attributes) { { bulk_upload:, field_2: "" } } + + it "is not permitted" do + expect(parser.errors[:field_2]).to eql(["The managing organisation code is incorrect"]) + end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end + end + context "when cannot find managing org" do let(:attributes) { { bulk_upload:, field_2: "donotexist" } } it "is not permitted" do expect(parser.errors[:field_2]).to eql(["The managing organisation code is incorrect"]) end + + it "blocks log creation" do + expect(parser).to be_block_log_creation + end end context "when not affiliated with managing org" do @@ -665,6 +723,16 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do end end + describe "#field_18" do # UPRN + context "when over 12 characters" do + let(:attributes) { { bulk_upload:, field_18: "1234567890123" } } + + it "has errors on the field" do + expect(parser.errors[:field_18]).to be_present + end + end + end + describe "#field_30" do context "when null" do let(:attributes) { setup_section_params.merge({ field_30: nil }) } @@ -686,9 +754,77 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do end end end + + describe "#field_56" do # age3 + context "when null but gender given" do + let(:attributes) { setup_section_params.merge({ field_56: "", field_57: "F" }) } + + it "returns an error" do + expect(parser.errors[:field_56]).to be_present + end + end + end end describe "#log" do + describe "#uprn" do + let(:attributes) { { bulk_upload:, field_18: "100023336956" } } + + it "sets to given value" do + expect(parser.log.uprn).to eql("100023336956") + end + end + + describe "#uprn_known" do + context "when uprn specified" do + let(:attributes) { { bulk_upload:, field_18: "100023336956" } } + + it "sets to 1" do + expect(parser.log.uprn_known).to be(1) + end + end + + context "when uprn blank" do + let(:attributes) { { bulk_upload:, field_18: "" } } + + it "sets to 0" do + expect(parser.log.uprn_known).to be(0) + end + end + end + + describe "#address_line1" do + let(:attributes) { { bulk_upload:, field_19: "123 Sesame Street" } } + + it "sets to given value" do + expect(parser.log.address_line1).to eql("123 Sesame Street") + end + end + + describe "#address_line2" do + let(:attributes) { { bulk_upload:, field_20: "Cookie Town" } } + + it "sets to given value" do + expect(parser.log.address_line2).to eql("Cookie Town") + end + end + + describe "#town_or_city" do + let(:attributes) { { bulk_upload:, field_21: "London" } } + + it "sets to given value" do + expect(parser.log.town_or_city).to eql("London") + end + end + + describe "#county" do + let(:attributes) { { bulk_upload:, field_22: "Greater London" } } + + it "sets to given value" do + expect(parser.log.county).to eql("Greater London") + end + end + [ %w[age1_known age1 field_46], %w[age2_known age2 field_52], @@ -700,6 +836,18 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do %w[age8_known age8 field_76], ].each do |known, age, field| describe "##{known} and ##{age}" do + context "when #{field} is blank" do + let(:attributes) { { bulk_upload:, field.to_s => nil } } + + it "sets ##{known} 1" do + expect(parser.log.public_send(known)).to be(1) + end + + it "sets ##{age} to nil" do + expect(parser.log.public_send(age)).to be_nil + end + end + context "when #{field} is R" do let(:attributes) { { bulk_upload:, field.to_s => "R" } } diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index b1064acd5..141bae6fb 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -155,6 +155,7 @@ RSpec.describe Csv::LettingsLogCsvService do period is_carehome chcharge + carehome_charges_value_check brent scharge pscharge diff --git a/spec/services/imports/lettings_logs_import_service_spec.rb b/spec/services/imports/lettings_logs_import_service_spec.rb index bfd907620..89dd6e0c4 100644 --- a/spec/services/imports/lettings_logs_import_service_spec.rb +++ b/spec/services/imports/lettings_logs_import_service_spec.rb @@ -366,6 +366,81 @@ RSpec.describe Imports::LettingsLogsImportService do end end + context "and this is a non temporary acommodation" do + before do + lettings_log_xml.at_xpath("//xmlns:Q27").content = "9" + lettings_log_xml.at_xpath("//xmlns:Q11").content = "4" + lettings_log_xml.at_xpath("//xmlns:VDAY").content = "" + lettings_log_xml.at_xpath("//xmlns:VMONTH").content = "" + lettings_log_xml.at_xpath("//xmlns:VYEAR").content = "" + lettings_log_xml.at_xpath("//xmlns:MRCDAY").content = "" + lettings_log_xml.at_xpath("//xmlns:MRCMONTH").content = "" + lettings_log_xml.at_xpath("//xmlns:MRCYEAR").content = "" + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Removing vacancy reason and previous tenancy since this accommodation is not temporary/) + expect { lettings_log_service.send(:create_log, lettings_log_xml) } + .not_to raise_error + end + + it "clears out the referral answer" 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.rsnvac).to be_nil + expect(lettings_log.prevten).to be_nil + end + end + + context "and the number the property was relet is over 20" do + before do + lettings_log_xml.at_xpath("//xmlns:Q20").content = "25" + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Removing offered as the value is above the maximum of 20/) + expect { lettings_log_service.send(:create_log, lettings_log_xml) } + .not_to raise_error + end + + it "clears out the referral answer" 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.offered).to be_nil + end + end + + context "and income over the max" do + before do + lettings_log_xml.at_xpath("//xmlns:Q8Money").content = "25000" + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Removing working situation because income is too high for it/) + expect { lettings_log_service.send(:create_log, lettings_log_xml) } + .not_to raise_error + end + + it "clears out the referral answer" 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.ecstat1).to be_nil + expect(lettings_log.earnings).to eq(25_000) + end + end + context "and the net income soft validation is triggered (net_income_value_check)" do before do lettings_log_xml.at_xpath("//xmlns:Q8a").content = "1 Weekly" @@ -416,6 +491,27 @@ RSpec.describe Imports::LettingsLogsImportService do end end + context "and the carehome charge soft validation is triggered (carehome_charge_value_check)" do + let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } + + before do + scheme2.update!(registered_under_care_act: 2) + lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id + lettings_log_xml.at_xpath("//xmlns:Q18b").content = "" + lettings_log_xml.at_xpath("//xmlns:Q18ai").content = "" + lettings_log_xml.at_xpath("//xmlns:Q18aii").content = "" + lettings_log_xml.at_xpath("//xmlns:Q18aiii").content = "" + lettings_log_xml.at_xpath("//xmlns:Q18aiv").content = "" + lettings_log_xml.at_xpath("//xmlns:Q18av").content = "" + end + + it "completes the log" do + lettings_log_service.send(:create_log, lettings_log_xml) + lettings_log = LettingsLog.find_by(old_id: lettings_log_id) + expect(lettings_log.status).to eq("completed") + end + end + context "and this is a supported housing log with multiple locations under a scheme" do let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } @@ -539,5 +635,41 @@ RSpec.describe Imports::LettingsLogsImportService do .to change(OrganisationRelationship, :count).by(1) end end + + context "when this is a joint tenancy with 1 person in the household" do + let(:lettings_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } + 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("//xmlns:joint").content = "1" + lettings_log_xml.at_xpath("//xmlns:HHMEMB").content = "1" + lettings_log_xml.at_xpath("//xmlns:P2Age").content = "" + lettings_log_xml.at_xpath("//xmlns:P2Rel").content = "" + lettings_log_xml.at_xpath("//xmlns:P2Sex").content = "" + lettings_log_xml.at_xpath("//xmlns:P1Nat").content = "18" + lettings_log_xml.at_xpath("//xmlns:P2Eco").content = "" + lettings_log_xml.at_xpath("//xmlns:DAY").content = "2" + lettings_log_xml.at_xpath("//xmlns:MONTH").content = "10" + lettings_log_xml.at_xpath("//xmlns:YEAR").content = "2022" + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Removing joint tenancy as there is only 1 person in the household/) + expect { lettings_log_service.send(:create_log, lettings_log_xml) } + .not_to raise_error + end + + it "clears out the referral answer" 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.joint).to be_nil + expect(lettings_log.hhmemb).to eq(1) + end + end end end diff --git a/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index d0e1f807d..f0168ba11 100644 --- a/spec/services/imports/sales_logs_import_service_spec.rb +++ b/spec/services/imports/sales_logs_import_service_spec.rb @@ -167,6 +167,23 @@ RSpec.describe Imports::SalesLogsImportService do end end + context "when the mortgage lender is not set" do + let(:sales_log_id) { "discounted_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:Q34a").content = "" + allow(logger).to receive(:warn).and_return(nil) + end + + it "correctly sets mortgage lender and mortgage lender other" do + sales_log_service.send(:create_log, sales_log_xml) + + sales_log = SalesLog.find_by(old_id: sales_log_id) + expect(sales_log&.mortgagelender).to be(0) + expect(sales_log&.mortgagelenderother).to be_nil + end + end + context "with shared ownership type" do let(:sales_log_id) { "shared_ownership_sales_log" } @@ -379,6 +396,21 @@ RSpec.describe Imports::SalesLogsImportService do end end + context "and the value soft validation is triggered (discounted_sale_value_check)" do + let(:sales_log_id) { "discounted_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:Q31PurchasePrice").content = "500000" + end + + it "completes the log" do + sales_log_service.send(:create_log, sales_log_xml) + sales_log = SalesLog.find_by(old_id: sales_log_id) + expect(sales_log.status).to eq("completed") + expect(sales_log.discounted_sale_value_check).to eq(0) + end + end + context "and it has an invalid record with invalid child age" do let(:sales_log_id) { "discounted_ownership_sales_log" } @@ -407,6 +439,108 @@ RSpec.describe Imports::SalesLogsImportService do end end + context "and it has a record with invalid equity" do + let(:sales_log_id) { "shared_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:Q23Equity").content = "78" + 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 { 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.equity).to be_nil + end + end + + context "and it has a record with invalid equity (under_min)" do + let(:sales_log_id) { "shared_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:Q23Equity").content = "20" + 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 { 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.equity).to be_nil + end + end + + context "and it has a record with postcode in invalid format" do + let(:sales_log_id) { "shared_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:Q14Postcode").content = "L3132AF" + sales_log_xml.at_xpath("//xmlns:Q14ONSLACode").content = "E07000223" + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Log shared_ownership_sales_log: Removing 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 la" 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.postcode_full).to be_nil + expect(sales_log.pcodenk).to eq(1) # not known + expect(sales_log.la).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" } + + before do + sales_log_xml.at_xpath("//meta:status").content = "saved" + sales_log_xml.at_xpath("//xmlns:Q17aStaircase").content = "1 Yes" + sales_log_xml.at_xpath("//xmlns:PercentBought").content = "5" + sales_log_xml.at_xpath("//xmlns:PercentOwns").content = "40" + sales_log_xml.at_xpath("//xmlns:Q17Resale").content = "" + sales_log_xml.at_xpath("//xmlns:EXDAY").content = "" + sales_log_xml.at_xpath("//xmlns:EXMONTH").content = "" + sales_log_xml.at_xpath("//xmlns:EXYEAR").content = "" + sales_log_xml.at_xpath("//xmlns:HODAY").content = "" + sales_log_xml.at_xpath("//xmlns:HOMONTH").content = "" + sales_log_xml.at_xpath("//xmlns:HOYEAR").content = "" + end + + it "intercepts the relevant validation error but does not clear setup fields" do + expect(logger).to receive(:warn).with(/Log shared_ownership_sales_log: Removing field stairbought from log triggering validation: The minimum increase in equity while staircasing is 10%/) + expect { sales_log_service.send(:create_log, sales_log_xml) } + .not_to raise_error + sales_log = SalesLog.find_by(old_id: sales_log_id) + + expect(sales_log.type).to eq(2) + end + end + context "and it has an invalid record with invalid postcodes" do let(:sales_log_id) { "discounted_ownership_sales_log" } @@ -433,6 +567,46 @@ RSpec.describe Imports::SalesLogsImportService do end end + context "and it has invalid postcodes" do + let(:sales_log_id) { "shared_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//meta:status").content = "submitted-invalid" + sales_log_xml.at_xpath("//xmlns:Q14Postcode").content = "2AA" # postcode + end + + it "intercepts the relevant validation error" do + expect(logger).to receive(:warn).with(/Removing field postcode_full from log triggering validation: wrong_format/) + 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.postcode_full).to be_nil + expect(sales_log.postcode_full).to be_nil + end + end + + context "when there is information about 7 people" do + let(:sales_log_id) { "shared_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:P7Age").content = "22" + sales_log_xml.at_xpath("//xmlns:LiveInOther").content = "10" + end + + it "does not try to save information about person 7" do + expect { sales_log_service.send(:create_log, sales_log_xml) } + .not_to raise_error + end + end + context "and it has an invalid record with invalid contracts exchange date" do let(:sales_log_id) { "shared_ownership_sales_log" } @@ -694,6 +868,31 @@ RSpec.describe Imports::SalesLogsImportService do end end + context "when inferring armed forces still" do + let(:sales_log_id) { "discounted_ownership_sales_log" } + + before do + sales_log_xml.at_xpath("//xmlns:ArmedF").content = "1 Yes" + allow(logger).to receive(:warn).and_return(nil) + end + + it "sets hhregresstill to don't know if not answered" do + sales_log_xml.at_xpath("//xmlns:LeftArmedF").content = "" + sales_log_service.send(:create_log, sales_log_xml) + + sales_log = SalesLog.find_by(old_id: sales_log_id) + expect(sales_log&.hhregresstill).to eq(7) + end + + it "sets hhregresstill correctly if answered" do + sales_log_xml.at_xpath("//xmlns:LeftArmedF").content = "4" + sales_log_service.send(:create_log, sales_log_xml) + + sales_log = SalesLog.find_by(old_id: sales_log_id) + expect(sales_log&.hhregresstill).to eq(4) + end + end + context "when inferring disability" do let(:sales_log_id) { "discounted_ownership_sales_log" } @@ -1237,6 +1436,24 @@ RSpec.describe Imports::SalesLogsImportService do expect(sales_log&.socprevten).to be(10) end end + + context "when it's a joint tenancy and jointmore is not answered" do + let(:sales_log_id) { "outright_sale_sales_log" } + + before do + allow(logger).to receive(:warn).and_return(nil) + end + + it "sets jointmore to don't know" do + sales_log_xml.at_xpath("//meta:status").content = "invalid" + sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes" + sales_log_xml.at_xpath("//xmlns:JointMore").content = "" + sales_log_service.send(:create_log, sales_log_xml) + + sales_log = SalesLog.find_by(old_id: sales_log_id) + expect(sales_log&.jointmore).to eq(3) + end + end end end end diff --git a/spec/services/imports/scheme_location_import_service_spec.rb b/spec/services/imports/scheme_location_import_service_spec.rb index e74067cae..186fba818 100644 --- a/spec/services/imports/scheme_location_import_service_spec.rb +++ b/spec/services/imports/scheme_location_import_service_spec.rb @@ -16,6 +16,11 @@ RSpec.describe Imports::SchemeLocationImportService do File.open("#{directory}/#{filename}.xml") end + before do + WebMock.stub_request(:get, /api.postcodes.io\/postcodes/) + .to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E08000035"}}}', headers: {}) + end + context "when importing scheme locations" do let(:remote_folder) { "schemes" } @@ -145,6 +150,7 @@ RSpec.describe Imports::SchemeLocationImportService do expect(location.old_visible_id).to eq("10") expect(location.startdate).to eq("1900-01-01") expect(location.scheme).to eq(scheme) + expect(location.confirmed).to eq(true) end it "matches expected schemes values" do @@ -156,10 +162,15 @@ RSpec.describe Imports::SchemeLocationImportService do expect(location.scheme.primary_client_group).to eq("Older people with support needs") expect(location.scheme.secondary_client_group).to be_nil expect(location.scheme.sensitive).to eq("No") - expect(location.scheme.end_date).to eq("2050-12-31") expect(location.scheme.confirmed).to be_truthy end + it "creates a deactivation period" do + location = location_service.create_scheme_location(location_xml) + expect(location.location_deactivation_periods.count).to eq(1) + expect(location.location_deactivation_periods.first.deactivation_date).to eq(Time.zone.local(2050, 12, 31)) + end + context "and we import the same location twice" do before { location_service.create_scheme_location(location_xml) } diff --git a/spec/support/bulk_upload/log_to_csv.rb b/spec/support/bulk_upload/log_to_csv.rb index 86167376d..a2d8c2f5f 100644 --- a/spec/support/bulk_upload/log_to_csv.rb +++ b/spec/support/bulk_upload/log_to_csv.rb @@ -29,11 +29,11 @@ class BulkUpload::LogToCsv to_2022_row + [ log.needstype, log.location&.id, - nil, # uprn, - nil, # address_line_1, - nil, # address_line_2, - nil, # town_or_city, - nil, # county, + log.uprn, + log.address_line1, + log.address_line2, + log.town_or_city, + log.county, ] end