Browse Source

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
pull/436/head
kosiakkatrina 3 years ago committed by GitHub
parent
commit
6c5391ad1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      app/helpers/interuption_screen_helper.rb
  2. 12
      app/models/case_log.rb
  3. 15
      app/models/form.rb
  4. 2
      app/models/form/question.rb
  5. 2
      app/models/validations/household_validations.rb
  6. 14
      app/models/validations/soft_validations.rb
  7. 54
      config/forms/2021_2022.json
  8. 11
      config/locales/en.yml
  9. 5
      db/migrate/20220328133331_add_rent_value_check.rb
  10. 1
      db/schema.rb
  11. 4
      spec/features/form/validations_spec.rb
  12. 1
      spec/fixtures/exports/case_logs.xml
  13. 4
      spec/fixtures/forms/2021_2022.json
  14. 10
      spec/helpers/interuption_screen_helper_spec.rb
  15. 40
      spec/models/form_spec.rb
  16. 2
      spec/models/validations/household_validations_spec.rb
  17. 73
      spec/models/validations/soft_validations_spec.rb

11
app/helpers/interuption_screen_helper.rb

@ -1,13 +1,10 @@
module InteruptionScreenHelper module InteruptionScreenHelper
def display_informative_text(informative_text, case_log) 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 begin
case translation_questions.count 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])
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
rescue StandardError rescue StandardError
return "" return ""
end end

12
app/models/case_log.rb

@ -124,6 +124,10 @@ class CaseLog < ApplicationRecord
net_income_in_soft_min_range? || net_income_in_soft_max_range? net_income_in_soft_min_range? || net_income_in_soft_max_range?
end end
def rent_in_soft_validation_range?
rent_in_soft_min_range? || rent_in_soft_max_range?
end
def given_reasonable_preference? def given_reasonable_preference?
reasonpref == 1 reasonpref == 1
end end
@ -281,6 +285,14 @@ class CaseLog < ApplicationRecord
[30, 31].any?(prevten) [30, 31].any?(prevten)
end 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 private
PIO = Postcodes::IO.new PIO = Postcodes::IO.new

15
app/models/form.rb

@ -24,8 +24,10 @@ class Form
pages.find { |p| p.id == id.to_s.underscore } pages.find { |p| p.id == id.to_s.underscore }
end end
def get_question(id) def get_question(id, case_log)
questions.find { |q| q.id == id.to_s.underscore } 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 end
def subsection_for_page(page) def subsection_for_page(page)
@ -35,7 +37,7 @@ class Form
def next_page(page, case_log) def next_page(page, case_log)
page_ids = subsection_for_page(page).pages.map(&:id) page_ids = subsection_for_page(page).pages.map(&:id)
page_index = page_ids.index(page.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) nxt_page = get_page(page_id)
return :check_answers if nxt_page.nil? return :check_answers if nxt_page.nil?
@ -142,4 +144,11 @@ class Form
subsection_ids = subsections.map(&:id) subsection_ids = subsections.map(&:id)
subsection.id == subsection_ids[subsection_ids.length - 1] && next_page(page, case_log) == :check_answers subsection.id == subsection_ids[subsection_ids.length - 1] && next_page(page, case_log) == :check_answers
end 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 end

2
app/models/form/question.rb

@ -49,7 +49,7 @@ class Form::Question
return [] unless inferred_answers return [] unless inferred_answers
enabled_inferred_answers(inferred_answers, case_log).keys.map do |x| 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
end end

2
app/models/validations/household_validations.rb

@ -88,7 +88,7 @@ module Validations::HouseholdValidations
end 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) 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 :prevten, I18n.t("validations.household.prevten.internal_transfer", prevten: label)
record.errors.add :referral, I18n.t("validations.household.referral.prevten_invalid", prevten: label) record.errors.add :referral, I18n.t("validations.household.referral.prevten_invalid", prevten: label)
end end

14
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) weekly_net_income.between?(applicable_income_range.hard_min, applicable_income_range.soft_min)
end 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 end

54
config/forms/2021_2022.json

@ -4539,12 +4539,12 @@
} }
} }
}, },
"check_income_amount": { "net_income_value_check": {
"depends_on": [{ "net_income_soft_validation_triggered?": true }], "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": { "informative_text": {
"translation": "soft_validations.net_income.hint_text", "translation": "soft_validations.net_income.hint_text",
"argument": ["ecstat1", "earnings"] "argument": {"ecstat1": "question", "earnings": "question"}
}, },
"questions": { "questions": {
"net_income_value_check": { "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": { "outstanding": {
"header": "", "header": "",
"description": "", "description": "",

11
config/locales/en.yml

@ -219,11 +219,16 @@ en:
soft_validations: soft_validations:
net_income: net_income:
hint_text: "<p>You told us the main tenant’s working situation is: <strong>%{ecstat1}</strong></p><p>The household income you have entered is <strong>%{earnings}</strong></p>" hint_text: "<p>You told us the lead tenant’s working situation is: <strong>%{ecstat1}</strong></p><p>The household income you have entered is <strong>%{earnings}</strong></p>"
in_soft_min_range: 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: 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: "<p>The minimum rent for a property in %{la} is £%{soft_min} every week.</p><p>You entered <strong>%{brent}</strong></p>"
max:
hint_text: "<p>The maximum rent for a property in %{la} is £%{soft_max} every week.</p><p>You entered <strong>%{brent}</strong></p>"
devise: devise:
two_factor_authentication: two_factor_authentication:
success: "Two factor authentication successful." success: "Two factor authentication successful."

5
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

1
db/schema.rb

@ -231,6 +231,7 @@ ActiveRecord::Schema[7.0].define(version: 202202071123100) do
t.string "relat6" t.string "relat6"
t.string "relat7" t.string "relat7"
t.string "relat8" t.string "relat8"
t.integer "rent_value_check"
t.index ["managing_organisation_id"], name: "index_case_logs_on_managing_organisation_id" 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" t.index ["owning_organisation_id"], name: "index_case_logs_on_owning_organisation_id"
end end

4
spec/features/form/validations_spec.rb

@ -130,8 +130,8 @@ RSpec.describe "validations" do
choose("case-log-incfreq-0-field", allow_label_click: true) choose("case-log-incfreq-0-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/logs/#{case_log.id}/net-income-value-check") 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("Net income is outside the expected range based on the lead 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("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") 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) choose("case-log-net-income-value-check-0-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")

1
spec/fixtures/exports/case_logs.xml vendored

@ -173,5 +173,6 @@
<relat6/> <relat6/>
<relat7/> <relat7/>
<relat8/> <relat8/>
<rent_value_check/>
</form> </form>
</forms> </forms>

4
spec/fixtures/forms/2021_2022.json vendored

@ -559,10 +559,10 @@
}, },
"net_income_value_check": { "net_income_value_check": {
"depends_on": [{ "net_income_soft_validation_triggered?": true }], "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": { "informative_text": {
"translation": "soft_validations.net_income.hint_text", "translation": "soft_validations.net_income.hint_text",
"argument": ["ecstat1", "earnings"] "argument": {"ecstat1": "question", "earnings": "question"}
}, },
"questions": { "questions": {
"net_income_value_check": { "net_income_value_check": {

10
spec/helpers/interuption_screen_helper_spec.rb

@ -22,10 +22,10 @@ RSpec.describe InteruptionScreenHelper do
it "returns correct informative text" do it "returns correct informative text" do
informative_text = { informative_text = {
"translation" => "soft_validations.net_income.hint_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)) expect(display_informative_text(informative_text, case_log))
.to eq("<p>You told us the main tenant’s working situation is: <strong>Full-time – 30 hours or more</strong></p><p>The household income you have entered is <strong>£750.00 every week</strong></p>") .to eq("<p>You told us the lead tenant’s working situation is: <strong>Full-time – 30 hours or more</strong></p><p>The household income you have entered is <strong>£750.00 every week</strong></p>")
end end
end end
@ -33,7 +33,7 @@ RSpec.describe InteruptionScreenHelper do
it "returns correct informative text" do it "returns correct informative text" do
informative_text = { informative_text = {
"translation" => "test.one_argument", "translation" => "test.one_argument",
"argument" => %w[ecstat1], "argument" => { "ecstat1": "question" },
} }
expect(display_informative_text(informative_text, case_log)) 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") .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 it "returns correct informative text" do
informative_text = { informative_text = {
"translation" => "test.one_argument", "translation" => "test.one_argument",
"argument" => %w[ecstat1 earnings], "argument" => { "ecstat1": "question", "earnings": "question" },
} }
expect(display_informative_text(informative_text, case_log)) 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") .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 it "returns an empty string" do
informative_text = { informative_text = {
"translation" => "soft_validations.net_income.hint_text", "translation" => "soft_validations.net_income.hint_text",
"argument" => %w[ecstat1], "argument" => { "ecstat1": "question" },
} }
expect(display_informative_text(informative_text, case_log)) expect(display_informative_text(informative_text, case_log))
.to eq("") .to eq("")

40
spec/models/form_spec.rb

@ -8,10 +8,50 @@ RSpec.describe Form, type: :model do
describe ".next_page" do describe ".next_page" do
let(:previous_page) { form.get_page("person_1_age") } 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 it "returns the next page given the previous" do
expect(form.next_page(previous_page, case_log)).to eq("person_1_gender") expect(form.next_page(previous_page, case_log)).to eq("person_1_gender")
end 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 end
describe "next_page_redirect_path" do describe "next_page_redirect_path" do

2
spec/models/validations/household_validations_spec.rb

@ -86,7 +86,7 @@ RSpec.describe Validations::HouseholdValidations do
end end
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 it "pregnancy can be yes" do
record.preg_occ = 0 record.preg_occ = 0
record.sex1 = "F" record.sex1 = "F"

73
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
Loading…
Cancel
Save