diff --git a/app/helpers/check_answers_helper.rb b/app/helpers/check_answers_helper.rb index 16f07032d..3e59de811 100644 --- a/app/helpers/check_answers_helper.rb +++ b/app/helpers/check_answers_helper.rb @@ -16,9 +16,6 @@ module CheckAnswersHelper while page_name.to_s != "check_answers" && subsection_keys.include?(page_name) questions = form.questions_for_page(page_name) - question_key = questions.keys[0] - question_value = questions.values[0] - applicable_questions = filter_conditional_questions(questions, case_log) total_questions = total_questions.merge(applicable_questions) diff --git a/app/models/case_log.rb b/app/models/case_log.rb index a770c9fb9..aee84fd03 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -3,9 +3,9 @@ class CaseLogValidator < ActiveModel::Validator # followed by field name this is how the metaprogramming of the method # name being call in the validate method works. - def validate_tenant_age(record) - if record.tenant_age && !/^[1-9][0-9]?$|^120$/.match?(record.tenant_age.to_s) - record.errors.add :tenant_age, "Tenant age must be between 0 and 120" + def validate_person_1_age(record) + if record.person_1_age && !/^[1-9][0-9]?$|^120$/.match?(record.person_1_age.to_s) + record.errors.add :person_1_age, "Tenant age must be between 0 and 120" end end @@ -39,6 +39,12 @@ class CaseLogValidator < ActiveModel::Validator end end + def validate_reason_for_leaving_last_settled_home(record) + if record.reason_for_leaving_last_settled_home == "Do not know" && record.benefit_cap_spare_room_subsidy != "Do not know" + record.errors.add :benefit_cap_spare_room_subsidy, "must be do not know if tenant’s main reason for leaving is do not know" + end + end + def validate_armed_forces_injured(record) if (record.armed_forces == "Yes - a regular" || record.armed_forces == "Yes - a reserve") && record.armed_forces_injured.blank? record.errors.add :armed_forces_injured, "You must answer the armed forces injury question if the tenant has served in the armed forces" @@ -57,6 +63,12 @@ class CaseLogValidator < ActiveModel::Validator (2..8).any? { |n| check_partner_net_income_uc_proportion(n, record) } end + def validate_household_pregnancy(record) + if (record.pregnancy == "Yes" || record.pregnancy == "Prefer not to say") && !women_of_child_bearing_age_in_household(record) + record.errors.add :pregnancy, "You must answer no as there are no female tenants aged 16-50 in the property" + end + end + def validate(record) # If we've come from the form UI we only want to validate the specific fields # that have just been submitted. If we're submitting a log via API or Bulk Upload @@ -83,6 +95,14 @@ private record.errors.add :net_income_uc_proportion, "income is from Universal Credit, state pensions or benefits cannot be All if the partner works part or full time" end end + + def women_of_child_bearing_age_in_household(record) + (1..8).any? do |n| + next if record["person_#{n}_gender"].nil? || record["person_#{n}_age"].nil? + + record["person_#{n}_gender"] == "Female" && record["person_#{n}_age"] >= 16 && record["person_#{n}_age"] <= 50 + end + end end class CaseLog < ApplicationRecord diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index 47378e9f0..e658da607 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -21,11 +21,11 @@ } } }, - "tenant_age": { + "person_1_age": { "header": "", "description": "", "questions": { - "tenant_age": { + "person_1_age": { "check_answer_label": "Tenant's age", "header": "What is the tenant's age?", "hint_text": "", @@ -36,11 +36,11 @@ } } }, - "tenant_gender": { + "person_1_gender": { "header": "", "description": "", "questions": { - "tenant_gender": { + "person_1_gender": { "check_answer_label": "Tenant's gender", "header": "Which of these best describes the tenant's gender identity?", "hint_text": "", @@ -612,7 +612,7 @@ "header": "Leaving their last settled home", "description": "", "questions": { - "last_settled_home": { + "reason_for_leaving_last_settled_home": { "header": "What is the tenant’s main reason for leaving?", "hint_text": "", "type": "radio", diff --git a/db/migrate/20211026123542_change_to_person1_gender_age.rb b/db/migrate/20211026123542_change_to_person1_gender_age.rb new file mode 100644 index 000000000..1d0e90e17 --- /dev/null +++ b/db/migrate/20211026123542_change_to_person1_gender_age.rb @@ -0,0 +1,8 @@ +class ChangeToPerson1GenderAge < ActiveRecord::Migration[6.1] + def change + change_table :case_logs, bulk: true do |t| + t.rename :tenant_age, :person_1_age + t.rename :tenant_gender, :person_1_gender + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 20dbfc383..2d4f30da1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_15_090040) do +ActiveRecord::Schema.define(version: 2021_10_26_123542) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -20,8 +20,8 @@ ActiveRecord::Schema.define(version: 2021_10_15_090040) do t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "tenant_code" - t.integer "tenant_age" - t.string "tenant_gender" + t.integer "person_1_age" + t.string "person_1_gender" t.string "tenant_ethnic_group" t.string "tenant_nationality" t.string "previous_housing_situation" diff --git a/docs/api/DLUHC-CORE-Data.v1.json b/docs/api/DLUHC-CORE-Data.v1.json index 61d4d2967..da3e9b6e1 100644 --- a/docs/api/DLUHC-CORE-Data.v1.json +++ b/docs/api/DLUHC-CORE-Data.v1.json @@ -193,7 +193,7 @@ "summary": "Create New Case Log", "operationId": "post-caselog", "responses": { - "200": { + "201": { "description": "Case Log Created", "content": { "application/json": { @@ -388,13 +388,13 @@ "type": "string", "minLength": 1 }, - "tenant_age": { + "person_1_age": { "type": "number", "description": "The age of the lead tenant", "maximum": 120, "minimum": 0 }, - "tenant_gender": { + "person_1_gender": { "type": "string", "minLength": 1, "enum": [ @@ -781,11 +781,55 @@ }, "reason_for_leaving_last_settled_home": { "type": "string", - "minLength": 1 + "minLength": 1, + "enum": [ + "Permanently decanted from another property owned by this landlord", + "Left home country as a refugee", + "Loss of tied accommodation", + "Domestic abuse", + "(Non violent) relationship breakdown with partner", + "Asked to leave by family or friends", + "Racial harassment", + "Other problems with neighbours", + "Property unsuitable because of overcrowding", + "End of assured shorthold tenancy - no fault", + "End of assured shorthold tenancy - tenant's fault", + "End of fixed term tenancy - no fault", + "End of fixed term tenancy - tenant's fault", + "Repossession", + "Under occupation - offered incentive to downsize", + "Under occupation - no incentive", + "Property unsuitable because of ill health / disability", + "Property unsuitable because of poor condition", + "Couldn't afford fees attached to renewing the tenancy", + "Couldn't afford increase in rent", + "Couldn't afford rent or mortgage - welfare reforms", + "Couldn't afford rent or mortgage - employment", + "Couldn't afford rent or mortgage - other", + "To move nearer to family / friends / school", + "To move nearer to work", + "To move to accomodation with support", + "To move to independent accomodation", + "Hate crime", + "Death of household member in last settled accomodation", + "Discharged from prison", + "Discharged from long stay hospital or similar institution", + "Other", + "Do not know", + "Prefer not to say" + ] }, "benefit_cap_spare_room_subsidy": { "type": "string", - "minLength": 1 + "minLength": 1, + "enum": [ + "Yes - benefit cap", + "Yes - removal of the spare room subsidy", + "Yes - both the benefit cap and the removal of the spare room subsidy", + "No", + "Do not know", + "Prefer not to say" + ] }, "armed_forces_active": { "type": "string", @@ -1048,8 +1092,8 @@ }, "required": [ "tenant_code", - "tenant_age", - "tenant_gender", + "person_1_age", + "person_1_gender", "tenant_ethnic_group", "tenant_nationality", "previous_housing_situation", @@ -1164,4 +1208,4 @@ }, "securitySchemes": {} } -} +} \ No newline at end of file diff --git a/spec/factories/case_log.rb b/spec/factories/case_log.rb index 044a4cbac..6e5960329 100644 --- a/spec/factories/case_log.rb +++ b/spec/factories/case_log.rb @@ -6,7 +6,7 @@ FactoryBot.define do tenant_code { "TH356" } property_postcode { "SW2 6HI" } previous_postcode { "P0 5ST" } - tenant_age { "12" } + person_1_age { "12" } end trait :completed do status { 2 } diff --git a/spec/features/case_log_spec.rb b/spec/features/case_log_spec.rb index 3e16f8530..587fc80f1 100644 --- a/spec/features/case_log_spec.rb +++ b/spec/features/case_log_spec.rb @@ -7,8 +7,8 @@ RSpec.describe "Test Features" do question_answers = { tenant_code: { type: "text", answer: "BZ737" }, - tenant_age: { type: "numeric", answer: 25 }, - tenant_gender: { type: "radio", answer: "Female" }, + person_1_age: { type: "numeric", answer: 25 }, + person_1_gender: { type: "radio", answer: "Female" }, household_number_of_other_members: { type: "numeric", answer: 2 }, } @@ -93,9 +93,52 @@ RSpec.describe "Test Features" do ) end + context "Validate pregnancy questions" do + it "Cannot answer yes if no female tenants" do + expect { + CaseLog.create!(pregnancy: "Yes", + person_1_gender: "Male", + person_1_age: 20) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "Cannot answer yes if no female tenants within age range" do + expect { + CaseLog.create!(pregnancy: "Yes", + person_1_gender: "Female", + person_1_age: 51) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "Cannot answer prefer not to say if no valid tenants" do + expect { + CaseLog.create!(pregnancy: "Prefer not to say", + person_1_gender: "Male", + person_1_age: 20) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "Can answer yes if valid tenants" do + expect { + CaseLog.create!(pregnancy: "Yes", + person_1_gender: "Female", + person_1_age: 20) + }.not_to raise_error + end + + it "Can answer yes if valid second tenant" do + expect { + CaseLog.create!(pregnancy: "Yes", + person_1_gender: "Male", person_1_age: 99, + person_2_gender: "Female", + person_2_age: 20) + }.not_to raise_error + end + end + it "can be accessed by url" do - visit("/case_logs/#{id}/tenant_age") - expect(page).to have_field("case-log-tenant-age-field") + visit("/case_logs/#{id}/person_1_age") + expect(page).to have_field("case-log-person-1-age-field") end it "updates model attributes correctly for each question" do @@ -140,8 +183,8 @@ RSpec.describe "Test Features" do end it "displays text answers in inputs if they are already saved" do - visit("/case_logs/#{id}/tenant_age") - expect(page).to have_field("case-log-tenant-age-field", with: "12") + visit("/case_logs/#{id}/person_1_age") + expect(page).to have_field("case-log-person-1-age-field", with: "12") end it "displays checkbox answers in inputs if they are already saved" do @@ -173,7 +216,7 @@ RSpec.describe "Test Features" do it "go back to tenant code page from tenant age page", js: true do visit("/case_logs/#{id}/tenant_code") click_button("Save and continue") - visit("/case_logs/#{id}/tenant_age") + visit("/case_logs/#{id}/person_1_age") click_link(text: "Back") expect(page).to have_field("case-log-tenant-code-field") end @@ -218,8 +261,8 @@ RSpec.describe "Test Features" do end it "should display answers given by the user for the question in the subsection" do - fill_in_number_question(empty_case_log.id, "tenant_age", 28) - choose("case-log-tenant-gender-non-binary-field") + fill_in_number_question(empty_case_log.id, "person_1_age", 28) + choose("case-log-person-1-gender-non-binary-field") click_button("Save and continue") visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") expect(page).to have_content("28") @@ -230,15 +273,15 @@ RSpec.describe "Test Features" do visit("case_logs/#{empty_case_log.id}/#{subsection}/check_answers") assert_selector "a", text: /Answer\z/, count: 4 assert_selector "a", text: "Change", count: 0 - expect(page).to have_link("Answer", href: "/case_logs/#{empty_case_log.id}/tenant_age") + expect(page).to have_link("Answer", href: "/case_logs/#{empty_case_log.id}/person_1_age") end it "should have a change link for answered questions" do - fill_in_number_question(empty_case_log.id, "tenant_age", 28) + fill_in_number_question(empty_case_log.id, "person_1_age", 28) visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") assert_selector "a", text: /Answer\z/, count: 3 assert_selector "a", text: "Change", count: 1 - expect(page).to have_link("Change", href: "/case_logs/#{empty_case_log.id}/tenant_age") + expect(page).to have_link("Change", href: "/case_logs/#{empty_case_log.id}/person_1_age") end it "should have a link pointing to the first question if no questions are answered" do @@ -317,19 +360,19 @@ RSpec.describe "Test Features" do describe "Question validation" do context "given an invalid tenant age" do it " of less than 0 it shows validation" do - visit("/case_logs/#{id}/tenant_age") - fill_in_number_question(empty_case_log.id, "tenant_age", -5) + visit("/case_logs/#{id}/person_1_age") + fill_in_number_question(empty_case_log.id, "person_1_age", -5) expect(page).to have_selector("#error-summary-title") - expect(page).to have_selector("#case-log-tenant-age-error") - expect(page).to have_selector("#case-log-tenant-age-field-error") + expect(page).to have_selector("#case-log-person-1-age-error") + expect(page).to have_selector("#case-log-person-1-age-field-error") end it " of greater than 120 it shows validation" do - visit("/case_logs/#{id}/tenant_age") - fill_in_number_question(empty_case_log.id, "tenant_age", 121) + visit("/case_logs/#{id}/person_1_age") + fill_in_number_question(empty_case_log.id, "person_1_age", 121) expect(page).to have_selector("#error-summary-title") - expect(page).to have_selector("#case-log-tenant-age-error") - expect(page).to have_selector("#case-log-tenant-age-field-error") + expect(page).to have_selector("#case-log-person-1-age-error") + expect(page).to have_selector("#case-log-person-1-age-field-error") end end end @@ -363,8 +406,8 @@ RSpec.describe "Test Features" do end it "can route based on multiple conditions" do - visit("/case_logs/#{id}/tenant_gender") - choose("case-log-tenant-gender-female-field", allow_label_click: true) + visit("/case_logs/#{id}/person_1_gender") + choose("case-log-person-1-gender-female-field", allow_label_click: true) click_button("Save and continue") visit("/case_logs/#{id}/conditional_question") choose("case-log-pregnancy-yes-field", allow_label_click: true) diff --git a/spec/fixtures/complete_case_log.json b/spec/fixtures/complete_case_log.json index 195de85f5..8a539e91c 100644 --- a/spec/fixtures/complete_case_log.json +++ b/spec/fixtures/complete_case_log.json @@ -2,8 +2,8 @@ "case_log": { "tenant_code": "T657", - "tenant_age": 35, - "tenant_gender": "Female", + "person_1_age": 35, + "person_1_gender": "Female", "tenant_ethnic_group": "White: English/Scottish/Welsh/Northern Irish/British", "tenant_nationality": "UK national resident in UK", "previous_housing_situation": "Private sector tenancy", diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json index f5bd9cb48..35590cb3e 100644 --- a/spec/fixtures/forms/test_form.json +++ b/spec/fixtures/forms/test_form.json @@ -16,9 +16,9 @@ } } }, - "tenant_age": { + "person_1_age": { "questions": { - "tenant_age": { + "person_1_age": { "check_answer_label": "Tenant's age", "header": "What is the tenant's age?", "type": "numeric", @@ -28,9 +28,9 @@ } } }, - "tenant_gender": { + "person_1_gender": { "questions": { - "tenant_gender": { + "person_1_gender": { "check_answer_label": "Tenant's gender", "header": "Which of these best describes the tenant's gender identity?", "type": "radio", @@ -252,7 +252,7 @@ } }, "conditional_route_to": { - "rent": { "pregnancy": "Yes", "tenant_gender": "Female" }, + "rent": { "pregnancy": "Yes", "person_1_gender": "Female" }, "conditional_question_yes_page": { "pregnancy": "Yes" }, "conditional_question_no_page": { "pregnancy": "No" } }, diff --git a/spec/helpers/check_answers_helper_spec.rb b/spec/helpers/check_answers_helper_spec.rb index cc619a041..d13f12e27 100644 --- a/spec/helpers/check_answers_helper_spec.rb +++ b/spec/helpers/check_answers_helper_spec.rb @@ -153,7 +153,7 @@ RSpec.describe CheckAnswersHelper do it "it includes conditional pages and questions that were displayed" do case_log["pregnancy"] = "Yes" - case_log["tenant_gender"] = "Female" + case_log["person_1_gender"] = "Female" result = total_questions(conditional_routing_subsection, case_log, form) expected_keys = %w[pregnancy] expect(result.keys).to match_array(expected_keys) diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb index ae2dc4308..91c60c06a 100644 --- a/spec/models/case_log_spec.rb +++ b/spec/models/case_log_spec.rb @@ -3,15 +3,15 @@ require "rails_helper" RSpec.describe Form, type: :model do describe "#new" do it "validates age is a number" do - expect { CaseLog.create!(tenant_age: "random") }.to raise_error(ActiveRecord::RecordInvalid) + expect { CaseLog.create!(person_1_age: "random") }.to raise_error(ActiveRecord::RecordInvalid) end it "validates age is under 120" do - expect { CaseLog.create!(tenant_age: 121) }.to raise_error(ActiveRecord::RecordInvalid) + expect { CaseLog.create!(person_1_age: 121) }.to raise_error(ActiveRecord::RecordInvalid) end it "validates age is over 0" do - expect { CaseLog.create!(tenant_age: 0) }.to raise_error(ActiveRecord::RecordInvalid) + expect { CaseLog.create!(person_1_age: 0) }.to raise_error(ActiveRecord::RecordInvalid) end it "validates number of relets is a number" do @@ -57,7 +57,14 @@ RSpec.describe Form, type: :model do }.to raise_error(ActiveRecord::RecordInvalid) end end - + context "reason for leaving last settled home validation" do + it "Reason for leaving must be don't know if reason for leaving settled home (Q9a) is don't know." do + expect { + CaseLog.create!(reason_for_leaving_last_settled_home: "Do not know", + benefit_cap_spare_room_subsidy: "Yes - benefit cap") + }.to raise_error(ActiveRecord::RecordInvalid) + end + end context "other reason for leaving last settled home validation" do it "must be provided if main reason for leaving last settled home was given as other" do expect { diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index b26e2014c..f11431c8b 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -5,9 +5,9 @@ RSpec.describe Form, type: :model do let(:form) { form_handler.get_form("test_form") } describe ".next_page" do - let(:previous_page) { "tenant_age" } + let(:previous_page) { "person_1_age" } it "returns the next page given the previous" do - expect(form.next_page(previous_page)).to eq("tenant_gender") + expect(form.next_page(previous_page)).to eq("person_1_gender") end end @@ -20,7 +20,7 @@ RSpec.describe Form, type: :model do describe ".previous_page" do context "given a page in the middle of a subsection" do - let(:current_page) { "tenant_age" } + let(:current_page) { "person_1_age" } it "returns the previous page given the current" do expect(form.previous_page(current_page)).to eq("tenant_code") end diff --git a/spec/requests/case_log_controller_spec.rb b/spec/requests/case_log_controller_spec.rb index 89a5592b4..e6c866c90 100644 --- a/spec/requests/case_log_controller_spec.rb +++ b/spec/requests/case_log_controller_spec.rb @@ -24,7 +24,7 @@ RSpec.describe CaseLogsController, type: :request do describe "POST #create" do let(:tenant_code) { "T365" } - let(:tenant_age) { 35 } + let(:person_1_age) { 35 } let(:property_number_of_times_relet) { 12 } let(:property_postcode) { "SE11 6TY" } let(:in_progress) { "in_progress" } @@ -33,7 +33,7 @@ RSpec.describe CaseLogsController, type: :request do let(:params) do { "tenant_code": tenant_code, - "tenant_age": tenant_age, + "person_1_age": person_1_age, "property_postcode": property_postcode, "property_number_of_times_relet": property_number_of_times_relet, } @@ -55,18 +55,18 @@ RSpec.describe CaseLogsController, type: :request do it "creates a case log with the values passed" do json_response = JSON.parse(response.body) expect(json_response["tenant_code"]).to eq(tenant_code) - expect(json_response["tenant_age"]).to eq(tenant_age) + expect(json_response["person_1_age"]).to eq(person_1_age) expect(json_response["property_postcode"]).to eq(property_postcode) end context "invalid json params" do - let(:tenant_age) { 2000 } + let(:person_1_age) { 2000 } let(:property_number_of_times_relet) { 21 } it "validates case log parameters" do json_response = JSON.parse(response.body) expect(response).to have_http_status(:unprocessable_entity) - expect(json_response["errors"]).to match_array([["property_number_of_times_relet", ["Must be between 0 and 20"]], ["tenant_age", ["Tenant age must be between 0 and 120"]]]) + expect(json_response["errors"]).to match_array([["property_number_of_times_relet", ["Must be between 0 and 20"]], ["person_1_age", ["Tenant age must be between 0 and 120"]]]) end end @@ -149,7 +149,7 @@ RSpec.describe CaseLogsController, type: :request do end context "invalid case log params" do - let(:params) { { tenant_age: 200 } } + let(:params) { { person_1_age: 200 } } it "returns 422" do expect(response).to have_http_status(:unprocessable_entity) @@ -157,7 +157,7 @@ RSpec.describe CaseLogsController, type: :request do it "returns an error message" do json_response = JSON.parse(response.body) - expect(json_response["errors"]).to eq({ "tenant_age" => ["Tenant age must be between 0 and 120"] }) + expect(json_response["errors"]).to eq({ "person_1_age" => ["Tenant age must be between 0 and 120"] }) end end