From 6c5391ad1cad6cdb0fc31873f923230dd57df495 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Wed, 30 Mar 2022 14:08:50 +0100 Subject: [PATCH] Cldc 1065 soft validations (#434) * change get_question form method to prioritise the routed to questions * Add soft validation and interruption screen for basic rent * get previous page that was routed to and display the same error for both soft validations * Separate max and min error screens * add a test for getting the previous page * Update content and add more tests for previous page --- app/helpers/interuption_screen_helper.rb | 11 +-- app/models/case_log.rb | 12 +++ app/models/form.rb | 15 +++- app/models/form/question.rb | 2 +- .../validations/household_validations.rb | 2 +- app/models/validations/soft_validations.rb | 14 ++++ config/forms/2021_2022.json | 54 +++++++++++++- config/locales/en.yml | 11 ++- .../20220328133331_add_rent_value_check.rb | 5 ++ db/schema.rb | 1 + spec/features/form/validations_spec.rb | 4 +- spec/fixtures/exports/case_logs.xml | 1 + spec/fixtures/forms/2021_2022.json | 4 +- .../helpers/interuption_screen_helper_spec.rb | 10 +-- spec/models/form_spec.rb | 40 ++++++++++ .../validations/household_validations_spec.rb | 2 +- .../validations/soft_validations_spec.rb | 73 +++++++++++++++++++ 17 files changed, 233 insertions(+), 28 deletions(-) create mode 100644 db/migrate/20220328133331_add_rent_value_check.rb create mode 100644 spec/models/validations/soft_validations_spec.rb diff --git a/app/helpers/interuption_screen_helper.rb b/app/helpers/interuption_screen_helper.rb index e189c4d88..393134f83 100644 --- a/app/helpers/interuption_screen_helper.rb +++ b/app/helpers/interuption_screen_helper.rb @@ -1,13 +1,10 @@ module InteruptionScreenHelper def display_informative_text(informative_text, case_log) - translation_questions = informative_text["argument"].map { |x| case_log.form.get_question(x) } + arguments = informative_text["argument"].map { |x, type| type == "question" ? case_log.form.get_question(x, case_log).answer_label(case_log) : case_log.public_send(x) } + keys = informative_text["argument"].keys + begin - case translation_questions.count - when 2 - translation = I18n.t(informative_text["translation"], informative_text["argument"][0].to_sym => translation_questions[0].answer_label(case_log), informative_text["argument"][1].to_sym => translation_questions[1].answer_label(case_log)) - when 1 - translation = I18n.t(informative_text["translation"], informative_text["argument"][0].to_sym => translation_questions[0].answer_label(case_log)) - end + translation = I18n.t(informative_text["translation"], keys[0].present? ? keys[0].to_sym : "" => arguments[0], keys[1].present? ? keys[1].to_sym : "" => arguments[1], keys[2].present? ? keys[2].to_sym : "" => arguments[2]) rescue StandardError return "" end diff --git a/app/models/case_log.rb b/app/models/case_log.rb index a24bc8a7b..d3271083c 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -124,6 +124,10 @@ class CaseLog < ApplicationRecord net_income_in_soft_min_range? || net_income_in_soft_max_range? end + def rent_in_soft_validation_range? + rent_in_soft_min_range? || rent_in_soft_max_range? + end + def given_reasonable_preference? reasonpref == 1 end @@ -281,6 +285,14 @@ class CaseLog < ApplicationRecord [30, 31].any?(prevten) end + def soft_min + LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:).soft_min + end + + def soft_max + LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:).soft_max + end + private PIO = Postcodes::IO.new diff --git a/app/models/form.rb b/app/models/form.rb index b68eef18c..3f1a83224 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -24,8 +24,10 @@ class Form pages.find { |p| p.id == id.to_s.underscore } end - def get_question(id) - questions.find { |q| q.id == id.to_s.underscore } + def get_question(id, case_log) + all_questions = questions.select { |q| q.id == id.to_s.underscore } + routed_question = all_questions.find { |q| q.page.routed_to?(case_log) } + routed_question || all_questions[0] end def subsection_for_page(page) @@ -35,7 +37,7 @@ class Form def next_page(page, case_log) page_ids = subsection_for_page(page).pages.map(&:id) page_index = page_ids.index(page.id) - page_id = page.id.include?("value_check") && case_log[page.id] == 1 ? page_ids[page_index - 1] : page_ids[page_index + 1] + page_id = page.id.include?("value_check") && case_log[page.questions[0].id] == 1 && page.routed_to?(case_log) ? previous_page(page_ids, page_index, case_log) : page_ids[page_index + 1] nxt_page = get_page(page_id) return :check_answers if nxt_page.nil? @@ -142,4 +144,11 @@ class Form subsection_ids = subsections.map(&:id) subsection.id == subsection_ids[subsection_ids.length - 1] && next_page(page, case_log) == :check_answers end + + def previous_page(page_ids, page_index, case_log) + prev_page = get_page(page_ids[page_index - 1]) + return prev_page.id if prev_page.routed_to?(case_log) + + previous_page(page_ids, page_index - 1, case_log) + end end diff --git a/app/models/form/question.rb b/app/models/form/question.rb index 602713c22..03210ba0f 100644 --- a/app/models/form/question.rb +++ b/app/models/form/question.rb @@ -49,7 +49,7 @@ class Form::Question return [] unless inferred_answers enabled_inferred_answers(inferred_answers, case_log).keys.map do |x| - form.get_question(x).label_from_value(case_log[x]) + form.get_question(x, case_log).label_from_value(case_log[x]) end end diff --git a/app/models/validations/household_validations.rb b/app/models/validations/household_validations.rb index 2528a41a4..cd8bc912b 100644 --- a/app/models/validations/household_validations.rb +++ b/app/models/validations/household_validations.rb @@ -88,7 +88,7 @@ module Validations::HouseholdValidations end if record.is_internal_transfer? && [3, 4, 7, 9, 10, 13, 14, 19, 21, 23, 24, 25, 26, 27, 28, 29].include?(record.prevten) - label = record.form.get_question("prevten").present? ? record.form.get_question("prevten").label_from_value(record.prevten) : "" + label = record.form.get_question("prevten", record).present? ? record.form.get_question("prevten", record).label_from_value(record.prevten) : "" record.errors.add :prevten, I18n.t("validations.household.prevten.internal_transfer", prevten: label) record.errors.add :referral, I18n.t("validations.household.referral.prevten_invalid", prevten: label) end diff --git a/app/models/validations/soft_validations.rb b/app/models/validations/soft_validations.rb index ec217ca77..739649dd4 100644 --- a/app/models/validations/soft_validations.rb +++ b/app/models/validations/soft_validations.rb @@ -24,4 +24,18 @@ module Validations::SoftValidations weekly_net_income.between?(applicable_income_range.hard_min, applicable_income_range.soft_min) end + + def rent_in_soft_min_range? + return unless brent && weekly_value(brent) && startdate + + rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:) + rent_range.present? && weekly_value(brent).between?(rent_range.hard_min, rent_range.soft_min) + end + + def rent_in_soft_max_range? + return unless brent && weekly_value(brent) && startdate + + rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:) + rent_range.present? && weekly_value(brent).between?(rent_range.soft_max, rent_range.hard_max) + end end diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index a23d9d4f8..a69b5916a 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -4539,12 +4539,12 @@ } } }, - "check_income_amount": { + "net_income_value_check": { "depends_on": [{ "net_income_soft_validation_triggered?": true }], - "title_text": "Net income is outside the expected range based on the main tenant’s working situation", + "title_text": "Net income is outside the expected range based on the lead tenant’s working situation", "informative_text": { "translation": "soft_validations.net_income.hint_text", - "argument": ["ecstat1", "earnings"] + "argument": {"ecstat1": "question", "earnings": "question"} }, "questions": { "net_income_value_check": { @@ -5534,6 +5534,54 @@ } ] }, + "min_rent_value_check": { + "depends_on": [{ "rent_in_soft_min_range?": true }], + "title_text": "Rent value is outside of the expected range", + "informative_text": { + "translation": "soft_validations.rent.min.hint_text", + "argument": {"la": "question", "soft_min": "method", "brent":"question"} + }, + "questions": { + "rent_value_check": { + "check_answer_label": "Rent soft validation", + "hidden_in_check_answers": true, + "header": "Are you sure this is correct?", + "type": "interruption_screen", + "answer_options": { + "0": { + "value":"Yes" + }, + "1": { + "value":"No" + } + } + } + } + }, + "max_rent_value_check": { + "depends_on": [{ "rent_in_soft_max_range?": true }], + "title_text": "Rent value is outside of the expected range", + "informative_text": { + "translation": "soft_validations.rent.max.hint_text", + "argument": {"la": "question", "soft_max": "method", "brent":"question"} + }, + "questions": { + "rent_value_check": { + "check_answer_label": "Rent soft validation", + "hidden_in_check_answers": true, + "header": "Are you sure this is correct?", + "type": "interruption_screen", + "answer_options": { + "0": { + "value":"Yes" + }, + "1": { + "value":"No" + } + } + } + } + }, "outstanding": { "header": "", "description": "", diff --git a/config/locales/en.yml b/config/locales/en.yml index 0f8227d20..f659bef3e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -219,11 +219,16 @@ en: soft_validations: net_income: - hint_text: "

You told us the main tenant’s working situation is: %{ecstat1}

The household income you have entered is %{earnings}

" + hint_text: "

You told us the lead tenant’s working situation is: %{ecstat1}

The household income you have entered is %{earnings}

" in_soft_min_range: - message: "Net income is lower than expected based on the main tenant’s working situation. Are you sure this is correct?" + message: "Net income is lower than expected based on the lead tenant’s working situation. Are you sure this is correct?" in_soft_max_range: - message: "Net income is higher than expected based on the main tenant’s working situation. Are you sure this is correct?" + message: "Net income is higher than expected based on the lead tenant’s working situation. Are you sure this is correct?" + rent: + min: + hint_text: "

The minimum rent for a property in %{la} is £%{soft_min} every week.

You entered %{brent}

" + max: + hint_text: "

The maximum rent for a property in %{la} is £%{soft_max} every week.

You entered %{brent}

" devise: two_factor_authentication: success: "Two factor authentication successful." diff --git a/db/migrate/20220328133331_add_rent_value_check.rb b/db/migrate/20220328133331_add_rent_value_check.rb new file mode 100644 index 000000000..c06b0dbd7 --- /dev/null +++ b/db/migrate/20220328133331_add_rent_value_check.rb @@ -0,0 +1,5 @@ +class AddRentValueCheck < ActiveRecord::Migration[7.0] + def change + add_column :case_logs, :rent_value_check, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index c5592dc25..f92f6a2d9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -231,6 +231,7 @@ ActiveRecord::Schema[7.0].define(version: 202202071123100) do t.string "relat6" t.string "relat7" t.string "relat8" + t.integer "rent_value_check" t.index ["managing_organisation_id"], name: "index_case_logs_on_managing_organisation_id" t.index ["owning_organisation_id"], name: "index_case_logs_on_owning_organisation_id" end diff --git a/spec/features/form/validations_spec.rb b/spec/features/form/validations_spec.rb index 34f6fbfd5..e1947bf87 100644 --- a/spec/features/form/validations_spec.rb +++ b/spec/features/form/validations_spec.rb @@ -130,8 +130,8 @@ RSpec.describe "validations" do choose("case-log-incfreq-0-field", allow_label_click: true) click_button("Save and continue") expect(page).to have_current_path("/logs/#{case_log.id}/net-income-value-check") - expect(page).to have_content("Net income is outside the expected range based on the main tenant’s working situation") - expect(page).to have_content("You told us the main tenant’s working situation is: Full-time – 30 hours or more") + expect(page).to have_content("Net income is outside the expected range based on the lead tenant’s working situation") + expect(page).to have_content("You told us the lead tenant’s working situation is: Full-time – 30 hours or more") expect(page).to have_content("The household income you have entered is £750.00 every week") choose("case-log-net-income-value-check-0-field", allow_label_click: true) click_button("Save and continue") diff --git a/spec/fixtures/exports/case_logs.xml b/spec/fixtures/exports/case_logs.xml index e64b91d20..1e05d6dc7 100644 --- a/spec/fixtures/exports/case_logs.xml +++ b/spec/fixtures/exports/case_logs.xml @@ -173,5 +173,6 @@ + diff --git a/spec/fixtures/forms/2021_2022.json b/spec/fixtures/forms/2021_2022.json index 8bd6c662e..c61582c2f 100644 --- a/spec/fixtures/forms/2021_2022.json +++ b/spec/fixtures/forms/2021_2022.json @@ -559,10 +559,10 @@ }, "net_income_value_check": { "depends_on": [{ "net_income_soft_validation_triggered?": true }], - "title_text": "Net income is outside the expected range based on the main tenant’s working situation", + "title_text": "Net income is outside the expected range based on the lead tenant’s working situation", "informative_text": { "translation": "soft_validations.net_income.hint_text", - "argument": ["ecstat1", "earnings"] + "argument": {"ecstat1": "question", "earnings": "question"} }, "questions": { "net_income_value_check": { diff --git a/spec/helpers/interuption_screen_helper_spec.rb b/spec/helpers/interuption_screen_helper_spec.rb index 3ad158857..efcf4d1e2 100644 --- a/spec/helpers/interuption_screen_helper_spec.rb +++ b/spec/helpers/interuption_screen_helper_spec.rb @@ -22,10 +22,10 @@ RSpec.describe InteruptionScreenHelper do it "returns correct informative text" do informative_text = { "translation" => "soft_validations.net_income.hint_text", - "argument" => %w[ecstat1 earnings], + "argument" => { "ecstat1": "question", "earnings": "question" }, } expect(display_informative_text(informative_text, case_log)) - .to eq("

You told us the main tenant’s working situation is: Full-time – 30 hours or more

The household income you have entered is £750.00 every week

") + .to eq("

You told us the lead tenant’s working situation is: Full-time – 30 hours or more

The household income you have entered is £750.00 every week

") end end @@ -33,7 +33,7 @@ RSpec.describe InteruptionScreenHelper do it "returns correct informative text" do informative_text = { "translation" => "test.one_argument", - "argument" => %w[ecstat1], + "argument" => { "ecstat1": "question" }, } expect(display_informative_text(informative_text, case_log)) .to eq("This is based on the tenant’s work situation: Full-time – 30 hours or more") @@ -45,7 +45,7 @@ RSpec.describe InteruptionScreenHelper do it "returns correct informative text" do informative_text = { "translation" => "test.one_argument", - "argument" => %w[ecstat1 earnings], + "argument" => { "ecstat1": "question", "earnings": "question" }, } expect(display_informative_text(informative_text, case_log)) .to eq("This is based on the tenant’s work situation: Full-time – 30 hours or more") @@ -56,7 +56,7 @@ RSpec.describe InteruptionScreenHelper do it "returns an empty string" do informative_text = { "translation" => "soft_validations.net_income.hint_text", - "argument" => %w[ecstat1], + "argument" => { "ecstat1": "question" }, } expect(display_informative_text(informative_text, case_log)) .to eq("") diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index 34c2ab929..61387969b 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -8,10 +8,50 @@ RSpec.describe Form, type: :model do describe ".next_page" do let(:previous_page) { form.get_page("person_1_age") } + let(:value_check_previous_page) { form.get_page("net_income_value_check") } it "returns the next page given the previous" do expect(form.next_page(previous_page, case_log)).to eq("person_1_gender") end + + context "when the current page is a value check page" do + before do + case_log.incfreq = 0 + case_log.earnings = 140 + case_log.ecstat1 = 1 + end + + it "returns the previous page if answer is `No` and the page is routed to" do + case_log.net_income_value_check = 1 + expect(form.next_page(value_check_previous_page, case_log)).to eq("net_income") + end + + it "returns the next page if answer is `Yes` answer and the page is routed to" do + case_log.net_income_value_check = 0 + expect(form.next_page(value_check_previous_page, case_log)).to eq("net_income_uc_proportion") + end + end + end + + describe ".previous_page" do + context "when the current page is not a value check page" do + let!(:subsection) { form.get_subsection("conditional_question") } + let!(:page_ids) { subsection.pages.map(&:id) } + + before do + case_log.preg_occ = 1 + end + + it "returns the previous page if the page is routed to" do + page_index = page_ids.index("conditional_question_no_second_page") + expect(form.previous_page(page_ids, page_index, case_log)).to eq("conditional_question_no_page") + end + + it "returns the page before the previous one if the previous page is not routed to" do + page_index = page_ids.index("conditional_question_no_page") + expect(form.previous_page(page_ids, page_index, case_log)).to eq("conditional_question") + end + end end describe "next_page_redirect_path" do diff --git a/spec/models/validations/household_validations_spec.rb b/spec/models/validations/household_validations_spec.rb index de78e01d9..9d1a00282 100644 --- a/spec/models/validations/household_validations_spec.rb +++ b/spec/models/validations/household_validations_spec.rb @@ -86,7 +86,7 @@ RSpec.describe Validations::HouseholdValidations do end end - context "and they are the main tenant and under 51" do + context "and they are the lead tenant and under 51" do it "pregnancy can be yes" do record.preg_occ = 0 record.sex1 = "F" diff --git a/spec/models/validations/soft_validations_spec.rb b/spec/models/validations/soft_validations_spec.rb new file mode 100644 index 000000000..461cfe561 --- /dev/null +++ b/spec/models/validations/soft_validations_spec.rb @@ -0,0 +1,73 @@ +require "rails_helper" + +RSpec.describe Validations::SoftValidations do + let(:record) { FactoryBot.create(:case_log) } + + describe "rent min max validations" do + before do + LaRentRange.create!( + ranges_rent_id: "1", + la: "E07000223", + beds: 1, + lettype: 1, + soft_min: 12.41, + soft_max: 89.54, + hard_min: 9.87, + hard_max: 100.99, + start_year: 2021, + ) + + record.la = "E07000223" + record.lettype = 1 + record.beds = 1 + record.period = 1 + record.startdate = Time.zone.local(2021, 10, 10) + end + + context "when validating soft min" do + before do + record.brent = 11 + end + + it "returns out of soft min range if no startdate is given" do + record.startdate = nil + expect(record) + .not_to be_rent_in_soft_min_range + end + + it "returns out of soft min range if no brent is given" do + record.brent = nil + expect(record) + .not_to be_rent_in_soft_min_range + end + + it "returns true if weekly rent is in soft min range" do + expect(record) + .to be_rent_in_soft_min_range + end + end + + context "when validating soft max" do + before do + record.brent = 90 + end + + it "returns out of soft max range if no startdate is given" do + record.startdate = nil + expect(record) + .not_to be_rent_in_soft_max_range + end + + it "returns out of soft max range if no brent is given" do + record.brent = nil + expect(record) + .not_to be_rent_in_soft_max_range + end + + it "returns true if weekly rent is in soft max range" do + expect(record) + .to be_rent_in_soft_max_range + end + end + end +end