From f29e41bb2c1588d925286399285c3e5a4cfb0a76 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Mon, 20 Mar 2023 16:28:02 +0000 Subject: [PATCH 01/31] Value validation (#1429) * Add discounted_sale_value_check to sales * Add DiscountedSaleValueCheck pages and questions * Add value check to the form * Only run validate_discounted_ownership_value as a hard validation on and after 24/25 * Rebase fix * Fix form spec * Update discounted_ownership_value_invalid? * update validation * Update soft validation content * PR comments * typo * lint * Default discounted_sale_value_check on import --- .../pages/discounted_sale_value_check.rb | 26 +++ .../questions/discounted_sale_value_check.rb | 23 ++ .../discounted_ownership_scheme.rb | 4 + app/models/form/sales/subsections/setup.rb | 1 + app/models/sales_log.rb | 17 +- .../sales/sale_information_validations.rb | 11 +- .../validations/sales/soft_validations.rb | 9 + .../imports/sales_logs_import_service.rb | 4 +- config/locales/en.yml | 3 + ...6162737_add_discounted_sale_value_check.rb | 5 + db/schema.rb | 1 + .../pages/discounted_sale_value_check_spec.rb | 52 +++++ .../discounted_sale_value_check_spec.rb | 57 +++++ .../discounted_ownership_scheme_spec.rb | 4 + .../form/sales/subsections/setup_spec.rb | 1 + spec/models/form_spec.rb | 4 +- spec/models/sales_log_spec.rb | 2 + .../sale_information_validations_spec.rb | 200 ++++++++++-------- .../sales/soft_validations_spec.rb | 115 ++++++++++ .../imports/sales_logs_import_service_spec.rb | 15 ++ 20 files changed, 450 insertions(+), 104 deletions(-) create mode 100644 app/models/form/sales/pages/discounted_sale_value_check.rb create mode 100644 app/models/form/sales/questions/discounted_sale_value_check.rb create mode 100644 db/migrate/20230316162737_add_discounted_sale_value_check.rb create mode 100644 spec/models/form/sales/pages/discounted_sale_value_check_spec.rb create mode 100644 spec/models/form/sales/questions/discounted_sale_value_check_spec.rb 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/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/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/sales_log.rb b/app/models/sales_log.rb index 7385d8b43..5b0d8f17c 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 mortgagelender othtype discounted_sale_value_check].freeze RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze def lettings? @@ -330,4 +330,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/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/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/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index d7a3c8534..3dc3c6d27 100644 --- a/app/services/imports/sales_logs_import_service.rb +++ b/app/services/imports/sales_logs_import_service.rb @@ -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 @@ -255,7 +256,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) diff --git a/config/locales/en.yml b/config/locales/en.yml index 8c9cd12c1..053929f46 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -525,6 +525,9 @@ 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}" devise: two_factor_authentication: 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 32d71dfeb..2cffbaf9f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -569,6 +569,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do t.string "county" t.integer "nationalbuy2" t.integer "student_not_child_value_check" + t.integer "discounted_sale_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" t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true 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/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/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_spec.rb b/spec/models/form_spec.rb index cac779e33..57995d90b 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -227,9 +227,9 @@ 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")) diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb index 890fa069f..d8f4ca5bc 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -61,6 +61,7 @@ RSpec.describe SalesLog, type: :model do old_persons_shared_ownership_value_check mortgagelender othtype + discounted_sale_value_check proplen mortlen frombeds @@ -79,6 +80,7 @@ RSpec.describe SalesLog, type: :model do old_persons_shared_ownership_value_check mortgagelender othtype + discounted_sale_value_check address_line2 county postcode_full diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index fb9500956..c34738de7 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -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/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/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index d0e1f807d..f0fe93588 100644 --- a/spec/services/imports/sales_logs_import_service_spec.rb +++ b/spec/services/imports/sales_logs_import_service_spec.rb @@ -379,6 +379,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" } From e66e27f6de765bf838be18c1c5ade867b77b3cf5 Mon Sep 17 00:00:00 2001 From: SamSeed-Softwire <63662292+SamSeed-Softwire@users.noreply.github.com> Date: Mon, 20 Mar 2023 16:51:44 +0000 Subject: [PATCH 02/31] fix: show "Most recent let type" qu for both needs types (#1418) --- app/models/form/lettings/pages/property_let_type.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/form/lettings/pages/property_let_type.rb b/app/models/form/lettings/pages/property_let_type.rb index f4d629b9e..3f9011c99 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, "renewal" => 0 }] end def questions From 84a6fc6308de8ba021aeb128fea39b32df5816d4 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:30:50 +0000 Subject: [PATCH 03/31] Clear postcode known if postcode is getting cleared (#1447) --- .../imports/sales_logs_import_service.rb | 2 ++ .../imports/sales_logs_import_service_spec.rb | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index 3dc3c6d27..e548b8c72 100644 --- a/app/services/imports/sales_logs_import_service.rb +++ b/app/services/imports/sales_logs_import_service.rb @@ -191,6 +191,8 @@ module Imports 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) + 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) diff --git a/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index f0fe93588..d74b24ce2 100644 --- a/spec/services/imports/sales_logs_import_service_spec.rb +++ b/spec/services/imports/sales_logs_import_service_spec.rb @@ -448,6 +448,32 @@ 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(/Enter a postcode in the correct format, for example AA1 1AA/) + 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 "and it has an invalid record with invalid contracts exchange date" do let(:sales_log_id) { "shared_ownership_sales_log" } From 926fdccad0d6a2973587fc40bca0dbd3040825ea Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Tue, 21 Mar 2023 10:31:31 +0000 Subject: [PATCH 04/31] Set jointmore to don't know if not given for incomplete logs too (#1449) --- .../imports/sales_logs_import_service.rb | 3 +-- .../imports/sales_logs_import_service_spec.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index e548b8c72..af38106a2 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) @@ -509,7 +509,6 @@ module Imports 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 diff --git a/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index d74b24ce2..be271778c 100644 --- a/spec/services/imports/sales_logs_import_service_spec.rb +++ b/spec/services/imports/sales_logs_import_service_spec.rb @@ -1278,6 +1278,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 From f25f0174660e0744845e3821c763c06e063d25b1 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:22:34 +0000 Subject: [PATCH 05/31] copy change for black ethnicity question on lettings and sales (#1421) --- app/models/form/lettings/questions/ethnic_black.rb | 2 +- .../form/sales/questions/buyer1_ethnic_background_black.rb | 2 +- .../form/sales/questions/buyer2_ethnic_background_black.rb | 2 +- config/forms/2021_2022.json | 2 +- config/forms/2022_2023.json | 2 +- .../form/sales/questions/buyer1_ethnic_background_black_spec.rb | 2 +- .../form/sales/questions/buyer2_ethnic_background_black_spec.rb | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) 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/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/config/forms/2021_2022.json b/config/forms/2021_2022.json index 49931ee05..d4e01cfd1 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" } } } diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index eeed6c3c7..bd88b1335 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -1671,7 +1671,7 @@ "value": "Caribbean" }, "14": { - "value": "Any other Black, African or Caribbean background" + "value": "Any other Black, African, Caribbean or Black British background" } } } 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 From 3083051d790de08349d6c6fc2615c1c9d530ac23 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:22:57 +0000 Subject: [PATCH 06/31] CLDC-2132 breadcrumbs logs link (#1427) * ensure the log review page has the correct links in the breadcrumbs * ensure check your answers pages have the correct links in the breadcrumbs * write feature tests to check that breadcrumbs have the correct links * utilise rails url helpers * when routing to a log show page, remove unnecessary :id call in url helper * slight tweak of methods used to get name of an instance of the class --- app/views/form/check_answers.html.erb | 6 ++-- app/views/form/review.html.erb | 22 ++++--------- spec/features/lettings_log_spec.rb | 26 +++++++++++++++ spec/features/sales_log_spec.rb | 46 ++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 19 deletions(-) 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/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 From f3e7d2c62b5010d05f98332d1ccef7c2a8649ae7 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:30:14 +0000 Subject: [PATCH 07/31] CLDC-2073 app crashing if needs type is changed (#1368) * add some methods on lettings log and use them and already existing methods to make depends on human readbale for pages in property information subsection * reformat answer options for neatness * ensure that property information subsection is conditionally not shown under correct conditions * amend method to find the path for the next question to answer so that if no questions in the next section are currently routed to, it goes to the section after that * make amendments for failing test and linting * remove unnecessary method * remove unnecessary conditions from depends on, the displayed in tasklist method override is sufficient * test the change to the method creating a link to the next subsection * minor refactor to displayed_is_tasklist condition and changes in testing * implement the fix on 22/23 form also * write a test covering the fix * removal not_renewal? method and tweak depends on for all pages using that method * linty fluff begone * correct some errors in tests after changes to factories * minor testing amendments after rebase --- app/models/form.rb | 4 +-- ...rst_time_property_let_as_social_housing.rb | 2 +- .../lettings/pages/new_build_handover_date.rb | 6 +--- .../lettings/pages/property_building_type.rb | 2 +- .../form/lettings/pages/property_let_type.rb | 2 +- .../pages/property_local_authority.rb | 2 +- .../lettings/pages/property_major_repairs.rb | 13 +------- .../pages/property_number_of_bedrooms.rb | 2 +- ...ty_number_of_times_relet_not_social_let.rb | 2 +- ...operty_number_of_times_relet_social_let.rb | 2 +- .../form/lettings/pages/property_postcode.rb | 2 +- .../form/lettings/pages/property_unit_type.rb | 2 +- .../property_vacancy_reason_first_let.rb | 2 +- .../property_vacancy_reason_not_first_let.rb | 2 +- .../pages/property_wheelchair_accessible.rb | 2 +- .../lettings/pages/void_or_renewal_date.rb | 13 +------- .../lettings/questions/rsnvac_first_let.rb | 9 ++---- .../subsections/property_information.rb | 4 +++ app/models/form/subsection.rb | 11 +++++-- app/models/lettings_log.rb | 4 +++ config/forms/2022_2023.json | 10 +++++- spec/factories/lettings_log.rb | 6 ++-- spec/fixtures/exports/general_needs_log.csv | 2 +- spec/fixtures/exports/general_needs_log.xml | 4 +-- .../exports/supported_housing_logs.xml | 4 +-- .../property_wheelchair_accessible_spec.rb | 4 +-- .../subsections/property_information_spec.rb | 10 ++---- spec/models/form_spec.rb | 20 ++++++++++++ .../requests/lettings_logs_controller_spec.rb | 32 +++++++++++++++++++ 29 files changed, 110 insertions(+), 70 deletions(-) diff --git a/app/models/form.rb b/app/models/form.rb index c7bb4f2b0..9fa908427 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -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/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 3f9011c99..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 }] + @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..2c64e3628 100644 --- a/app/models/form/lettings/pages/property_local_authority.rb +++ b/app/models/form/lettings/pages/property_local_authority.rb @@ -2,7 +2,7 @@ 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 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/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/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/subsections/property_information.rb b/app/models/form/lettings/subsections/property_information.rb index cc07535ae..6e20ea7cf 100644 --- a/app/models/form/lettings/subsections/property_information.rb +++ b/app/models/form/lettings/subsections/property_information.rb @@ -27,4 +27,8 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection Form::Lettings::Pages::PropertyMajorRepairsValueCheck.new(nil, nil, self), ].compact end + + def displayed_in_tasklist?(log) + !(log.is_supported_housing? && log.is_renewal?) + end end 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/lettings_log.rb b/app/models/lettings_log.rb index 4524ead12..36d81a537 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -287,6 +287,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 diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index bd88b1335..7cee2b737 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -939,7 +939,15 @@ } } } - } + }, + "displayed_in_tasklist": [ + { + "is_supported_housing?": false + }, + { + "is_renewal?": false + } + ] }, "tenancy_information": { "label": "Tenancy information", 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/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/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/subsections/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb index 227773487..8b30964c3 100644 --- a/spec/models/form/lettings/subsections/property_information_spec.rb +++ b/spec/models/form/lettings/subsections/property_information_spec.rb @@ -1,10 +1,8 @@ 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 @@ -44,10 +42,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_spec.rb b/spec/models/form_spec.rb index 57995d90b..3236623c1 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 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( From 1acd3b3aafe81f7289f0009567245759a4630aac Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:18:58 +0000 Subject: [PATCH 08/31] CLDC-2074 Change care home charges validation (#1410) * Add carehome charges value check field * Add carehome charges soft validation to 23/24 forms * Update care_home_charge_expected_not_provided? * Add care_home_charges_value_check to 22/23 * Update csv * Add care_home_charges_value_check to 21/22 form * Update import to set value_chech to yes --- .../pages/care_home_charges_value_check.rb | 15 +++++ .../care_home_charges_value_check.rb | 14 +++++ .../subsections/income_and_benefits.rb | 1 + app/models/lettings_log.rb | 6 +- .../imports/lettings_logs_import_service.rb | 3 +- config/forms/2021_2022.json | 36 ++++++++++++ config/forms/2022_2023.json | 36 ++++++++++++ config/locales/en.yml | 2 + ...124749_add_carehome_charges_value_check.rb | 5 ++ db/schema.rb | 1 + .../fixtures/files/lettings_logs_download.csv | 4 +- .../lettings_logs_download_codes_only.csv | 4 +- .../lettings_logs_download_non_support.csv | 4 +- .../care_home_charges_value_check_spec.rb | 44 +++++++++++++++ .../care_home_charges_value_check_spec.rb | 56 +++++++++++++++++++ .../subsections/income_and_benefits_spec.rb | 1 + spec/models/lettings_log_spec.rb | 2 + .../validations/soft_validations_spec.rb | 34 +++++++++++ .../csv/lettings_log_csv_service_spec.rb | 1 + .../lettings_logs_import_service_spec.rb | 21 +++++++ 20 files changed, 282 insertions(+), 8 deletions(-) create mode 100644 app/models/form/lettings/pages/care_home_charges_value_check.rb create mode 100644 app/models/form/lettings/questions/care_home_charges_value_check.rb create mode 100644 db/migrate/20230313124749_add_carehome_charges_value_check.rb create mode 100644 spec/models/form/lettings/pages/care_home_charges_value_check_spec.rb create mode 100644 spec/models/form/lettings/questions/care_home_charges_value_check_spec.rb 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/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/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/lettings_log.rb b/app/models/lettings_log.rb index 36d81a537..f8c817c56 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -53,7 +53,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 @@ -505,6 +505,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 diff --git a/app/services/imports/lettings_logs_import_service.rb b/app/services/imports/lettings_logs_import_service.rb index 34582091d..9e5de20ba 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 @@ -339,7 +340,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/config/forms/2021_2022.json b/config/forms/2021_2022.json index d4e01cfd1..dfcf83fb6 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -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 7cee2b737..6a1b8cc40 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -7782,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/locales/en.yml b/config/locales/en.yml index 053929f46..36d8b93f8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -528,6 +528,8 @@ en: 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/schema.rb b/db/schema.rb index 2cffbaf9f..92b0d9a63 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" 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/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/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/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/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb index 57b5de21a..43cbc69ce 100644 --- a/spec/models/lettings_log_spec.rb +++ b/spec/models/lettings_log_spec.rb @@ -2235,6 +2235,7 @@ RSpec.describe LettingsLog do first_time_property_let_as_social_housing tenancycode propcode + chcharge tenancylength ]) end @@ -2248,6 +2249,7 @@ RSpec.describe LettingsLog do first_time_property_let_as_social_housing tenancycode propcode + chcharge tenancylength address_line2 county diff --git a/spec/models/validations/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb index 3ce2b4527..b71d91a62 100644 --- a/spec/models/validations/soft_validations_spec.rb +++ b/spec/models/validations/soft_validations_spec.rb @@ -327,4 +327,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/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..5b56efdfb 100644 --- a/spec/services/imports/lettings_logs_import_service_spec.rb +++ b/spec/services/imports/lettings_logs_import_service_spec.rb @@ -416,6 +416,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" } From aad771b3841ad57cf1ab6af3c614f22605c830a3 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Tue, 21 Mar 2023 15:51:26 +0000 Subject: [PATCH 09/31] CLDC-2143 Set more default fields and don't clear setup values (#1450) * Set default hhregresstill * Don't clear type if it errors * Make mortgagelender mandatory and add a don't know option * Infer mortgagelender as don't know by default --- .../form/sales/questions/mortgage_lender.rb | 47 +++++++++++++ app/models/sales_log.rb | 2 +- .../imports/sales_logs_import_service.rb | 8 ++- .../sales/questions/mortgage_lender_spec.rb | 47 +++++++++++++ spec/models/sales_log_spec.rb | 2 - .../imports/sales_logs_import_service_spec.rb | 69 +++++++++++++++++++ 6 files changed, 170 insertions(+), 5 deletions(-) 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/sales_log.rb b/app/models/sales_log.rb index 5b0d8f17c..ba2ea4fa8 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 discounted_sale_value_check].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? diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index af38106a2..c2844e019 100644 --- a/app/services/imports/sales_logs_import_service.rb +++ b/app/services/imports/sales_logs_import_service.rb @@ -189,8 +189,10 @@ 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 @@ -504,6 +506,7 @@ 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 @@ -518,6 +521,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 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/sales_log_spec.rb b/spec/models/sales_log_spec.rb index d8f4ca5bc..231dc68c4 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -59,7 +59,6 @@ RSpec.describe SalesLog, type: :model do purchid monthly_charges_value_check old_persons_shared_ownership_value_check - mortgagelender othtype discounted_sale_value_check proplen @@ -78,7 +77,6 @@ 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 diff --git a/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index be271778c..e41ffabaf 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" } @@ -422,6 +439,33 @@ RSpec.describe Imports::SalesLogsImportService do 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" } @@ -735,6 +779,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" } From 579fa6a969650131c850757c6d635cc11a8d7de2 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Tue, 21 Mar 2023 17:22:38 +0000 Subject: [PATCH 10/31] CLDC-2134 Rework summary and email (#1451) * remove column errors from bulk upload email * summarise setup errors only if there are any --- ...lk_upload_error_summary_table_component.rb | 12 +- app/mailers/bulk_upload_mailer.rb | 13 -- app/models/bulk_upload.rb | 8 - ...load_error_summary_table_component_spec.rb | 147 +++++++++++------- spec/mailers/bulk_upload_mailer_spec.rb | 31 +--- 5 files changed, 99 insertions(+), 112 deletions(-) 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/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/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/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 From 1a5d9fc14b7a417a359cc95754a5c6768f2b4f3c Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:00:03 +0000 Subject: [PATCH 11/31] [CLDC-2068] Add UPRN questions to lettings (#1432) * Update CYA page * Update UPRN derived fields * Update sales' UPRN questions * Add UPRN lettings questions * Fix spec --- ...swers_summary_list_card_component.html.erb | 16 +++- .../lettings_log_variables.rb | 21 +++++ app/models/form/lettings/pages/address.rb | 24 +++++ .../pages/property_local_authority.rb | 8 ++ app/models/form/lettings/pages/uprn.rb | 28 ++++++ .../form/lettings/pages/uprn_confirmation.rb | 17 ++++ app/models/form/lettings/pages/uprn_known.rb | 16 ++++ .../form/lettings/questions/address_line1.rb | 38 ++++++++ .../form/lettings/questions/address_line2.rb | 13 +++ app/models/form/lettings/questions/county.rb | 13 +++ app/models/form/lettings/questions/la.rb | 4 + .../questions/postcode_for_full_address.rb | 25 +++++ .../form/lettings/questions/town_or_city.rb | 13 +++ app/models/form/lettings/questions/uprn.rb | 35 +++++++ .../lettings/questions/uprn_confirmation.rb | 34 +++++++ .../form/lettings/questions/uprn_known.rb | 21 +++++ .../subsections/property_information.rb | 19 +++- .../form/sales/questions/address_line1.rb | 1 + app/models/form/sales/questions/uprn.rb | 1 + app/models/lettings_log.rb | 5 + app/models/log.rb | 1 + .../form/_check_answers_summary_list.html.erb | 2 +- .../form/lettings/pages/address_spec.rb | 73 +++++++++++++++ .../pages/property_local_authority_spec.rb | 77 ++++++++++++++++ .../lettings/pages/uprn_confirmation_spec.rb | 59 ++++++++++++ .../form/lettings/pages/uprn_known_spec.rb | 51 ++++++++++ spec/models/form/lettings/pages/uprn_spec.rb | 81 ++++++++++++++++ .../lettings/questions/address_line1_spec.rb | 79 ++++++++++++++++ .../lettings/questions/address_line2_spec.rb | 49 ++++++++++ .../form/lettings/questions/county_spec.rb | 49 ++++++++++ .../models/form/lettings/questions/la_spec.rb | 30 ++++++ .../postcode_for_full_address_spec.rb | 62 +++++++++++++ .../lettings/questions/town_or_city_spec.rb | 49 ++++++++++ .../questions/uprn_confirmation_spec.rb | 90 ++++++++++++++++++ .../lettings/questions/uprn_known_spec.rb | 59 ++++++++++++ .../form/lettings/questions/uprn_spec.rb | 92 +++++++++++++++++++ .../subsections/property_information_spec.rb | 83 ++++++++++++----- .../sales/questions/address_line1_spec.rb | 4 + spec/models/form/sales/questions/uprn_spec.rb | 4 + spec/models/lettings_log_spec.rb | 57 ++++++++++++ spec/models/sales_log_spec.rb | 10 +- 41 files changed, 1382 insertions(+), 31 deletions(-) create mode 100644 app/models/form/lettings/pages/address.rb create mode 100644 app/models/form/lettings/pages/uprn.rb create mode 100644 app/models/form/lettings/pages/uprn_confirmation.rb create mode 100644 app/models/form/lettings/pages/uprn_known.rb create mode 100644 app/models/form/lettings/questions/address_line1.rb create mode 100644 app/models/form/lettings/questions/address_line2.rb create mode 100644 app/models/form/lettings/questions/county.rb create mode 100644 app/models/form/lettings/questions/postcode_for_full_address.rb create mode 100644 app/models/form/lettings/questions/town_or_city.rb create mode 100644 app/models/form/lettings/questions/uprn.rb create mode 100644 app/models/form/lettings/questions/uprn_confirmation.rb create mode 100644 app/models/form/lettings/questions/uprn_known.rb create mode 100644 spec/models/form/lettings/pages/address_spec.rb create mode 100644 spec/models/form/lettings/pages/property_local_authority_spec.rb create mode 100644 spec/models/form/lettings/pages/uprn_confirmation_spec.rb create mode 100644 spec/models/form/lettings/pages/uprn_known_spec.rb create mode 100644 spec/models/form/lettings/pages/uprn_spec.rb create mode 100644 spec/models/form/lettings/questions/address_line1_spec.rb create mode 100644 spec/models/form/lettings/questions/address_line2_spec.rb create mode 100644 spec/models/form/lettings/questions/county_spec.rb create mode 100644 spec/models/form/lettings/questions/postcode_for_full_address_spec.rb create mode 100644 spec/models/form/lettings/questions/town_or_city_spec.rb create mode 100644 spec/models/form/lettings/questions/uprn_confirmation_spec.rb create mode 100644 spec/models/form/lettings/questions/uprn_known_spec.rb create mode 100644 spec/models/form/lettings/questions/uprn_spec.rb 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/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/lettings/pages/address.rb b/app/models/form/lettings/pages/address.rb new file mode 100644 index 000000000..6f88bad0d --- /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 = "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/property_local_authority.rb b/app/models/form/lettings/pages/property_local_authority.rb index 2c64e3628..7692fd376 100644 --- a/app/models/form/lettings/pages/property_local_authority.rb +++ b/app/models/form/lettings/pages/property_local_authority.rb @@ -8,4 +8,12 @@ class Form::Lettings::Pages::PropertyLocalAuthority < ::Form::Page 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/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/questions/address_line1.rb b/app/models/form/lettings/questions/address_line1.rb new file mode 100644 index 000000000..6f82edf45 --- /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 + @question_number = 12 + 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/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/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/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..6e3ce0302 --- /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 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/property_information.rb b/app/models/form/lettings/subsections/property_information.rb index 6e20ea7cf..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,7 +25,22 @@ 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) diff --git a/app/models/form/sales/questions/address_line1.rb b/app/models/form/sales/questions/address_line1.rb index e8ccb17c0..2dd3a734e 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 + @question_number = 15 end def hidden_in_check_answers?(log, _current_user = nil) 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/lettings_log.rb b/app/models/lettings_log.rb index f8c817c56..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 @@ -679,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/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/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/spec/models/form/lettings/pages/address_spec.rb b/spec/models/form/lettings/pages/address_spec.rb new file mode 100644 index 000000000..e4cf044b8 --- /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("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/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/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..781b0a748 --- /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 eq(12) + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("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/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..1a0f810da --- /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 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/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb index 8b30964c3..2e7e58deb 100644 --- a/spec/models/form/lettings/subsections/property_information_spec.rb +++ b/spec/models/form/lettings/subsections/property_information_spec.rb @@ -9,28 +9,67 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model 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 diff --git a/spec/models/form/sales/questions/address_line1_spec.rb b/spec/models/form/sales/questions/address_line1_spec.rb index bc65c0646..27c0179e2 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 eq(15) + end + it "has the correct id" do expect(question.id).to eq("address_line1") end 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/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb index 43cbc69ce..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) } @@ -3010,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 231dc68c4..4bc90da37 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -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 From 3cb67623ac856c04aac9ccb104822fe10a7d44c2 Mon Sep 17 00:00:00 2001 From: James Rose Date: Wed, 22 Mar 2023 13:08:50 +0000 Subject: [PATCH 12/31] Update collection year end dates for 2022 onwards (#1453) This fixes a mistake I made in https://github.com/communitiesuk/submit-social-housing-lettings-and-sales-data/pull/1312 where I set the dates to July instead of June. --- app/models/form.rb | 4 ++-- config/forms/2022_2023.json | 2 +- spec/helpers/tasklist_helper_spec.rb | 4 ++-- spec/models/form_spec.rb | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/form.rb b/app/models/form.rb index 9fa908427..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) } diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index 6a1b8cc40..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": { diff --git a/spec/helpers/tasklist_helper_spec.rb b/spec/helpers/tasklist_helper_spec.rb index 5d75616ec..b4e26437b 100644 --- a/spec/helpers/tasklist_helper_spec.rb +++ b/spec/helpers/tasklist_helper_spec.rb @@ -85,7 +85,7 @@ RSpec.describe TasklistHelper do 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 @@ -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/models/form_spec.rb b/spec/models/form_spec.rb index 3236623c1..a1cf650c0 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -252,7 +252,7 @@ RSpec.describe Form, type: :model do 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 From 2edb63d59337b3fcbe583081d09cf987a513a822 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Wed, 22 Mar 2023 16:05:27 +0000 Subject: [PATCH 13/31] CLDC-2148-household-count-validation (#1452) * alter har dmax value for number of other people in the property, change a couple of depends on formulations to improve readability * correct linting error --- .../form/sales/pages/number_of_others_in_property.rb | 6 +++--- .../sales/questions/number_of_others_in_property.rb | 4 ++-- .../sales/pages/number_of_others_in_property_spec.rb | 12 ++++++------ .../questions/number_of_others_in_property_spec.rb | 12 ++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) 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/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/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/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 From 97bbf1924d306b8aa459262e046b3e4e2ddf9ac3 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Wed, 22 Mar 2023 16:05:46 +0000 Subject: [PATCH 14/31] CLDC-2016 mortgage validation (#1445) * add method to sales log and use in depends on to increase readability * increase minimum allowed value for mortgage * write tests and add validation error to config for new validation * write validation * adjust validation so it doesn't trigger when mortgage value is derived as 0 * correct linting problem and update tests to account for change in validation --- app/models/form/sales/pages/mortgage_amount.rb | 4 +--- .../form/sales/questions/mortgage_amount.rb | 2 +- app/models/sales_log.rb | 4 ++++ .../validations/sales/financial_validations.rb | 4 ++++ config/locales/en.yml | 1 + .../form/sales/pages/mortgage_amount_spec.rb | 4 +--- .../sales/questions/mortgage_amount_spec.rb | 6 +++--- .../sales/financial_validations_spec.rb | 18 ++++++++++++++++++ 8 files changed, 33 insertions(+), 10 deletions(-) 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/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/sales_log.rb b/app/models/sales_log.rb index ba2ea4fa8..2a6e1a6d3 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -243,6 +243,10 @@ class SalesLog < Log ownershipsch == 2 end + def mortgage_used? + mortgageused == 1 + end + def mortgage_not_used? mortgageused == 2 end diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb index faf436afa..61772be93 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 diff --git a/config/locales/en.yml b/config/locales/en.yml index 36d8b93f8..56caa6a59 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -316,6 +316,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: 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/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/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) } From ffcfa7db6eac61fca55a65fca5475c7b58be204f Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 23 Mar 2023 09:41:09 +0000 Subject: [PATCH 15/31] bulk upload age can be null (#1459) --- .../lettings/year2022/row_parser.rb | 30 +++++++++---------- .../lettings/year2023/row_parser.rb | 30 +++++++++---------- .../lettings/year2022/row_parser_spec.rb | 12 ++++++++ .../lettings/year2023/row_parser_spec.rb | 12 ++++++++ 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb index 560ed82b5..b2bc24110 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)") } @@ -848,28 +848,28 @@ private attributes["tenancylength"] = field_11 attributes["declaration"] = field_132 - attributes["age1_known"] = field_12 == "R" ? 1 : 0 + attributes["age1_known"] = (field_12 == "R" || field_12.blank? ? 1 : 0) 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"] = (field_13 == "R" || field_13.blank? ? 1 : 0) 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"] = (field_14 == "R" || field_14.blank? ? 1 : 0) 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"] = (field_15 == "R" || field_15.blank? ? 1 : 0) 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"] = (field_16 == "R" || field_16.blank? ? 1 : 0) 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"] = (field_17 == "R" || field_17.blank? ? 1 : 0) 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"] = (field_18 == "R" || field_18.blank? ? 1 : 0) 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"] = (field_19 == "R" || field_19.blank? ? 1 : 0) attributes["age8"] = field_19 if attributes["age8_known"].zero? && field_19&.match(/\A\d{1,3}\z|\AR\z/) attributes["sex1"] = field_20 diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index 724b1c2ef..69dc6aeca 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)") } @@ -790,28 +790,28 @@ private attributes["tenancylength"] = field_43 attributes["declaration"] = field_45 - attributes["age1_known"] = field_46 == "R" ? 1 : 0 + attributes["age1_known"] = (field_46 == "R" || field_46.blank? ? 1 : 0) 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"] = (field_52 == "R" || field_52.blank? ? 1 : 0) 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"] = (field_56 == "R" || field_56.blank? ? 1 : 0) 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"] = (field_60 == "R" || field_60.blank? ? 1 : 0) 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"] = (field_64 == "R" || field_64.blank? ? 1 : 0) 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"] = (field_68 == "R" || field_68.blank? ? 1 : 0) 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"] = (field_72 == "R" || field_72.blank? ? 1 : 0) 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"] = (field_76 == "R" || field_76.blank? ? 1 : 0) attributes["age8"] = field_76 if attributes["age8_known"].zero? && field_76&.match(/\A\d{1,3}\z|\AR\z/) attributes["sex1"] = field_47 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..f7848f690 100644 --- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb @@ -742,6 +742,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..53cd24ed8 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -700,6 +700,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" } } From 5c20a46a1b2144e438b181bc4eca00dae2a523d8 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Thu, 23 Mar 2023 13:01:25 +0000 Subject: [PATCH 16/31] CLDC-2143 Resolve more import validations (#1454) * Remove failing equity over max on import * Remove failing equity under min on import * Use LA instead of postcode if postcode is in invalid format * Do not backfill information about people indexed 7 and higher * Unskip test --- .../sales/financial_validations.rb | 4 +- app/models/validations/shared_validations.rb | 2 +- .../imports/sales_logs_import_service.rb | 13 ++- .../imports/sales_logs_import_service_spec.rb | 91 ++++++++++++++++++- 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb index 61772be93..8f81aa117 100644 --- a/app/models/validations/sales/financial_validations.rb +++ b/app/models/validations/sales/financial_validations.rb @@ -98,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/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/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb index c2844e019..e6f735b3e 100644 --- a/app/services/imports/sales_logs_import_service.rb +++ b/app/services/imports/sales_logs_import_service.rb @@ -214,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| @@ -544,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/spec/services/imports/sales_logs_import_service_spec.rb b/spec/services/imports/sales_logs_import_service_spec.rb index e41ffabaf..f0168ba11 100644 --- a/spec/services/imports/sales_logs_import_service_spec.rb +++ b/spec/services/imports/sales_logs_import_service_spec.rb @@ -439,6 +439,81 @@ 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" } @@ -501,7 +576,7 @@ RSpec.describe Imports::SalesLogsImportService do end it "intercepts the relevant validation error" do - expect(logger).to receive(:warn).with(/Enter a postcode in the correct format, for example AA1 1AA/) + 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 @@ -518,6 +593,20 @@ RSpec.describe Imports::SalesLogsImportService do 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" } From 0b973ceebdc1c5177e2a6d249ff95137f14cc754 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 23 Mar 2023 13:09:46 +0000 Subject: [PATCH 17/31] add new uprn and address fields to bulk upload (#1462) --- .../lettings/year2023/row_parser.rb | 7 +++ .../lettings/year2023/row_parser_spec.rb | 63 +++++++++++++++++++ spec/support/bulk_upload/log_to_csv.rb | 10 +-- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index 69dc6aeca..e4ba7cb82 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -939,6 +939,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 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 53cd24ed8..997624757 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -63,6 +63,9 @@ 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: {}) + 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 +201,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do field_35: now.strftime("%g"), field_4: "1", + + field_18: "100023336956", } end @@ -689,6 +694,64 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do 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], 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 From 2440e8a2efdf21673922c3afc2a0eeeadef4311b Mon Sep 17 00:00:00 2001 From: James Rose Date: Thu, 23 Mar 2023 15:56:41 +0000 Subject: [PATCH 18/31] Update service charge validations (#1428) * Update service charge validations * Create location deactivation periods instead of setting a scheme end date * Add test for deactivation period * Update ranges in tests * Remove scheme validation test * Check that the location gets confirmed --------- Co-authored-by: Kat --- app/models/validations/date_validations.rb | 7 ---- .../validations/financial_validations.rb | 8 ++-- .../imports/scheme_location_import_service.rb | 24 ++++++----- config/locales/en.yml | 8 ++-- .../validations/date_validations_spec.rb | 8 ---- .../validations/financial_validations_spec.rb | 42 +++++++++---------- .../scheme_location_import_service_spec.rb | 13 +++++- 7 files changed, 54 insertions(+), 56 deletions(-) diff --git a/app/models/validations/date_validations.rb b/app/models/validations/date_validations.rb index ee7789171..744f636dc 100644 --- a/app/models/validations/date_validations.rb +++ b/app/models/validations/date_validations.rb @@ -37,13 +37,6 @@ module Validations::DateValidations 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..71371ec71 100644 --- a/app/models/validations/financial_validations.rb +++ b/app/models/validations/financial_validations.rb @@ -132,12 +132,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: { 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/config/locales/en.yml b/config/locales/en.yml index 56caa6a59..215a611b4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -253,11 +253,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" diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb index cd6e38f50..410da4f0c 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) diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb index c2fe3b963..1f40f7cbc 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 }, 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) } From fa8676b8eaec6031d9265f1613fce673c7835a81 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:57:05 +0000 Subject: [PATCH 19/31] Lettings log import validations (#1463) * Clear import fields failing non_temp_accommodation validation * Clear joint tenancy if there is only 1 person in the household * Clear offered if the value is above the maximum of 20 * Display error message on ecstat * Remove ecstat if the income is too high for it --- .../validations/financial_validations.rb | 1 + .../validations/household_validations.rb | 2 +- .../validations/property_validations.rb | 2 +- app/models/validations/tenancy_validations.rb | 2 +- .../imports/lettings_logs_import_service.rb | 21 ++++ config/locales/en.yml | 2 + .../0ead17cb-1668-442d-898c-0d52879ff592.xml | 1 + .../lettings_logs_import_service_spec.rb | 111 ++++++++++++++++++ 8 files changed, 139 insertions(+), 3 deletions(-) diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb index 71371ec71..f39c17af7 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 diff --git a/app/models/validations/household_validations.rb b/app/models/validations/household_validations.rb index afa7867ff..0b871fce0 100644 --- a/app/models/validations/household_validations.rb +++ b/app/models/validations/household_validations.rb @@ -63,7 +63,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/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/imports/lettings_logs_import_service.rb b/app/services/imports/lettings_logs_import_service.rb index 9e5de20ba..ecd32c51d 100644 --- a/app/services/imports/lettings_logs_import_service.rb +++ b/app/services/imports/lettings_logs_import_service.rb @@ -311,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| diff --git a/config/locales/en.yml b/config/locales/en.yml index 215a611b4..526dd8347 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -272,6 +272,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" 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/services/imports/lettings_logs_import_service_spec.rb b/spec/services/imports/lettings_logs_import_service_spec.rb index 5b56efdfb..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" @@ -560,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 From 0966bd6869b3eabbea1951615548f9268ae3e253 Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Fri, 24 Mar 2023 09:25:56 +0000 Subject: [PATCH 20/31] CLDC-2020 Add saledate less than 2 weeks from today validation (#1446) * feat: copy updates and add saledate validation * feat: rename methods and enable feature toggle * feat: rename methods and enable feature toggle * test: add tests * refactor: ruby police * feat: fix tests * refactor: readability * feat: enable validation on review apps * db:update --- app/models/validations/date_validations.rb | 2 +- .../validations/sales/setup_validations.rb | 10 +++- config/initializers/feature_toggle.rb | 4 ++ config/locales/en.yml | 17 ++++--- db/schema.rb | 2 +- spec/helpers/tasklist_helper_spec.rb | 4 +- spec/models/sales_log_spec.rb | 2 +- .../sale_information_validations_spec.rb | 8 +-- .../sales/setup_validations_spec.rb | 50 +++++++++++++++---- spec/requests/sales_logs_controller_spec.rb | 19 +++++-- 10 files changed, 87 insertions(+), 31 deletions(-) diff --git a/app/models/validations/date_validations.rb b/app/models/validations/date_validations.rb index 744f636dc..ae5d7ee19 100644 --- a/app/models/validations/date_validations.rb +++ b/app/models/validations/date_validations.rb @@ -33,7 +33,7 @@ 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 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/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb index e00a7190b..6c889bcc5 100644 --- a/config/initializers/feature_toggle.rb +++ b/config/initializers/feature_toggle.rb @@ -12,6 +12,10 @@ class FeatureToggle 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 526dd8347..a7a5e5400 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: @@ -470,16 +471,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}" diff --git a/db/schema.rb b/db/schema.rb index 92b0d9a63..225129dfd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -569,8 +569,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do t.string "town_or_city" t.string "county" t.integer "nationalbuy2" - t.integer "student_not_child_value_check" 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" t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true diff --git a/spec/helpers/tasklist_helper_spec.rb b/spec/helpers/tasklist_helper_spec.rb index b4e26437b..bd1bdb61f 100644 --- a/spec/helpers/tasklist_helper_spec.rb +++ b/spec/helpers/tasklist_helper_spec.rb @@ -81,7 +81,7 @@ 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( @@ -92,7 +92,7 @@ RSpec.describe TasklistHelper do 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 diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb index 4bc90da37..511f1820b 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -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 diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index c34738de7..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 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/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 From c9473c9362ee656f3dff210f99696359923b0f4a Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Fri, 24 Mar 2023 12:03:02 +0000 Subject: [PATCH 21/31] cannot create log if owning or mangaging data bad (#1464) - for bulk upload --- .../lettings/year2022/row_parser.rb | 48 +++++++++++++------ .../lettings/year2023/row_parser.rb | 43 +++++++++++------ .../lettings/year2022/row_parser_spec.rb | 24 ++++++++++ .../lettings/year2023/row_parser_spec.rb | 32 +++++++++++++ 4 files changed, 118 insertions(+), 29 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb index b2bc24110..d9cc99505 100644 --- a/app/services/bulk_upload/lettings/year2022/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb @@ -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 diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index e4ba7cb82..dc2a04a66 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -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 @@ -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 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 f7848f690..6355bb3bd 100644 --- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb @@ -634,6 +634,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 +646,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 +682,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 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 997624757..4d745f21e 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -585,12 +585,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 @@ -623,12 +639,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 From cf46ae46fe64490f63129b65b8e57f584de764f1 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Fri, 24 Mar 2023 14:18:34 +0000 Subject: [PATCH 22/31] CLDC-2131 Update pregnancy validation (#1458) * Remove hard pregnancy validation and update soft validation * Remove validate_pregnancy references * Don't care about the age in gender validation --- .../validations/household_validations.rb | 6 -- app/models/validations/soft_validations.rb | 10 ++- config/locales/en.yml | 4 +- spec/features/form/page_routing_spec.rb | 1 - .../validations/household_validations_spec.rb | 67 ------------------- .../validations/soft_validations_spec.rb | 11 ++- spec/requests/form_controller_spec.rb | 4 -- 7 files changed, 18 insertions(+), 85 deletions(-) diff --git a/app/models/validations/household_validations.rb b/app/models/validations/household_validations.rb index 0b871fce0..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) 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/config/locales/en.yml b/config/locales/en.yml index a7a5e5400..7e514b17f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -335,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" @@ -516,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: 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/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/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb index b71d91a62..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 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") From 8d9c577e6979e93f9711b0f4fd384c79d1d5b2ff Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Fri, 24 Mar 2023 14:32:57 +0000 Subject: [PATCH 23/31] disable start date validation for staging (#1466) --- config/initializers/feature_toggle.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb index 6c889bcc5..de1c11fbd 100644 --- a/config/initializers/feature_toggle.rb +++ b/config/initializers/feature_toggle.rb @@ -5,7 +5,7 @@ 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? From ea810beab1c3b8ce73567fd74f5bb6f70ab7e21b Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Fri, 24 Mar 2023 14:56:57 +0000 Subject: [PATCH 24/31] Address UPRN PO review (#1467) * Fix question number rendering * Update title copy --- app/models/form/lettings/pages/address.rb | 2 +- app/models/form/lettings/questions/address_line1.rb | 2 +- app/models/form/lettings/questions/uprn_known.rb | 2 +- app/models/form/sales/pages/address.rb | 2 +- app/models/form/sales/questions/address_line1.rb | 2 +- app/models/form/sales/questions/uprn_known.rb | 2 +- spec/models/form/lettings/pages/address_spec.rb | 2 +- spec/models/form/lettings/questions/address_line1_spec.rb | 4 ++-- spec/models/form/lettings/questions/uprn_known_spec.rb | 2 +- spec/models/form/sales/pages/address_spec.rb | 2 +- spec/models/form/sales/questions/address_line1_spec.rb | 4 ++-- spec/models/form/sales/questions/uprn_known_spec.rb | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/models/form/lettings/pages/address.rb b/app/models/form/lettings/pages/address.rb index 6f88bad0d..cf6f73036 100644 --- a/app/models/form/lettings/pages/address.rb +++ b/app/models/form/lettings/pages/address.rb @@ -2,7 +2,7 @@ class Form::Lettings::Pages::Address < ::Form::Page def initialize(id, hsh, subsection) super @id = "address" - @header = "What is the property's address?" + @header = "Q12 - What is the property's address?" end def questions diff --git a/app/models/form/lettings/questions/address_line1.rb b/app/models/form/lettings/questions/address_line1.rb index 6f82edf45..b3288c82c 100644 --- a/app/models/form/lettings/questions/address_line1.rb +++ b/app/models/form/lettings/questions/address_line1.rb @@ -6,7 +6,7 @@ class Form::Lettings::Questions::AddressLine1 < ::Form::Question @header = "Address line 1" @type = "text" @plain_label = true - @question_number = 12 + @check_answer_label = "Q12 - Address" end def hidden_in_check_answers?(log, _current_user = nil) diff --git a/app/models/form/lettings/questions/uprn_known.rb b/app/models/form/lettings/questions/uprn_known.rb index 6e3ce0302..d206885fb 100644 --- a/app/models/form/lettings/questions/uprn_known.rb +++ b/app/models/form/lettings/questions/uprn_known.rb @@ -3,7 +3,7 @@ class Form::Lettings::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/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/questions/address_line1.rb b/app/models/form/sales/questions/address_line1.rb index 2dd3a734e..a71229970 100644 --- a/app/models/form/sales/questions/address_line1.rb +++ b/app/models/form/sales/questions/address_line1.rb @@ -6,7 +6,7 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question @header = "Address line 1" @type = "text" @plain_label = true - @question_number = 15 + @check_answer_label = "Q15 - Address" end def hidden_in_check_answers?(log, _current_user = nil) 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/spec/models/form/lettings/pages/address_spec.rb b/spec/models/form/lettings/pages/address_spec.rb index e4cf044b8..230d6964f 100644 --- a/spec/models/form/lettings/pages/address_spec.rb +++ b/spec/models/form/lettings/pages/address_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Form::Lettings::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("Q12 - What is the property's address?") end it "has the correct description" do diff --git a/spec/models/form/lettings/questions/address_line1_spec.rb b/spec/models/form/lettings/questions/address_line1_spec.rb index 781b0a748..e2600f0cc 100644 --- a/spec/models/form/lettings/questions/address_line1_spec.rb +++ b/spec/models/form/lettings/questions/address_line1_spec.rb @@ -20,11 +20,11 @@ RSpec.describe Form::Lettings::Questions::AddressLine1, type: :model do end it "has the correct question_number" do - expect(question.question_number).to eq(12) + expect(question.question_number).to be_nil end it "has the correct check_answer_label" do - expect(question.check_answer_label).to eq("Address") + expect(question.check_answer_label).to eq("Q12 - Address") end it "has the correct type" do diff --git a/spec/models/form/lettings/questions/uprn_known_spec.rb b/spec/models/form/lettings/questions/uprn_known_spec.rb index 1a0f810da..07eb72f8d 100644 --- a/spec/models/form/lettings/questions/uprn_known_spec.rb +++ b/spec/models/form/lettings/questions/uprn_known_spec.rb @@ -16,7 +16,7 @@ RSpec.describe Form::Lettings::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/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/questions/address_line1_spec.rb b/spec/models/form/sales/questions/address_line1_spec.rb index 27c0179e2..f037f41cd 100644 --- a/spec/models/form/sales/questions/address_line1_spec.rb +++ b/spec/models/form/sales/questions/address_line1_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Form::Sales::Questions::AddressLine1, type: :model do end it "has the correct question_number" do - expect(question.question_number).to eq(15) + expect(question.question_number).to be_nil end it "has the correct id" do @@ -24,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/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 From 9f3b2bba28955e8f1bcd0f31f53ee17f3878f793 Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Fri, 24 Mar 2023 15:44:09 +0000 Subject: [PATCH 25/31] CLDC-2032 test log creation in crossover period (#1420) * ensure that no form is added to the forms hash under the key "nil" * add a test to ensure that the form handler does not add outdated forms to the forms hash with key nil * remove unnecessary singleton reinitialisation * remove a duplicated Timecop around block --- app/models/form_handler.rb | 2 +- spec/models/form_handler_spec.rb | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) 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/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 From d42a37c08e6d7c09abe852ee4fb45bca23c1eac7 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Fri, 24 Mar 2023 18:25:15 +0000 Subject: [PATCH 26/31] permit at least one housing need (#1470) --- .../bulk_upload/lettings/year2022/row_parser.rb | 2 +- .../bulk_upload/lettings/year2023/row_parser.rb | 2 +- .../bulk_upload/lettings/year2022/row_parser_spec.rb | 10 ++++++++++ .../bulk_upload/lettings/year2023/row_parser_spec.rb | 10 ++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb index d9cc99505..34b65700e 100644 --- a/app/services/bulk_upload/lettings/year2022/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb @@ -520,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")) diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index dc2a04a66..3c214a204 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -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")) 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 6355bb3bd..29c48006e 100644 --- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb @@ -475,6 +475,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" } } 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 4d745f21e..1bb4dc99a 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -438,6 +438,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" } } From b262178923c80b945f1f26c7c63c13348aaf9bb6 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Fri, 24 Mar 2023 18:25:52 +0000 Subject: [PATCH 27/31] bulk upload ageN check depends on other fields (#1468) - if other fields for a person are present but the age is not we ask them to enter their age --- .../lettings/year2022/row_parser.rb | 71 +++++++++++++------ .../lettings/year2023/row_parser.rb | 71 +++++++++++++------ .../lettings/year2022/row_parser_spec.rb | 10 +++ .../lettings/year2023/row_parser_spec.rb | 10 +++ 4 files changed, 116 insertions(+), 46 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb index 34b65700e..432897d0b 100644 --- a/app/services/bulk_upload/lettings/year2022/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb @@ -866,28 +866,28 @@ private attributes["tenancylength"] = field_11 attributes["declaration"] = field_132 - attributes["age1_known"] = (field_12 == "R" || field_12.blank? ? 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" || field_13.blank? ? 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" || field_14.blank? ? 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" || field_15.blank? ? 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" || field_16.blank? ? 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" || field_17.blank? ? 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" || field_18.blank? ? 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" || field_19.blank? ? 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 @@ -920,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 @@ -1112,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 @@ -1129,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 3c214a204..d1689b2dd 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -805,28 +805,28 @@ private attributes["tenancylength"] = field_43 attributes["declaration"] = field_45 - attributes["age1_known"] = (field_46 == "R" || field_46.blank? ? 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" || field_52.blank? ? 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" || field_56.blank? ? 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" || field_60.blank? ? 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" || field_64.blank? ? 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" || field_68.blank? ? 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" || field_72.blank? ? 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" || field_76.blank? ? 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 @@ -859,13 +859,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 @@ -1077,36 +1077,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/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb index 29c48006e..bada35dad 100644 --- a/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb @@ -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 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 1bb4dc99a..7dc1e177b 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -733,6 +733,16 @@ 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 From 5aba3ef9a966ffffce13cd5438ddd4c0727f842d Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Mon, 27 Mar 2023 09:01:39 +0100 Subject: [PATCH 28/31] Run rent validations when >= 4 beds (#1465) --- app/models/validations/financial_validations.rb | 11 +++++++++-- spec/models/validations/financial_validations_spec.rb | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb index f39c17af7..fc1c44585 100644 --- a/app/models/validations/financial_validations.rb +++ b/app/models/validations/financial_validations.rb @@ -188,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 @@ -201,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/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb index 1f40f7cbc..8cb777029 100644 --- a/spec/models/validations/financial_validations_spec.rb +++ b/spec/models/validations/financial_validations_spec.rb @@ -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) From be6e6585bb82c19218f6d380776061794d0958a1 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Mon, 27 Mar 2023 09:40:43 +0100 Subject: [PATCH 29/31] bulk upload maps new field errors (#1471) --- .../lettings/year2023/row_parser.rb | 6 +++++ .../lettings/year2023/row_parser_spec.rb | 23 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb index d1689b2dd..2fc61921f 100644 --- a/app/services/bulk_upload/lettings/year2023/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb @@ -766,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 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 7dc1e177b..bc35388d7 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -63,8 +63,19 @@ 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: {}) + .to_return(status: 200, body:, headers: {}) parser.valid? end @@ -712,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 }) } From bc722ab1ff2a9d34bd4f2571803695892c554be8 Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Mon, 27 Mar 2023 10:28:41 +0100 Subject: [PATCH 30/31] British Summer Time fixes (#1473) --- spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb | 2 +- spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 bada35dad..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:) } 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 bc35388d7..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) } From b5c2584a6e4a042e12f488626cf4723d95da93cf Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Mon, 27 Mar 2023 14:44:53 +0100 Subject: [PATCH 31/31] CLDC-1854 Make schemes with 0 locations be incomplete rather than active (#1456) * feat: update scheme status so incomplete unless has active locations * feat: change active -> completed * feat: change to confirmed to add clarification in code * feat: fix tests * refactor: rubocop * feat: add tests for incomplete schemes * refactor: linting * refactor: simplify --- app/models/location.rb | 1 + app/models/scheme.rb | 2 +- spec/helpers/schemes_helper_spec.rb | 273 ++++++++++-------- spec/models/scheme_spec.rb | 1 + .../validations/date_validations_spec.rb | 2 + .../validations/setup_validations_spec.rb | 2 + spec/requests/schemes_controller_spec.rb | 7 + 7 files changed, 174 insertions(+), 114 deletions(-) diff --git a/app/models/location.rb b/app/models/location.rb index 48689ef71..6050a05cf 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/scheme.rb b/app/models/scheme.rb index ca3624e3a..1ab65ea32 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/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/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 410da4f0c..18912b1c8 100644 --- a/spec/models/validations/date_validations_spec.rb +++ b/spec/models/validations/date_validations_spec.rb @@ -165,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 @@ -189,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/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/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