Browse Source

Merge branch 'main' into CLDC-641-JSONValidation

pull/76/head
magicmilo 3 years ago
parent
commit
041e41b2be
  1. 1
      Gemfile
  2. 10
      Gemfile.lock
  3. 3
      app/admin/case_logs.rb
  4. 703
      app/constants/db_enums.rb
  5. 10
      app/controllers/case_logs_controller.rb
  6. 20
      app/controllers/soft_validations_controller.rb
  7. 2
      app/helpers/check_answers_helper.rb
  8. 7
      app/javascript/controllers/conditional_question_controller.js
  9. 36
      app/javascript/controllers/soft_validations_controller.js
  10. 159
      app/models/case_log.rb
  11. 17
      app/models/form.rb
  12. 22
      app/validations/financial_validations.rb
  13. 100
      app/validations/household_validations.rb
  14. 4
      app/validations/property_validations.rb
  15. 10
      app/validations/soft_validations.rb
  16. 12
      app/validations/tenancy_validations.rb
  17. 2
      app/views/form/_check_answers_table.html.erb
  18. 2
      app/views/form/_checkbox_question.html.erb
  19. 11
      app/views/form/_select_question.html.erb
  20. 16
      app/views/form/_validation_override_question.html.erb
  21. 2
      app/views/form/check_answers.html.erb
  22. 8
      app/views/form/page.html.erb
  23. 561
      config/forms/2021_2022.json
  24. 2
      config/initializers/active_admin.rb
  25. 1
      config/routes.rb
  26. 106
      db/migrate/20211101192151_rename_fields.rb
  27. 17
      db/migrate/20211102100820_add_about_this_log_readable_columns.rb
  28. 131
      db/migrate/20211103090530_change_field_types.rb
  29. 9
      db/migrate/20211105164644_change_net_income_overide.rb
  30. 15
      db/migrate/20211108091320_change_checkbox_types.rb
  31. 57
      db/migrate/20211108134601_further_core_migrations.rb
  32. 21
      db/migrate/20211110140928_add_mrc_dates.rb
  33. 7
      db/migrate/20211111143319_add_other_members_column.rb
  34. 8
      db/migrate/20211112105348_add_incref_field.rb
  35. 216
      db/schema.rb
  36. 11
      docs/adr/adr-008-field-names.md
  37. 673
      docs/api/DLUHC-CORE-Data.v1.json
  38. 99
      spec/controllers/case_logs_controller_spec.rb
  39. 12
      spec/factories/case_log.rb
  40. 176
      spec/features/case_log_spec.rb
  41. 225
      spec/fixtures/complete_case_log.json
  42. 180
      spec/fixtures/forms/test_aboutthislog.json
  43. 38
      spec/helpers/check_answers_helper_spec.rb
  44. 4
      spec/helpers/conditional_questions_helper_spec.rb
  45. 12
      spec/helpers/question_attribute_helper_spec.rb
  46. 6
      spec/helpers/tasklist_helper_spec.rb
  47. 176
      spec/models/case_log_spec.rb
  48. 2
      spec/models/form_handler_spec.rb
  49. 2
      spec/models/form_spec.rb
  50. 20
      spec/requests/case_log_controller_spec.rb
  51. 39
      spec/requests/soft_validations_controller_spec.rb

1
Gemfile

@ -31,6 +31,7 @@ gem "activeadmin"
gem "chartkick" gem "chartkick"
#Json Schema #Json Schema
gem "json-schema" gem "json-schema"
gem "uk_postcode"
group :development, :test do group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console # Call 'byebug' anywhere in the code to stop execution and get a debugger console

10
Gemfile.lock

@ -1,6 +1,6 @@
GIT GIT
remote: https://github.com/rspec/rspec-core.git remote: https://github.com/rspec/rspec-core.git
revision: d57c371ee92b16211b80ac7b0b025968438f5297 revision: 42a9fe3a2dc9d5e68811ee646f4b9b4349c18b24
branch: main branch: main
specs: specs:
rspec-core (3.11.0.pre) rspec-core (3.11.0.pre)
@ -40,7 +40,7 @@ GIT
GIT GIT
remote: https://github.com/rspec/rspec-support.git remote: https://github.com/rspec/rspec-support.git
revision: 2a17194b9fc868a4b4a41d7168103dca825c3004 revision: 9499cb622f9feef43a53f357809f9e656e7cb6de
branch: main branch: main
specs: specs:
rspec-support (3.11.0.pre) rspec-support (3.11.0.pre)
@ -182,7 +182,7 @@ GEM
rails (>= 6.0.0) rails (>= 6.0.0)
stimulus-rails stimulus-rails
turbo-rails turbo-rails
i18n (1.8.10) i18n (1.8.11)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
inherited_resources (1.13.0) inherited_resources (1.13.0)
actionpack (>= 5.2, < 6.2) actionpack (>= 5.2, < 6.2)
@ -311,7 +311,7 @@ GEM
rubocop-rails (= 2.12.2) rubocop-rails (= 2.12.2)
rubocop-rake (= 0.6.0) rubocop-rake (= 0.6.0)
rubocop-rspec (= 2.4.0) rubocop-rspec (= 2.4.0)
rubocop-performance (1.11.5) rubocop-performance (1.12.0)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0) rubocop-ast (>= 0.4.0)
rubocop-rails (2.12.2) rubocop-rails (2.12.2)
@ -360,6 +360,7 @@ GEM
rails (>= 6.0.0) rails (>= 6.0.0)
tzinfo (2.0.4) tzinfo (2.0.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
uk_postcode (2.1.6)
unicode-display_width (2.1.0) unicode-display_width (2.1.0)
view_component (2.39.0) view_component (2.39.0)
activesupport (>= 5.0.0, < 8.0) activesupport (>= 5.0.0, < 8.0)
@ -420,6 +421,7 @@ DEPENDENCIES
selenium-webdriver selenium-webdriver
simplecov simplecov
tzinfo-data tzinfo-data
uk_postcode
web-console (>= 4.1.0) web-console (>= 4.1.0)
webpacker (~> 5.0) webpacker (~> 5.0)

3
app/admin/case_logs.rb

@ -1,9 +1,8 @@
ActiveAdmin.register CaseLog do ActiveAdmin.register CaseLog do
# See permitted parameters documentation: # See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters # https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
permit_params do permit_params do
permitted = [:status, :tenant_code, :person_1_age, :person_1_gender, :tenant_ethnic_group, :tenant_nationality, :previous_housing_situation, :armed_forces, :person_1_economic_status, :household_number_of_other_members, :person_2_relationship, :person_2_age, :person_2_gender, :person_2_economic_status, :person_3_relationship, :person_3_age, :person_3_gender, :person_3_economic_status, :person_4_relationship, :person_4_age, :person_4_gender, :person_4_economic_status, :person_5_relationship, :person_5_age, :person_5_gender, :person_5_economic_status, :person_6_relationship, :person_6_age, :person_6_gender, :person_6_economic_status, :person_7_relationship, :person_7_age, :person_7_gender, :person_7_economic_status, :person_8_relationship, :person_8_age, :person_8_gender, :person_8_economic_status, :homelessness, :reason_for_leaving_last_settled_home, :benefit_cap_spare_room_subsidy, :armed_forces_active, :armed_forces_injured, :armed_forces_partner, :medical_conditions, :pregnancy, :accessibility_requirements, :condition_effects, :tenancy_code, :tenancy_start_date, :starter_tenancy, :fixed_term_tenancy, :tenancy_type, :letting_type, :letting_provider, :property_location, :previous_postcode, :property_relet, :property_vacancy_reason, :property_reference, :property_unit_type, :property_building_type, :property_number_of_bedrooms, :property_void_date, :property_major_repairs, :property_major_repairs_date, :property_number_of_times_relet, :property_wheelchair_accessible, :net_income, :net_income_frequency, :net_income_uc_proportion, :housing_benefit, :rent_frequency, :basic_rent, :service_charge, :personal_service_charge, :support_charge, :total_charge, :outstanding_amount, :time_lived_in_la, :time_on_la_waiting_list, :previous_la, :property_postcode, :reasonable_preference, :reasonable_preference_reason, :cbl_letting, :chr_letting, :cap_letting, :outstanding_rent_or_charges, :other_reason_for_leaving_last_settled_home, :accessibility_requirements_fully_wheelchair_accessible_housing, :accessibility_requirements_wheelchair_access_to_essential_rooms, :accessibility_requirements_level_access_housing, :accessibility_requirements_other_disability_requirements, :accessibility_requirements_no_disability_requirements, :accessibility_requirements_do_not_know, :accessibility_requirements_prefer_not_to_say, :condition_effects_vision, :condition_effects_hearing, :condition_effects_mobility, :condition_effects_dexterity, :condition_effects_stamina, :condition_effects_learning, :condition_effects_memory, :condition_effects_mental_health, :condition_effects_social_or_behavioral, :condition_effects_other, :condition_effects_prefer_not_to_say, :reasonable_preference_reason_homeless, :reasonable_preference_reason_unsatisfactory_housing, :reasonable_preference_reason_medical_grounds, :reasonable_preference_reason_avoid_hardship, :reasonable_preference_reason_do_not_know, :other_tenancy_type, :override_net_income_validation, :net_income_known] permitted = %i[status tenant_code age1 sex1 tenant_ethnic_group tenant_nationality previous_housing_situation armed_forces ecstat1 other_hhmemb relat2 age2 sex2 ecstat2 relat3 age3 sex3 ecstat3 relat4 age4 sex4 ecstat4 relat5 age5 sex5 ecstat5 relat6 age6 sex6 ecstat6 relat7 age7 person_7_gender ecstat7 relat8 age8 sex8 ecstat8 homelessness reason benefit_cap_spare_room_subsidy armed_forces_active armed_forces_injured armed_forces_partner medical_conditions pregnancy accessibility_requirements condition_effects tenancy_code tenancy_start_date starter_tenancy fixed_term_tenancy tenancy_type letting_type letting_provider la previous_postcode property_relet property_vacancy_reason property_reference property_unit_type property_building_type property_number_of_bedrooms property_void_date majorrepairs mrcdate property_number_of_times_relet property_wheelchair_accessible net_income net_income_frequency net_income_uc_proportion hb rent_frequency basic_rent service_charge personal_service_charge support_charge total_charge tshortfall time_lived_in_la time_on_la_waiting_list prevloc property_postcode reasonable_preference reasonable_preference_reason cbl_letting chr_letting cap_letting hbrentshortfall other_reason accessibility_requirements_fully_wheelchair_accessible_housing accessibility_requirements_wheelchair_access_to_essential_rooms accessibility_requirements_level_access_housing accessibility_requirements_other_disability_requirements accessibility_requirements_no_disability_requirements accessibility_requirements_do_not_know accessibility_requirements_prefer_not_to_say condition_effects_vision condition_effects_hearing condition_effects_mobility condition_effects_dexterity condition_effects_stamina condition_effects_learning condition_effects_memory condition_effects_mental_health condition_effects_social_or_behavioral condition_effects_other condition_effects_prefer_not_to_say reasonable_preference_reason_homeless reasonable_preference_reason_unsatisfactory_housing reasonable_preference_reason_medical_grounds reasonable_preference_reason_avoid_hardship reasonable_preference_reason_do_not_know other_tenancy_type override_net_income_validation net_income_known]
permitted permitted
end end

703
app/constants/db_enums.rb

@ -0,0 +1,703 @@
module DbEnums
def self.benefitcap
{
"Yes - benefit cap" => 5,
"Yes - removal of the spare room subsidy" => 4,
"Yes - both the benefit cap and the removal of the spare room subsidy" => 6,
"No" => 2,
"Do not know" => 3,
"Prefer not to say" => 100,
}
end
def self.ecstat
{
"Part-time - Less than 30 hours" => 2,
"Full-time - 30 hours or more" => 1,
"In government training into work, such as New Deal" => 3,
"Jobseeker" => 4,
"Retired" => 5,
"Not seeking work" => 6,
"Full-time student" => 7,
"Unable to work because of long term sick or disability" => 8,
"Child under 16" => 9,
"Other" => 0,
"Prefer not to say" => 10,
}
end
def self.ethnic
{
"White: English/Scottish/Welsh/Northern Irish/British" => 1,
"White: Irish" => 2,
"White: Gypsy/Irish Traveller" => 18,
"White: Other" => 3,
"Mixed: White & Black Caribbean" => 4,
"Mixed: White & Black African" => 5,
"Mixed: White & Asian" => 6,
"Mixed: Other" => 7,
"Asian or Asian British: Indian" => 8,
"Asian or Asian British: Pakistani" => 9,
"Asian or Asian British: Bangladeshi" => 10,
"Asian or Asian British: Chinese" => 15,
"Asian or Asian British: Other" => 11,
"Black: Caribbean" => 12,
"Black: African" => 13,
"Black: Other" => 14,
"Other Ethnic Group: Arab" => 16,
"Other Ethnic Group: Other" => 19,
"Prefer not to say" => 17,
}
end
def self.homeless
{
"Yes - assessed as homeless by a local authority and owed a homelessness duty. Including if threatened with homelessness within 56 days" => 11,
"Yes - other homelessness" => 7,
"No" => 1,
}
end
def self.illness
{
"Yes" => 1,
"No" => 2,
"Do not know" => 3,
}
end
def self.leftreg
{
"Yes" => 6,
"No - they left up to 5 years ago" => 4,
"No - they left more than 5 years ago" => 5,
"Prefer not to say" => 3,
}
end
def self.national
{
"UK national resident in UK" => 1,
"A current or former reserve in the UK Armed Forces (exc. National Service)" => 100,
"UK national returning from residence overseas" => 2,
"Czech Republic" => 3,
"Estonia" => 4,
"Hungary" => 5,
"Latvia" => 6,
"Lithuania" => 7,
"Poland" => 8,
"Slovakia" => 9,
"Bulgaria" => 14,
"Romania" => 15,
"Ireland" => 17,
"Slovenia" => 10,
"Croatia" => 16,
"Other EU Economic Area (EEA country)" => 11,
"Any other country" => 12,
"Prefer not to say" => 13,
}
end
def self.pregnancy
{
"Yes" => 1,
"No" => 2,
"Prefer not to say" => 3,
}
end
def self.previous_tenancy
{
"Owner occupation (private) " => 26,
"Owner occupation (low cost home ownership)" => 27,
"Private sector tenancy" => 3,
"Tied housing or rented with job" => 4,
"Supported housing" => 5,
"Sheltered accomodation" => 8,
"Residential care home" => 9,
"Living with friends or family" => 28,
"Refuge" => 21,
"Hospital" => 10,
"Prison / approved probation hostel" => 29,
"Direct access hostel" => 7,
"Bed & Breakfast" => 14,
"Mobile home / caravan" => 23,
"Any other temporary accommodation" => 18,
"Home Office Asylum Support" => 24,
"Children’s home / foster care" => 13,
"Rough sleeping" => 19,
"Other" => 25,
"Fixed term Local Authority General Needs tenancy" => 30,
"Lifetime Local Authority General Needs tenancy" => 31,
"Fixed term PRP General Needs tenancy" => 32,
"Lifetime PRP General Needs tenancy" => 33,
}
end
def self.reservist
{
"Yes" => 1,
"No" => 2,
"Prefer not to say" => 3,
}
end
def self.polar
{
"No" => 0,
"Yes" => 1,
}
end
def self.polar2
{
"No" => 2,
"Yes" => 1,
}
end
def self.polar_with_unknown
{
"No" => 2,
"Yes" => 1,
"Do not know" => 3,
}
end
def self.tenancy
{
"Fixed term – Secure" => 1,
"Fixed term – Assured Shorthold Tenancy (AST)" => 4,
"Lifetime – Secure" => 100,
"Lifetime – Assured" => 2,
"License agreement" => 5,
"Other" => 3,
}
end
def self.landlord
{
"This landlord" => 1,
"Another registered provider - includes housing association or local authority" => 2,
}
end
def self.rsnvac
{
"First let of newbuild property" => 15,
"First let of conversion/rehabilitation/acquired property" => 16,
"First let of leased property" => 17,
"Relet - tenant evicted due to arrears" => 10,
"Relet - tenant evicted due to ASB or other reason" => 11,
"Relet - tenant died (no succession)" => 5,
"Relet - tenant moved to other social housing provider" => 12,
"Relet - tenant abandoned property" => 6,
"Relet - tenant moved to private sector or other accommodation" => 8,
"Relet - to tenant who occupied same property as temporary accommodation" => 9,
"Relet – internal transfer (excluding renewals of a fixed-term tenancy)" => 13,
"Relet – renewal of fixed-term tenancy" => 14,
"Relet – tenant moved to care home" => 18,
"Relet – tenant involved in a succession downsize" => 19,
}
end
def self.unittype_gn
{
"Flat / maisonette" => 1,
"Bed-sit" => 2,
"House" => 7,
"Bungalow" => 8,
"Shared flat / maisonette" => 4,
"Shared house" => 9,
"Shared bungalow" => 10,
"Other" => 6,
}
end
def self.incfreq
{
"Weekly" => 1,
"Monthly" => 2,
"Yearly" => 3,
}
end
def self.override_soft_validation
{
"No" => 0,
"Yes" => 1,
}
end
def self.benefits
{
"All" => 1,
"Some" => 2,
"None" => 3,
"Do not know" => 4,
}
end
def self.period
{
"Weekly for 52 weeks" => 1,
"Fortnightly" => 2,
"Four-weekly" => 3,
"Calendar monthly" => 4,
"Weekly for 50 weeks" => 5,
"Weekly for 49 weeks" => 6,
"Weekly for 48 weeks" => 7,
"Weekly for 47 weeks" => 8,
"Weekly for 46 weeks" => 9,
"Weekly for 53 weeks" => 10,
}
end
def self.latime
{
"Just moved to local authority area" => 1,
"Less than 1 year" => 2,
"1 to 2 years" => 7,
"2 to 3 years" => 8,
"3 to 4 years" => 9,
"4 to 5 years" => 10,
"5 years or more" => 5,
"Do not know" => 6,
}
end
def self.housing_benefit
{
"Housing Benefit, but not Universal Credit" => 1,
"Universal Credit with housing element, but not Housing Benefit" => 6,
"Universal Credit without housing element and no Housing Benefit" => 7,
"Universal Credit and Housing Benefit" => 8,
"Not Housing Benefit or Universal Credit" => 9,
"Do not know" => 3,
"Prefer not to say" => 100,
}
end
def self.reason
{
"Permanently decanted from another property owned by this landlord" => 1,
"Left home country as a refugee" => 2,
"Loss of tied accommodation" => 4,
"Domestic abuse" => 7,
"(Non violent) relationship breakdown with partner" => 8,
"Asked to leave by family or friends" => 9,
"Racial harassment" => 10,
"Other problems with neighbours" => 11,
"Property unsuitable because of overcrowding" => 12,
"End of assured shorthold tenancy - no fault" => 40,
"End of assured shorthold tenancy - tenant's fault" => 41,
"End of fixed term tenancy - no fault" => 42,
"End of fixed term tenancy - tenant's fault" => 43,
"Repossession" => 34,
"Under occupation - offered incentive to downsize" => 29,
"Under occupation - no incentive" => 30,
"Property unsuitable because of ill health / disability" => 13,
"Property unsuitable because of poor condition" => 14,
"Couldn't afford fees attached to renewing the tenancy" => 35,
"Couldn't afford increase in rent" => 36,
"Couldn't afford rent or mortgage - welfare reforms" => 37,
"Couldn't afford rent or mortgage - employment" => 38,
"Couldn't afford rent or mortgage - other" => 39,
"To move nearer to family / friends / school" => 16,
"To move nearer to work" => 17,
"To move to accomodation with support" => 18,
"To move to independent accomodation" => 19,
"Hate crime" => 31,
"Death of household member in last settled accomodation" => 46,
"Discharged from prison" => 44,
"Discharged from long stay hospital or similar institution" => 45,
"Other" => 20,
"Do not know" => 28,
"Prefer not to say" => 100,
}
end
def self.la
{
"Hartlepool" => "E06000001",
"Na h-Eileanan Siar" => "S12000013",
"Middlesbrough" => "E06000002",
"Redcar and Cleveland" => "E06000003",
"Stockton-on-Tees" => "E06000004",
"Darlington" => "E06000005",
"Halton" => "E06000006",
"Warrington" => "E06000007",
"Blackburn with Darwen" => "E06000008",
"Blackpool" => "E06000009",
"Kingston upon Hull, City of" => "E06000010",
"East Riding of Yorkshire" => "E06000011",
"North East Lincolnshire" => "E06000012",
"North Lincolnshire" => "E06000013",
"York" => "E06000014",
"Derby" => "E06000015",
"Leicester" => "E06000016",
"Rutland" => "E06000017",
"Nottingham" => "E06000018",
"Herefordshire, County of" => "E06000019",
"Telford and Wrekin" => "E06000020",
"Stoke-on-Trent" => "E06000021",
"Bath and North East Somerset" => "E06000022",
"Bristol, City of" => "E06000023",
"North Somerset" => "E06000024",
"South Gloucestershire" => "E06000025",
"Plymouth" => "E06000026",
"Torbay" => "E06000027",
"Swindon" => "E06000030",
"Peterborough" => "E06000031",
"Luton" => "E06000032",
"Southend-on-Sea" => "E06000033",
"Thurrock" => "E06000034",
"Medway" => "E06000035",
"Bracknell Forest" => "E06000036",
"West Berkshire" => "E06000037",
"Reading" => "E06000038",
"Slough" => "E06000039",
"Windsor and Maidenhead" => "E06000040",
"Wokingham" => "E06000041",
"Milton Keynes" => "E06000042",
"Brighton and Hove" => "E06000043",
"Portsmouth" => "E06000044",
"Southampton" => "E06000045",
"Isle of Wight" => "E06000046",
"County Durham" => "E06000047",
"Cheshire East" => "E06000049",
"Cheshire West and Chester" => "E06000050",
"Shropshire" => "E06000051",
"Cornwall" => "E06000052",
"Isles of Scilly" => "E06000053",
"Wiltshire" => "E06000054",
"Bedford" => "E06000055",
"Central Bedfordshire" => "E06000056",
"Northumberland" => "E06000057",
"Bournemouth, Christchurch and Poole" => "E06000058",
"North Warwickshire" => "E07000218",
"Nuneaton and Bedworth" => "E07000219",
"Rugby" => "E07000220",
"Stratford-on-Avon" => "E07000221",
"Warwick" => "E07000222",
"Adur" => "E07000223",
"Arun" => "E07000224",
"Chichester" => "E07000225",
"Crawley" => "E07000226",
"Horsham" => "E07000227",
"Mid Sussex" => "E07000228",
"Worthing" => "E07000229",
"Bromsgrove" => "E07000234",
"Malvern Hills" => "E07000235",
"Redditch" => "E07000236",
"Worcester" => "E07000237",
"Wychavon" => "E07000238",
"Wyre Forest" => "E07000239",
"St Albans" => "E07000240",
"Welwyn Hatfield" => "E07000241",
"East Hertfordshire" => "E07000242",
"Stevenage" => "E07000243",
"East Suffolk" => "E07000244",
"West Suffolk" => "E07000245",
"Somerset West and Taunton" => "E07000246",
"Bolton" => "E08000001",
"Bury" => "E08000002",
"Manchester" => "E08000003",
"Oldham" => "E08000004",
"Rochdale" => "E08000005",
"Salford" => "E08000006",
"Stockport" => "E08000007",
"Tameside" => "E08000008",
"Trafford" => "E08000009",
"Wigan" => "E08000010",
"Knowsley" => "E08000011",
"Liverpool" => "E08000012",
"St. Helens" => "E08000013",
"Sefton" => "E08000014",
"Wirral" => "E08000015",
"Barnsley" => "E08000016",
"Doncaster" => "E08000017",
"Rotherham" => "E08000018",
"Sheffield" => "E08000019",
"Newcastle upon Tyne" => "E08000021",
"North Tyneside" => "E08000022",
"South Tyneside" => "E08000023",
"Sunderland" => "E08000024",
"Birmingham" => "E08000025",
"Coventry" => "E08000026",
"Dudley" => "E08000027",
"Sandwell" => "E08000028",
"Solihull" => "E08000029",
"Walsall" => "E08000030",
"Dorset" => "E06000059",
"Wolverhampton" => "E08000031",
"Falkirk" => "S12000014",
"Highland" => "S12000017",
"Inverclyde" => "S12000018",
"Midlothian" => "S12000019",
"Moray" => "S12000020",
"North Ayrshire" => "S12000021",
"Orkney Islands" => "S12000023",
"Scottish Borders" => "S12000026",
"Shetland Islands" => "S12000027",
"South Ayrshire" => "S12000028",
"South Lanarkshire" => "S12000029",
"Stirling" => "S12000030",
"Aberdeen City" => "S12000033",
"Aberdeenshire" => "S12000034",
"Argyll and Bute" => "S12000035",
"City of Edinburgh" => "S12000036",
"Renfrewshire" => "S12000038",
"West Dunbartonshire" => "S12000039",
"West Lothian" => "S12000040",
"Angus" => "S12000041",
"Dundee City" => "S12000042",
"East Dunbartonshire" => "S12000045",
"Buckinghamshire" => "E06000060",
"Fife" => "S12000047",
"Cambridge" => "E07000008",
"Perth and Kinross" => "S12000048",
"East Cambridgeshire" => "E07000009",
"Glasgow City" => "S12000049",
"Fenland" => "E07000010",
"North Lanarkshire" => "S12000050",
"Huntingdonshire" => "E07000011",
"Isle of Anglesey" => "W06000001",
"South Cambridgeshire" => "E07000012",
"Gwynedd" => "W06000002",
"Allerdale" => "E07000026",
"Conwy" => "W06000003",
"Barrow-in-Furness" => "E07000027",
"Denbighshire" => "W06000004",
"Carlisle" => "E07000028",
"Flintshire" => "W06000005",
"Copeland" => "E07000029",
"Wrexham" => "W06000006",
"Eden" => "E07000030",
"Ceredigion" => "W06000008",
"South Lakeland" => "E07000031",
"Pembrokeshire" => "W06000009",
"Amber Valley" => "E07000032",
"Carmarthenshire" => "W06000010",
"Bolsover" => "E07000033",
"Swansea" => "W06000011",
"Chesterfield" => "E07000034",
"Neath Port Talbot" => "W06000012",
"Derbyshire Dales" => "E07000035",
"Bridgend" => "W06000013",
"Erewash" => "E07000036",
"Vale of Glamorgan" => "W06000014",
"High Peak" => "E07000037",
"Cardiff" => "W06000015",
"North East Derbyshire" => "E07000038",
"Rhondda Cynon Taf" => "W06000016",
"South Derbyshire" => "E07000039",
"Caerphilly" => "W06000018",
"East Devon" => "E07000040",
"Blaenau Gwent" => "W06000019",
"Exeter" => "E07000041",
"Torfaen" => "W06000020",
"Mid Devon" => "E07000042",
"Monmouthshire" => "W06000021",
"North Devon" => "E07000043",
"Newport" => "W06000022",
"South Hams" => "E07000044",
"Powys" => "W06000023",
"Teignbridge" => "E07000045",
"Merthyr Tydfil" => "W06000024",
"Torridge" => "E07000046",
"West Devon" => "E07000047",
"Eastbourne" => "E07000061",
"Hastings" => "E07000062",
"Lewes" => "E07000063",
"Rother" => "E07000064",
"Wealden" => "E07000065",
"Basildon" => "E07000066",
"Braintree" => "E07000067",
"Brentwood" => "E07000068",
"Castle Point" => "E07000069",
"Chelmsford" => "E07000070",
"Colchester" => "E07000071",
"Epping Forest" => "E07000072",
"Harlow" => "E07000073",
"Maldon" => "E07000074",
"Rochford" => "E07000075",
"Tendring" => "E07000076",
"Uttlesford" => "E07000077",
"Cheltenham" => "E07000078",
"Cotswold" => "E07000079",
"Forest of Dean" => "E07000080",
"Gloucester" => "E07000081",
"Stroud" => "E07000082",
"Tewkesbury" => "E07000083",
"Basingstoke and Deane" => "E07000084",
"East Hampshire" => "E07000085",
"King’s Lynn and West Norfolk" => "E07000146",
"Eastleigh" => "E07000086",
"North Norfolk" => "E07000147",
"Norwich" => "E07000148",
"South Norfolk" => "E07000149",
"Corby" => "E07000150",
"Daventry" => "E07000151",
"East Northamptonshire" => "E07000152",
"Kettering" => "E07000153",
"Northampton" => "E07000154",
"South Northamptonshire" => "E07000155",
"Wellingborough" => "E07000156",
"Craven" => "E07000163",
"Hambleton" => "E07000164",
"Harrogate" => "E07000165",
"Richmondshire" => "E07000166",
"Ryedale" => "E07000167",
"Scarborough" => "E07000168",
"Selby" => "E07000169",
"Ashfield" => "E07000170",
"Bassetlaw" => "E07000171",
"Broxtowe" => "E07000172",
"Gedling" => "E07000173",
"Mansfield" => "E07000174",
"Newark and Sherwood" => "E07000175",
"Rushcliffe" => "E07000176",
"Cherwell" => "E07000177",
"Oxford" => "E07000178",
"South Oxfordshire" => "E07000179",
"Vale of White Horse" => "E07000180",
"West Oxfordshire" => "E07000181",
"Mendip" => "E07000187",
"Sedgemoor" => "E07000188",
"South Somerset" => "E07000189",
"Cannock Chase" => "E07000192",
"East Staffordshire" => "E07000193",
"Lichfield" => "E07000194",
"Newcastle-under-Lyme" => "E07000195",
"South Staffordshire" => "E07000196",
"Stafford" => "E07000197",
"Staffordshire Moorlands" => "E07000198",
"Tamworth" => "E07000199",
"Babergh" => "E07000200",
"Ipswich" => "E07000202",
"Mid Suffolk" => "E07000203",
"Elmbridge" => "E07000207",
"Epsom and Ewell" => "E07000208",
"Guildford" => "E07000209",
"Mole Valley" => "E07000210",
"Reigate and Banstead" => "E07000211",
"Runnymede" => "E07000212",
"Spelthorne" => "E07000213",
"Surrey Heath" => "E07000214",
"Tandridge" => "E07000215",
"Waverley" => "E07000216",
"Woking" => "E07000217",
"Fareham" => "E07000087",
"Gosport" => "E07000088",
"Hart" => "E07000089",
"Havant" => "E07000090",
"New Forest" => "E07000091",
"Rushmoor" => "E07000092",
"Test Valley" => "E07000093",
"Winchester" => "E07000094",
"Broxbourne" => "E07000095",
"Dacorum" => "E07000096",
"Hertsmere" => "E07000098",
"North Hertfordshire" => "E07000099",
"Three Rivers" => "E07000102",
"Watford" => "E07000103",
"Ashford" => "E07000105",
"Canterbury" => "E07000106",
"Dartford" => "E07000107",
"Dover" => "E07000108",
"Gravesham" => "E07000109",
"Maidstone" => "E07000110",
"Sevenoaks" => "E07000111",
"Folkestone and Hythe" => "E07000112",
"Swale" => "E07000113",
"Thanet" => "E07000114",
"Tonbridge and Malling" => "E07000115",
"Tunbridge Wells" => "E07000116",
"Burnley" => "E07000117",
"Chorley" => "E07000118",
"Fylde" => "E07000119",
"Hyndburn" => "E07000120",
"Lancaster" => "E07000121",
"Pendle" => "E07000122",
"Preston" => "E07000123",
"Ribble Valley" => "E07000124",
"Rossendale" => "E07000125",
"South Ribble" => "E07000126",
"West Lancashire" => "E07000127",
"Wyre" => "E07000128",
"Blaby" => "E07000129",
"Charnwood" => "E07000130",
"Harborough" => "E07000131",
"Hinckley and Bosworth" => "E07000132",
"Melton" => "E07000133",
"North West Leicestershire" => "E07000134",
"Oadby and Wigston" => "E07000135",
"Boston" => "E07000136",
"East Lindsey" => "E07000137",
"Lincoln" => "E07000138",
"North Kesteven" => "E07000139",
"South Holland" => "E07000140",
"South Kesteven" => "E07000141",
"West Lindsey" => "E07000142",
"Breckland" => "E07000143",
"Broadland" => "E07000144",
"Great Yarmouth" => "E07000145",
"Bradford" => "E08000032",
"Calderdale" => "E08000033",
"Kirklees" => "E08000034",
"Leeds" => "E08000035",
"Wakefield" => "E08000036",
"Gateshead" => "E08000037",
"City of London" => "E09000001",
"Barking and Dagenham" => "E09000002",
"Barnet" => "E09000003",
"Bexley" => "E09000004",
"Brent" => "E09000005",
"Bromley" => "E09000006",
"Camden" => "E09000007",
"Croydon" => "E09000008",
"Ealing" => "E09000009",
"Enfield" => "E09000010",
"Greenwich" => "E09000011",
"Hackney" => "E09000012",
"Hammersmith and Fulham" => "E09000013",
"Haringey" => "E09000014",
"Harrow" => "E09000015",
"Havering" => "E09000016",
"Hillingdon" => "E09000017",
"Hounslow" => "E09000018",
"Islington" => "E09000019",
"Kensington and Chelsea" => "E09000020",
"Kingston upon Thames" => "E09000021",
"Lambeth" => "E09000022",
"Lewisham" => "E09000023",
"Merton" => "E09000024",
"Newham" => "E09000025",
"Redbridge" => "E09000026",
"Richmond upon Thames" => "E09000027",
"Southwark" => "E09000028",
"Sutton" => "E09000029",
"Tower Hamlets" => "E09000030",
"Waltham Forest" => "E09000031",
"Wandsworth" => "E09000032",
"Westminster" => "E09000033",
"Antrim and Newtownabbey" => "N09000001",
"Armagh City, Banbridge and Craigavon" => "N09000002",
"Belfast" => "N09000003",
"Causeway Coast and Glens" => "N09000004",
"Derry City and Strabane" => "N09000005",
"Fermanagh and Omagh" => "N09000006",
"Lisburn and Castlereagh" => "N09000007",
"Mid and East Antrim" => "N09000008",
"Mid Ulster" => "N09000009",
"Newry, Mourne and Down" => "N09000010",
"Ards and North Down" => "N09000011",
"Clackmannanshire" => "S12000005",
"Dumfries and Galloway" => "S12000006",
"East Ayrshire" => "S12000008",
"East Lothian" => "S12000010",
"East Renfrewshire" => "S12000011",
}
end
end

10
app/controllers/case_logs_controller.rb

@ -103,11 +103,17 @@ private
form = FormHandler.instance.get_form("2021_2022") form = FormHandler.instance.get_form("2021_2022")
form.expected_responses_for_page(page).each_with_object({}) do |(question_key, question_info), result| form.expected_responses_for_page(page).each_with_object({}) do |(question_key, question_info), result|
question_params = params["case_log"][question_key] question_params = params["case_log"][question_key]
if question_info["type"] == "date"
day = params["case_log"]["#{question_key}(3i)"]
month = params["case_log"]["#{question_key}(2i)"]
year = params["case_log"]["#{question_key}(1i)"]
result[question_key] = Date.new(year.to_i, month.to_i, day.to_i)
end
next unless question_params next unless question_params
if question_info["type"] == "checkbox" if %w[checkbox validation_override].include?(question_info["type"])
question_info["answer_options"].keys.reject { |x| x.match(/divider/) }.each do |option| question_info["answer_options"].keys.reject { |x| x.match(/divider/) }.each do |option|
result[option] = question_params.include?(option) result[option] = question_params.include?(option) ? 1 : 0
end end
else else
result[question_key] = question_params result[question_key] = question_params

20
app/controllers/soft_validations_controller.rb

@ -0,0 +1,20 @@
class SoftValidationsController < ApplicationController
def show
@case_log = CaseLog.find(params[:case_log_id])
page_key = request.env["PATH_INFO"].split("/")[-2]
form = FormHandler.instance.get_form("2021_2022")
page = form.all_pages[page_key]
if page_requires_soft_validation_override?(page)
errors = @case_log.soft_errors.values.first
render json: { show: true, label: errors.message, hint: errors.hint_text }
else
render json: { show: false }
end
end
private
def page_requires_soft_validation_override?(page)
@case_log.soft_errors.present? && @case_log.soft_errors.keys.first == page["soft_validations"]&.keys&.first
end
end

2
app/helpers/check_answers_helper.rb

@ -56,6 +56,8 @@ module CheckAnswersHelper
operator = condition[/[<>=]+/].to_sym operator = condition[/[<>=]+/].to_sym
operand = condition[/\d+/].to_i operand = condition[/\d+/].to_i
case_log[question_key].blank? || !case_log[question_key].send(operator, operand) case_log[question_key].blank? || !case_log[question_key].send(operator, operand)
when "text"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "radio" when "radio"
case_log[question_key].blank? || !condition.include?(case_log[question_key]) case_log[question_key].blank? || !condition.include?(case_log[question_key])
else else

7
app/javascript/controllers/conditional_question_controller.js

@ -12,7 +12,6 @@ export default class extends Controller {
case "radio": case "radio":
this.displayConditionalRadio() this.displayConditionalRadio()
default: default:
console.log("Not yet implemented for " + this.element.type)
break; break;
} }
} }
@ -22,7 +21,7 @@ export default class extends Controller {
let selectedValue = this.element.value let selectedValue = this.element.value
let conditional_for = JSON.parse(this.element.dataset.info) let conditional_for = JSON.parse(this.element.dataset.info)
Object.entries(conditional_for).forEach(([targetQuestion, conditions]) => { Object.entries(conditional_for).map(([targetQuestion, conditions]) => {
let div = document.getElementById(targetQuestion + "_div") let div = document.getElementById(targetQuestion + "_div")
if(conditions.includes(selectedValue)) { if(conditions.includes(selectedValue)) {
div.style.display = "block" div.style.display = "block"
@ -32,7 +31,7 @@ export default class extends Controller {
if (buttons.length == 0){ if (buttons.length == 0){
buttons = document.getElementsByName(`case_log[${targetQuestion}][]`); buttons = document.getElementsByName(`case_log[${targetQuestion}][]`);
} }
Object.entries(buttons).forEach(([idx, button]) => { Object.entries(buttons).map(([idx, button]) => {
button.checked = false; button.checked = false;
}) })
} }
@ -44,7 +43,7 @@ export default class extends Controller {
let enteredValue = this.element.value let enteredValue = this.element.value
let conditional_for = JSON.parse(this.element.dataset.info) let conditional_for = JSON.parse(this.element.dataset.info)
Object.entries(conditional_for).forEach(([targetQuestion, condition]) => { Object.entries(conditional_for).map(([targetQuestion, condition]) => {
let div = document.getElementById(targetQuestion + "_div") let div = document.getElementById(targetQuestion + "_div")
if(eval((enteredValue + condition))) { if(eval((enteredValue + condition))) {
div.style.display = "block" div.style.display = "block"

36
app/javascript/controllers/soft_validations_controller.js

@ -0,0 +1,36 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "override" ]
initialize() {
let url = window.location.href + "/soft_validations"
this.fetch_retry(url, { headers: { accept: "application/json" } }, 2)
}
fetch_retry(url, options, n) {
let self = this
let div = this.overrideTarget
fetch(url, options)
.then(response => response.json())
.then((response) => {
if(response["show"]){
div.style.display = "block"
let innerHTML = div.innerHTML
innerHTML = innerHTML.replace("soft-validations-placeholder-message", response["label"])
innerHTML = innerHTML.replace("soft-validations-placeholder-hint-text", response["hint"])
div.innerHTML = innerHTML
} else {
div.style.display = "none"
let buttons = document.getElementsByName(`case_log[override_net_income_validation][]`)
Object.entries(buttons).map(([idx, button]) => {
button.checked = false
})
}
})
.catch(function(error) {
if (n === 1) throw error
return self.fetch_retry(url, options, n - 1)
})
}
}

159
app/models/case_log.rb

@ -37,6 +37,7 @@ end
class CaseLog < ApplicationRecord class CaseLog < ApplicationRecord
include Discard::Model include Discard::Model
include SoftValidations include SoftValidations
include DbEnums
default_scope -> { kept } default_scope -> { kept }
scope :not_completed, -> { where.not(status: "completed") } scope :not_completed, -> { where.not(status: "completed") }
@ -47,6 +48,68 @@ class CaseLog < ApplicationRecord
enum status: { "not_started" => 0, "in_progress" => 1, "completed" => 2 } enum status: { "not_started" => 0, "in_progress" => 1, "completed" => 2 }
enum ethnic: DbEnums.ethnic
enum national: DbEnums.national, _suffix: true
enum ecstat1: DbEnums.ecstat, _suffix: true
enum ecstat2: DbEnums.ecstat, _suffix: true
enum ecstat3: DbEnums.ecstat, _suffix: true
enum ecstat4: DbEnums.ecstat, _suffix: true
enum ecstat5: DbEnums.ecstat, _suffix: true
enum ecstat6: DbEnums.ecstat, _suffix: true
enum ecstat7: DbEnums.ecstat, _suffix: true
enum ecstat8: DbEnums.ecstat, _suffix: true
enum prevten: DbEnums.previous_tenancy, _suffix: true
enum homeless: DbEnums.homeless, _suffix: true
enum underoccupation_benefitcap: DbEnums.benefitcap, _suffix: true
enum reservist: DbEnums.reservist, _suffix: true
enum leftreg: DbEnums.leftreg, _suffix: true
enum illness: DbEnums.illness, _suffix: true
enum preg_occ: DbEnums.pregnancy, _suffix: true
enum override_net_income_validation: DbEnums.override_soft_validation, _suffix: true
enum housingneeds_a: DbEnums.polar, _suffix: true
enum housingneeds_b: DbEnums.polar, _suffix: true
enum housingneeds_c: DbEnums.polar, _suffix: true
enum housingneeds_f: DbEnums.polar, _suffix: true
enum housingneeds_g: DbEnums.polar, _suffix: true
enum housingneeds_h: DbEnums.polar, _suffix: true
enum illness_type_1: DbEnums.polar, _suffix: true
enum illness_type_2: DbEnums.polar, _suffix: true
enum illness_type_3: DbEnums.polar, _suffix: true
enum illness_type_4: DbEnums.polar, _suffix: true
enum illness_type_5: DbEnums.polar, _suffix: true
enum illness_type_6: DbEnums.polar, _suffix: true
enum illness_type_7: DbEnums.polar, _suffix: true
enum illness_type_8: DbEnums.polar, _suffix: true
enum illness_type_9: DbEnums.polar, _suffix: true
enum illness_type_10: DbEnums.polar, _suffix: true
enum startertenancy: DbEnums.polar2, _suffix: true
enum tenancy: DbEnums.tenancy, _suffix: true
enum landlord: DbEnums.landlord, _suffix: true
enum rsnvac: DbEnums.rsnvac, _suffix: true
enum unittype_gn: DbEnums.unittype_gn, _suffix: true
enum rp_homeless: DbEnums.polar, _suffix: true
enum rp_insan_unsat: DbEnums.polar, _suffix: true
enum rp_medwel: DbEnums.polar, _suffix: true
enum rp_hardship: DbEnums.polar, _suffix: true
enum rp_dontknow: DbEnums.polar, _suffix: true
enum cbl: DbEnums.polar2, _suffix: true
enum chr: DbEnums.polar2, _suffix: true
enum cap: DbEnums.polar2, _suffix: true
enum wchair: DbEnums.polar2, _suffix: true
enum incfreq: DbEnums.incfreq, _suffix: true
enum benefits: DbEnums.benefits, _suffix: true
enum period: DbEnums.period, _suffix: true
enum layear: DbEnums.latime, _suffix: true
enum lawaitlist: DbEnums.latime, _suffix: true
enum reasonpref: DbEnums.polar_with_unknown, _suffix: true
enum reason: DbEnums.reason, _suffix: true
enum la: DbEnums.la, _suffix: true
enum prevloc: DbEnums.la, _suffix: true
enum majorrepairs: DbEnums.polar, _suffix: true
enum hb: DbEnums.housing_benefit, _suffix: true
enum hbrentshortfall: DbEnums.polar_with_unknown, _suffix: true
enum property_relet: DbEnums.polar, _suffix: true
AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze
def self.editable_fields def self.editable_fields
@ -66,20 +129,72 @@ class CaseLog < ApplicationRecord
end end
def weekly_net_income def weekly_net_income
case net_income_frequency case incfreq
when "Weekly" when "Weekly"
net_income earnings
when "Monthly" when "Monthly"
((net_income * 12) / 52.0).round(0) ((earnings * 12) / 52.0).round(0)
when "Yearly" when "Yearly"
(net_income / 12.0).round(0) (earnings / 12.0).round(0)
end
end
def postcode
if property_postcode.present?
UKPostcode.parse(property_postcode).outcode
end
end
def postcod2
if property_postcode.present?
UKPostcode.parse(property_postcode).incode
end
end end
def ppostc1
if previous_postcode.present?
UKPostcode.parse(previous_postcode).outcode
end
end
def ppostc2
if previous_postcode.present?
UKPostcode.parse(previous_postcode).incode
end
end
def hhmemb
other_hhmemb.presence
end end
def applicable_income_range def applicable_income_range
return unless person_1_economic_status return unless ecstat1
IncomeRange::ALLOWED[person_1_economic_status.to_sym] IncomeRange::ALLOWED[ecstat1.to_sym]
end
def mrcday
if mrcdate.present?
mrcdate.day
end
end
def mrcmonth
if mrcdate.present?
mrcdate.month
end
end
def mrcyear
if mrcdate.present?
mrcdate.year
end
end
def incref
if net_income_known == "Prefer not to say"
1
end
end end
private private
@ -107,37 +222,41 @@ private
dynamically_not_required = [] dynamically_not_required = []
if reason_for_leaving_last_settled_home != "Other" if reason != "Other"
dynamically_not_required << "other_reason_for_leaving_last_settled_home" dynamically_not_required << "other_reason_for_leaving_last_settled_home"
end end
if net_income.to_i.zero? if earnings.to_i.zero?
dynamically_not_required << "net_income_frequency" dynamically_not_required << "incfreq"
end end
if tenancy_type == "Fixed term – Secure" if tenancy == "Fixed term – Secure"
dynamically_not_required << "fixed_term_tenancy" dynamically_not_required << "tenancylength"
end end
unless net_income_in_soft_max_range? || net_income_in_soft_min_range? unless net_income_in_soft_max_range? || net_income_in_soft_min_range?
dynamically_not_required << "override_net_income_validation" dynamically_not_required << "override_net_income_validation"
end end
unless tenancy_type == "Other" unless tenancy == "Other"
dynamically_not_required << "other_tenancy_type" dynamically_not_required << "tenancyother"
end end
unless net_income_known == "Yes" unless net_income_known == "Yes"
dynamically_not_required << "net_income" dynamically_not_required << "earnings"
dynamically_not_required << "net_income_frequency" dynamically_not_required << "incfreq"
end end
start_range = (household_number_of_other_members || 0) + 2 start_range = (other_hhmemb || 0) + 2
(start_range..8).each do |n| (start_range..8).each do |n|
dynamically_not_required << "person_#{n}_age" dynamically_not_required << "age#{n}"
dynamically_not_required << "person_#{n}_gender" dynamically_not_required << "sex#{n}"
dynamically_not_required << "person_#{n}_relationship" dynamically_not_required << "relat#{n}"
dynamically_not_required << "person_#{n}_economic_status" dynamically_not_required << "ecstat#{n}"
end
if net_income_known != "Prefer not to say"
dynamically_not_required << "incref"
end end
required.delete_if { |key, _value| dynamically_not_required.include?(key) } required.delete_if { |key, _value| dynamically_not_required.include?(key) }

17
app/models/form.rb

@ -90,4 +90,21 @@ class Form
pages_for_subsection(subsection).keys[current_page_idx - 1] pages_for_subsection(subsection).keys[current_page_idx - 1]
end end
def all_questions
@all_questions ||= all_pages.map { |_page_key, page_value|
page_value["questions"]
}.reduce(:merge)
end
def get_answer_label(case_log, question_title)
question = all_questions[question_title]
if question["type"] == "checkbox"
answer = []
question["answer_options"].each { |key, value| case_log[key] == "Yes" ? answer << value : nil }
return answer.join(", ")
end
case_log[question_title]
end
end end

22
app/validations/financial_validations.rb

@ -2,36 +2,36 @@ module FinancialValidations
# Validations methods need to be called 'validate_<page_name>' to run on model save # Validations methods need to be called 'validate_<page_name>' to run on model save
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_outstanding_rent_amount(record) def validate_outstanding_rent_amount(record)
if record.outstanding_rent_or_charges == "Yes" && record.outstanding_amount.blank? if record.hbrentshortfall == "Yes" && record.tshortfall.blank?
record.errors.add :outstanding_amount, "You must answer the oustanding amout question if you have outstanding rent or charges." record.errors.add :tshortfall, "You must answer the oustanding amout question if you have outstanding rent or charges."
end end
if record.outstanding_rent_or_charges == "No" && record.outstanding_amount.present? if record.hbrentshortfall == "No" && record.tshortfall.present?
record.errors.add :outstanding_amount, "You must not answer the oustanding amout question if you don't have outstanding rent or charges." record.errors.add :tshortfall, "You must not answer the oustanding amout question if you don't have outstanding rent or charges."
end end
end end
EMPLOYED_STATUSES = ["Full-time - 30 hours or more", "Part-time - Less than 30 hours"].freeze EMPLOYED_STATUSES = ["Full-time - 30 hours or more", "Part-time - Less than 30 hours"].freeze
def validate_net_income_uc_proportion(record) def validate_net_income_uc_proportion(record)
(1..8).any? do |n| (1..8).any? do |n|
economic_status = record["person_#{n}_economic_status"] economic_status = record["ecstat#{n}"]
is_employed = EMPLOYED_STATUSES.include?(economic_status) is_employed = EMPLOYED_STATUSES.include?(economic_status)
relationship = record["person_#{n}_relationship"] relationship = record["relat#{n}"]
is_partner_or_main = relationship == "Partner" || (relationship.nil? && economic_status.present?) is_partner_or_main = relationship == "Partner" || (relationship.nil? && economic_status.present?)
if is_employed && is_partner_or_main && record.net_income_uc_proportion == "All" if is_employed && is_partner_or_main && record.benefits == "All"
record.errors.add :net_income_uc_proportion, "income is from Universal Credit, state pensions or benefits cannot be All if the tenant or the partner works part or full time" record.errors.add :benefits, "income is from Universal Credit, state pensions or benefits cannot be All if the tenant or the partner works part or full time"
end end
end end
end end
def validate_net_income(record) def validate_net_income(record)
return unless record.person_1_economic_status && record.weekly_net_income return unless record.ecstat1 && record.weekly_net_income
if record.weekly_net_income > record.applicable_income_range.hard_max if record.weekly_net_income > record.applicable_income_range.hard_max
record.errors.add :net_income, "Net income cannot be greater than #{record.applicable_income_range.hard_max} given the tenant's working situation" record.errors.add :earnings, "Net income cannot be greater than #{record.applicable_income_range.hard_max} given the tenant's working situation"
end end
if record.weekly_net_income < record.applicable_income_range.hard_min if record.weekly_net_income < record.applicable_income_range.hard_min
record.errors.add :net_income, "Net income cannot be less than #{record.applicable_income_range.hard_min} given the tenant's working situation" record.errors.add :earnings, "Net income cannot be less than #{record.applicable_income_range.hard_min} given the tenant's working situation"
end end
end end
end end

100
app/validations/household_validations.rb

@ -2,52 +2,52 @@ module HouseholdValidations
# Validations methods need to be called 'validate_<page_name>' to run on model save # Validations methods need to be called 'validate_<page_name>' to run on model save
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_reasonable_preference(record) def validate_reasonable_preference(record)
if record.homelessness == "No" && record.reasonable_preference == "Yes" if record.homeless == "No" && record.reasonpref == "Yes"
record.errors.add :reasonable_preference, "Can not be Yes if Not Homeless immediately prior to this letting has been selected" record.errors.add :reasonpref, "Can not be Yes if Not Homeless immediately prior to this letting has been selected"
elsif record.reasonable_preference == "Yes" elsif record.reasonpref == "Yes"
if !record.reasonable_preference_reason_homeless && !record.reasonable_preference_reason_unsatisfactory_housing && !record.reasonable_preference_reason_medical_grounds && !record.reasonable_preference_reason_avoid_hardship && !record.reasonable_preference_reason_do_not_know if !record.rp_homeless && !record.rp_insan_unsat && !record.rp_medwel && !record.rp_hardship && !record.rp_dontknow
record.errors.add :reasonable_preference_reason, "If reasonable preference is Yes, a reason must be given" record.errors.add :reasonable_preference_reason, "If reasonable preference is Yes, a reason must be given"
end end
elsif record.reasonable_preference == "No" elsif record.reasonpref == "No"
if record.reasonable_preference_reason_homeless || record.reasonable_preference_reason_unsatisfactory_housing || record.reasonable_preference_reason_medical_grounds || record.reasonable_preference_reason_avoid_hardship || record.reasonable_preference_reason_do_not_know if record.rp_homeless || record.rp_insan_unsat || record.rp_medwel || record.rp_hardship || record.rp_dontknow
record.errors.add :reasonable_preference_reason, "If reasonable preference is No, no reasons should be given" record.errors.add :reasonable_preference_reason, "If reasonable preference is No, no reasons should be given"
end end
end end
end end
def validate_other_reason_for_leaving_last_settled_home(record) def validate_other_reason_for_leaving_last_settled_home(record)
validate_other_field(record, "reason_for_leaving_last_settled_home", "other_reason_for_leaving_last_settled_home") validate_other_field(record, "reason", "other_reason_for_leaving_last_settled_home")
end end
def validate_reason_for_leaving_last_settled_home(record) 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" if record.reason == "Do not know" && record.underoccupation_benefitcap != "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" record.errors.add :underoccupation_benefitcap, "must be do not know if tenant’s main reason for leaving is do not know"
end end
end end
def validate_armed_forces_injured(record) def validate_armed_forces_injured(record)
if (record.armed_forces == "Yes - a regular" || record.armed_forces == "Yes - a reserve") && record.armed_forces_injured.blank? if (record.armed_forces == "Yes - a regular" || record.armed_forces == "Yes - a reserve") && record.reservist.blank?
record.errors.add :armed_forces_injured, "You must answer the armed forces injury question if the tenant has served in the armed forces" record.errors.add :reservist, "You must answer the armed forces injury question if the tenant has served in the armed forces"
end end
if (record.armed_forces == "No" || record.armed_forces == "Prefer not to say") && record.armed_forces_injured.present? if (record.armed_forces == "No" || record.armed_forces == "Prefer not to say") && record.reservist.present?
record.errors.add :armed_forces_injured, "You must not answer the armed forces injury question if the tenant has not served in the armed forces or prefer not to say was chosen" record.errors.add :reservist, "You must not answer the armed forces injury question if the tenant has not served in the armed forces or prefer not to say was chosen"
end end
end end
def validate_armed_forces_active_response(record) def validate_armed_forces_active_response(record)
if record.armed_forces == "Yes - a regular" && record.armed_forces_active.blank? if record.armed_forces == "Yes - a regular" && record.leftreg.blank?
record.errors.add :armed_forces_active, "You must answer the armed forces active question if the tenant has served as a regular in the armed forces" record.errors.add :leftreg, "You must answer the armed forces active question if the tenant has served as a regular in the armed forces"
end end
if record.armed_forces != "Yes - a regular" && record.armed_forces_active.present? if record.armed_forces != "Yes - a regular" && record.leftreg.present?
record.errors.add :armed_forces_active, "You must not answer the armed forces active question if the tenant has not served as a regular in the armed forces" record.errors.add :leftreg, "You must not answer the armed forces active question if the tenant has not served as a regular in the armed forces"
end end
end end
def validate_household_pregnancy(record) def validate_household_pregnancy(record)
if (record.pregnancy == "Yes" || record.pregnancy == "Prefer not to say") && !women_of_child_bearing_age_in_household(record) if (record.preg_occ == "Yes" || record.preg_occ == "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" record.errors.add :preg_occ, "You must answer no as there are no female tenants aged 16-50 in the property"
end end
end end
@ -63,10 +63,10 @@ module HouseholdValidations
end end
def validate_person_1_age(record) def validate_person_1_age(record)
return unless record.person_1_age return unless record.age1
if !record.person_1_age.is_a?(Integer) || record.person_1_age < 16 || record.person_1_age > 120 if !record.age1.is_a?(Integer) || record.age1 < 16 || record.age1 > 120
record.errors.add "person_1_age", "Tenant age must be an integer between 16 and 120" record.errors.add "age1", "Tenant age must be an integer between 16 and 120"
end end
end end
@ -75,17 +75,17 @@ module HouseholdValidations
end end
def validate_shared_housing_rooms(record) def validate_shared_housing_rooms(record)
unless record.property_unit_type.nil? unless record.unittype_gn.nil?
if record.property_unit_type == "Bed-sit" && record.property_number_of_bedrooms != 1 if record.unittype_gn == "Bed-sit" && record.beds != 1
record.errors.add :property_unit_type, "A bedsit can only have one bedroom" record.errors.add :unittype_gn, "A bedsit can only have one bedroom"
end end
if !record.household_number_of_other_members.nil? && record.household_number_of_other_members.positive? && (record.property_unit_type.include?("Shared") && !record.property_number_of_bedrooms.to_i.between?(1, 7)) if !record.other_hhmemb.nil? && record.other_hhmemb.positive? && (record.unittype_gn.include?("Shared") && !record.beds.to_i.between?(1, 7))
record.errors.add :property_unit_type, "A shared house must have 1 to 7 bedrooms" record.errors.add :unittype_gn, "A shared house must have 1 to 7 bedrooms"
end end
if record.property_unit_type.include?("Shared") && !record.property_number_of_bedrooms.to_i.between?(1, 3) if record.unittype_gn.include?("Shared") && !record.beds.to_i.between?(1, 3)
record.errors.add :property_unit_type, "A shared house with less than two tenants must have 1 to 3 bedrooms" record.errors.add :unittype_gn, "A shared house with less than two tenants must have 1 to 3 bedrooms"
end end
end end
end end
@ -94,72 +94,72 @@ private
def women_of_child_bearing_age_in_household(record) def women_of_child_bearing_age_in_household(record)
(1..8).any? do |n| (1..8).any? do |n|
next if record["person_#{n}_gender"].nil? || record["person_#{n}_age"].nil? next if record["sex#{n}"].nil? || record["age#{n}"].nil?
record["person_#{n}_gender"] == "Female" && record["person_#{n}_age"] >= 16 && record["person_#{n}_age"] <= 50 record["sex#{n}"] == "Female" && record["age#{n}"] >= 16 && record["age#{n}"] <= 50
end end
end end
def validate_person_age(record, person_num) def validate_person_age(record, person_num)
age = record.public_send("person_#{person_num}_age") age = record.public_send("age#{person_num}")
return unless age return unless age
if !age.is_a?(Integer) || age < 1 || age > 120 if !age.is_a?(Integer) || age < 1 || age > 120
record.errors.add "person_#{person_num}_age".to_sym, "Tenant age must be an integer between 0 and 120" record.errors.add "age#{person_num}".to_sym, "Tenant age must be an integer between 0 and 120"
end end
end end
def validate_person_age_matches_economic_status(record, person_num) def validate_person_age_matches_economic_status(record, person_num)
age = record.public_send("person_#{person_num}_age") age = record.public_send("age#{person_num}")
economic_status = record.public_send("person_#{person_num}_economic_status") economic_status = record.public_send("ecstat#{person_num}")
return unless age && economic_status return unless age && economic_status
if age > 70 && economic_status != "Retired" if age > 70 && economic_status != "Retired"
record.errors.add "person_#{person_num}_economic_status", "Tenant #{person_num} must be retired if over 70" record.errors.add "ecstat#{person_num}", "Tenant #{person_num} must be retired if over 70"
end end
if age < 16 && economic_status != "Child under 16" if age < 16 && economic_status != "Child under 16"
record.errors.add "person_#{person_num}_economic_status", "Tenant #{person_num} economic status must be Child under 16 if their age is under 16" record.errors.add "ecstat#{person_num}", "Tenant #{person_num} economic status must be Child under 16 if their age is under 16"
end end
end end
def validate_person_age_matches_relationship(record, person_num) def validate_person_age_matches_relationship(record, person_num)
age = record.public_send("person_#{person_num}_age") age = record.public_send("age#{person_num}")
relationship = record.public_send("person_#{person_num}_relationship") relationship = record.public_send("relat#{person_num}")
return unless age && relationship return unless age && relationship
if age < 16 && relationship != "Child - includes young adult and grown-up" if age < 16 && relationship != "Child - includes young adult and grown-up"
record.errors.add "person_#{person_num}_relationship", "Tenant #{person_num}'s relationship to tenant 1 must be Child if their age is under 16" record.errors.add "relat#{person_num}", "Tenant #{person_num}'s relationship to tenant 1 must be Child if their age is under 16"
end end
end end
def validate_person_age_and_relationship_matches_economic_status(record, person_num) def validate_person_age_and_relationship_matches_economic_status(record, person_num)
age = record.public_send("person_#{person_num}_age") age = record.public_send("age#{person_num}")
economic_status = record.public_send("person_#{person_num}_economic_status") economic_status = record.public_send("ecstat#{person_num}")
relationship = record.public_send("person_#{person_num}_relationship") relationship = record.public_send("relat#{person_num}")
return unless age && economic_status && relationship return unless age && economic_status && relationship
if age >= 16 && age <= 19 && relationship == "Child - includes young adult and grown-up" && (economic_status != "Full-time student" || economic_status != "Prefer not to say") if age >= 16 && age <= 19 && relationship == "Child - includes young adult and grown-up" && (economic_status != "Full-time student" || economic_status != "Prefer not to say")
record.errors.add "person_#{person_num}_economic_status", "If age is between 16 and 19 - tenant #{person_num} must be a full time student or prefer not to say." record.errors.add "ecstat#{person_num}", "If age is between 16 and 19 - tenant #{person_num} must be a full time student or prefer not to say."
end end
end end
def validate_person_age_and_gender_match_economic_status(record, person_num) def validate_person_age_and_gender_match_economic_status(record, person_num)
age = record.public_send("person_#{person_num}_age") age = record.public_send("age#{person_num}")
gender = record.public_send("person_#{person_num}_gender") gender = record.public_send("sex#{person_num}")
economic_status = record.public_send("person_#{person_num}_economic_status") economic_status = record.public_send("ecstat#{person_num}")
return unless age && economic_status && gender return unless age && economic_status && gender
if gender == "Male" && economic_status == "Retired" && age < 65 if gender == "Male" && economic_status == "Retired" && age < 65
record.errors.add "person_#{person_num}_age", "Male tenant who is retired must be 65 or over" record.errors.add "age#{person_num}", "Male tenant who is retired must be 65 or over"
end end
if gender == "Female" && economic_status == "Retired" && age < 60 if gender == "Female" && economic_status == "Retired" && age < 60
record.errors.add "person_#{person_num}_age", "Female tenant who is retired must be 60 or over" record.errors.add "age#{person_num}", "Female tenant who is retired must be 60 or over"
end end
end end
def validate_partner_count(record) def validate_partner_count(record)
# TODO: probably need to keep track of which specific field is wrong so we can highlight it in the UI # TODO: probably need to keep track of which specific field is wrong so we can highlight it in the UI
partner_count = (2..8).count { |n| record.public_send("person_#{n}_relationship") == "Partner" } partner_count = (2..8).count { |n| record.public_send("relat#{n}") == "Partner" }
if partner_count > 1 if partner_count > 1
record.errors.add :base, "Number of partners cannot be greater than 1" record.errors.add :base, "Number of partners cannot be greater than 1"
end end

4
app/validations/property_validations.rb

@ -2,8 +2,8 @@ module PropertyValidations
# Validations methods need to be called 'validate_<page_name>' to run on model save # Validations methods need to be called 'validate_<page_name>' to run on model save
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_property_number_of_times_relet(record) def validate_property_number_of_times_relet(record)
if record.property_number_of_times_relet && !/^[1-9]$|^0[1-9]$|^1[0-9]$|^20$/.match?(record.property_number_of_times_relet.to_s) if record.offered && !/^[1-9]$|^0[1-9]$|^1[0-9]$|^20$/.match?(record.offered.to_s)
record.errors.add :property_number_of_times_relet, "Property number of times relet must be between 0 and 20" record.errors.add :offered, "Property number of times relet must be between 0 and 20"
end end
end end
end end

10
app/validations/soft_validations.rb

@ -8,7 +8,7 @@ module SoftValidations
end end
def soft_errors_overridden? def soft_errors_overridden?
public_send(soft_errors.keys.first) if soft_errors.present? public_send(soft_errors.keys.first) == "Yes" if soft_errors.present?
end end
private private
@ -18,12 +18,12 @@ private
if net_income_in_soft_min_range? if net_income_in_soft_min_range?
net_income_errors["override_net_income_validation"] = OpenStruct.new( net_income_errors["override_net_income_validation"] = OpenStruct.new(
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 main tenant's working situation. Are you sure this is correct?",
hint_text: "This is based on the tenant's work situation: #{person_1_economic_status}", hint_text: "This is based on the tenant's work situation: #{ecstat1}",
) )
elsif net_income_in_soft_max_range? elsif net_income_in_soft_max_range?
net_income_errors["override_net_income_validation"] = OpenStruct.new( net_income_errors["override_net_income_validation"] = OpenStruct.new(
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 main tenant's working situation. Are you sure this is correct?",
hint_text: "This is based on the tenant's work situation: #{person_1_economic_status}", hint_text: "This is based on the tenant's work situation: #{ecstat1}",
) )
else else
update_column(:override_net_income_validation, nil) update_column(:override_net_income_validation, nil)
@ -32,13 +32,13 @@ private
end end
def net_income_in_soft_max_range? def net_income_in_soft_max_range?
return unless weekly_net_income && person_1_economic_status return unless weekly_net_income && ecstat1
weekly_net_income.between?(applicable_income_range.soft_max, applicable_income_range.hard_max) weekly_net_income.between?(applicable_income_range.soft_max, applicable_income_range.hard_max)
end end
def net_income_in_soft_min_range? def net_income_in_soft_min_range?
return unless weekly_net_income && person_1_economic_status return unless weekly_net_income && ecstat1
weekly_net_income.between?(applicable_income_range.soft_min, applicable_income_range.hard_min) weekly_net_income.between?(applicable_income_range.soft_min, applicable_income_range.hard_min)
end end

12
app/validations/tenancy_validations.rb

@ -2,20 +2,20 @@ module TenancyValidations
# Validations methods need to be called 'validate_<page_name>' to run on model save # Validations methods need to be called 'validate_<page_name>' to run on model save
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_fixed_term_tenancy(record) def validate_fixed_term_tenancy(record)
is_present = record.fixed_term_tenancy.present? is_present = record.tenancylength.present?
is_in_range = record.fixed_term_tenancy.to_i.between?(2, 99) is_in_range = record.tenancylength.to_i.between?(2, 99)
is_secure = record.tenancy_type == "Fixed term – Secure" is_secure = record.tenancy == "Fixed term – Secure"
is_ast = record.tenancy_type == "Fixed term – Assured Shorthold Tenancy (AST)" is_ast = record.tenancy == "Fixed term – Assured Shorthold Tenancy (AST)"
conditions = [ conditions = [
{ condition: !(is_secure || is_ast) && is_present, error: "You must only answer the fixed term tenancy length question if the tenancy type is fixed term" }, { condition: !(is_secure || is_ast) && is_present, error: "You must only answer the fixed term tenancy length question if the tenancy type is fixed term" },
{ condition: is_ast && !is_in_range, error: "Fixed term – Assured Shorthold Tenancy (AST) should be between 2 and 99 years" }, { condition: is_ast && !is_in_range, error: "Fixed term – Assured Shorthold Tenancy (AST) should be between 2 and 99 years" },
{ condition: is_secure && (!is_in_range && is_present), error: "Fixed term – Secure should be between 2 and 99 years or not specified" }, { condition: is_secure && (!is_in_range && is_present), error: "Fixed term – Secure should be between 2 and 99 years or not specified" },
] ]
conditions.each { |condition| condition[:condition] ? (record.errors.add :fixed_term_tenancy, condition[:error]) : nil } conditions.each { |condition| condition[:condition] ? (record.errors.add :tenancylength, condition[:error]) : nil }
end end
def validate_other_tenancy_type(record) def validate_other_tenancy_type(record)
validate_other_field(record, "tenancy_type", "other_tenancy_type") validate_other_field(record, "tenancy", "tenancyother")
end end
end end

2
app/views/form/_check_answers_table.html.erb

@ -4,7 +4,7 @@
<%= question_info["check_answer_label"].to_s.present? ? question_info["check_answer_label"].to_s : question_info["header"].to_s%> <%= question_info["check_answer_label"].to_s.present? ? question_info["check_answer_label"].to_s : question_info["header"].to_s%>
<dt> <dt>
<dd class="govuk-summary-list__value"> <dd class="govuk-summary-list__value">
<%= @case_log[question_title] %> <%= form.get_answer_label(@case_log, question_title) %>
</dd> </dd>
<dd class="govuk-summary-list__actions"> <dd class="govuk-summary-list__actions">
<%= create_update_answer_link(@case_log[question_title], @case_log.id, page)%> <%= create_update_answer_link(@case_log[question_title], @case_log.id, page)%>

2
app/views/form/_checkbox_question.html.erb

@ -8,7 +8,7 @@
<% else %> <% else %>
<%= f.govuk_check_box question_key, key, <%= f.govuk_check_box question_key, key,
label: { text: val }, label: { text: val },
checked: f.object.send(key), checked: @case_log[key] == "Yes",
**stimulus_html_attributes(question) **stimulus_html_attributes(question)
%> %>
<% end %> <% end %>

11
app/views/form/_select_question.html.erb

@ -0,0 +1,11 @@
<%= answers = question["answer_options"].map {|key, value| OpenStruct.new(id:key, name: value)}
f.govuk_collection_select question_key,
answers,
:name,
:name,
label: { text: question["header"]},
hint: { text: question["hint_text"] }
%>

16
app/views/form/_validation_override_question.html.erb

@ -1,11 +1,15 @@
<div class="govuk-form-group govuk-form-group--error"> <div class="govuk-form-group govuk-form-group--error"
<%= f.govuk_check_boxes_fieldset @case_log.soft_errors.keys.first, data-controller="soft-validations"
legend: { text: @case_log.soft_errors.values.first.message, size: "l" }, data-soft-validations-target="override"
hint: { text: @case_log.soft_errors.values.first.hint_text } do %> style='display:none;'>
<%= f.govuk_check_box @case_log.soft_errors.keys.first, @case_log.soft_errors.keys.first, <%= f.govuk_check_boxes_fieldset page_info["soft_validations"]&.keys&.first,
legend: { text: "soft-validations-placeholder-message", size: "l" },
hint: { text: "soft-validations-placeholder-hint-text" } do %>
<%= f.govuk_check_box page_info["soft_validations"]&.keys&.first, page_info["soft_validations"]&.keys&.first,
label: { text: "Yes" }, label: { text: "Yes" },
checked: f.object.send(@case_log.soft_errors.keys.first) checked: @case_log[page_info["soft_validations"]&.keys&.first] == "Yes"
%> %>
<% end %> <% end %>
</div> </div>

2
app/views/form/check_answers.html.erb

@ -6,7 +6,7 @@
<% form.pages_for_subsection(subsection).each do |page, page_info| %> <% form.pages_for_subsection(subsection).each do |page, page_info| %>
<% page_info["questions"].each do |question_title, question_info| %> <% page_info["questions"].each do |question_title, question_info| %>
<% if total_questions(subsection, @case_log, form).include?(question_title) %> <% if total_questions(subsection, @case_log, form).include?(question_title) %>
<%= render partial: 'form/check_answers_table', locals: { question_title: question_title, question_info: question_info, case_log: @case_log, page: page } %> <%= render partial: 'form/check_answers_table', locals: { question_title: question_title, question_info: question_info, case_log: @case_log, page: page, form: form } %>
<%end %> <%end %>
<%end %> <%end %>
<% end %> <% end %>

8
app/views/form/page.html.erb

@ -1,7 +1,5 @@
<meta http-equiv="Pragma" content="no-cache">
<% content_for :before_content do %> <% content_for :before_content do %>
<%= link_to 'Back', :back, class: "govuk-back-link" %> <%= link_to 'Back', 'javascript:history.back()', class: "govuk-back-link" %>
<% end %> <% end %>
<%= turbo_frame_tag "case_log_form", target: "_top" do %> <%= turbo_frame_tag "case_log_form", target: "_top" do %>
@ -19,8 +17,8 @@
</div> </div>
<% end %> <% end %>
<% if @case_log.soft_errors.present? && @case_log.soft_errors.keys.first == page_info["soft_validations"]&.keys&.first %> <% if page_info["soft_validations"]&.keys&.first %>
<%= render partial: "form/validation_override_question", locals: { f: f } %> <%= render partial: "form/validation_override_question", locals: { f: f, page_key: page_key, page_info: page_info } %>
<% end %> <% end %>
<%= f.hidden_field :page, value: page_key %> <%= f.hidden_field :page, value: page_key %>

561
config/forms/2021_2022.json

File diff suppressed because it is too large Load Diff

2
config/initializers/active_admin.rb

@ -157,7 +157,7 @@ ActiveAdmin.setup do |config|
# You can exclude possibly sensitive model attributes from being displayed, # You can exclude possibly sensitive model attributes from being displayed,
# added to forms, or exported by default by ActiveAdmin # added to forms, or exported by default by ActiveAdmin
# #
config.filter_attributes = [:encrypted_password, :password, :password_confirmation] config.filter_attributes = %i[encrypted_password password password_confirmation]
# == Localize Date/Time Format # == Localize Date/Time Format
# #

1
config/routes.rb

@ -11,6 +11,7 @@ Rails.application.routes.draw do
resources :case_logs do resources :case_logs do
form.all_pages.keys.map do |page| form.all_pages.keys.map do |page|
get page.to_s, to: "case_logs##{page}" get page.to_s, to: "case_logs##{page}"
get "#{page}/soft_validations", to: "soft_validations#show"
end end
form.all_subsections.keys.map do |subsection| form.all_subsections.keys.map do |subsection|
get "#{subsection}/check_answers", to: "case_logs#check_answers" get "#{subsection}/check_answers", to: "case_logs#check_answers"

106
db/migrate/20211101192151_rename_fields.rb

@ -0,0 +1,106 @@
class RenameFields < ActiveRecord::Migration[6.1]
def change
rename_column :case_logs, :person_1_age, :age1
rename_column :case_logs, :person_1_gender, :sex1
rename_column :case_logs, :tenant_ethnic_group, :ethnic
rename_column :case_logs, :tenant_nationality, :national
rename_column :case_logs, :person_1_economic_status, :ecstat1
rename_column :case_logs, :household_number_of_other_members, :hhmemb
rename_column :case_logs, :person_2_relationship, :relat2
rename_column :case_logs, :person_2_age, :age2
rename_column :case_logs, :person_2_gender, :sex2
rename_column :case_logs, :person_2_economic_status, :ecstat2
rename_column :case_logs, :person_3_relationship, :relat3
rename_column :case_logs, :person_3_age, :age3
rename_column :case_logs, :person_3_gender, :sex3
rename_column :case_logs, :person_3_economic_status, :ecstat3
rename_column :case_logs, :person_4_relationship, :relat4
rename_column :case_logs, :person_4_age, :age4
rename_column :case_logs, :person_4_gender, :sex4
rename_column :case_logs, :person_4_economic_status, :ecstat4
rename_column :case_logs, :person_5_relationship, :relat5
rename_column :case_logs, :person_5_age, :age5
rename_column :case_logs, :person_5_gender, :sex5
rename_column :case_logs, :person_5_economic_status, :ecstat5
rename_column :case_logs, :person_6_relationship, :relat6
rename_column :case_logs, :person_6_age, :age6
rename_column :case_logs, :person_6_gender, :sex6
rename_column :case_logs, :person_6_economic_status, :ecstat6
rename_column :case_logs, :person_7_relationship, :relat7
rename_column :case_logs, :person_7_age, :age7
rename_column :case_logs, :person_7_gender, :sex7
rename_column :case_logs, :person_7_economic_status, :ecstat7
rename_column :case_logs, :person_8_relationship, :relat8
rename_column :case_logs, :person_8_age, :age8
rename_column :case_logs, :person_8_gender, :sex8
rename_column :case_logs, :person_8_economic_status, :ecstat8
rename_column :case_logs, :previous_housing_situation, :prevten
rename_column :case_logs, :homelessness, :homeless
rename_column :case_logs, :benefit_cap_spare_room_subsidy, :underoccupation_benefitcap
rename_column :case_logs, :armed_forces_injured, :reservist
rename_column :case_logs, :armed_forces_active, :leftreg
rename_column :case_logs, :medical_conditions, :illness
rename_column :case_logs, :pregnancy, :preg_occ
rename_column :case_logs, :accessibility_requirements_fully_wheelchair_accessible_housing, :housingneeds_a
rename_column :case_logs, :accessibility_requirements_wheelchair_access_to_essential_rooms, :housingneeds_b
rename_column :case_logs, :accessibility_requirements_level_access_housing, :housingneeds_c
rename_column :case_logs, :accessibility_requirements_other_disability_requirements, :housingneeds_f
rename_column :case_logs, :accessibility_requirements_no_disability_requirements, :housingneeds_g
rename_column :case_logs, :accessibility_requirements_do_not_know, :housingneeds_h
rename_column :case_logs, :condition_effects_vision, :illness_type_1
rename_column :case_logs, :condition_effects_hearing, :illness_type_2
rename_column :case_logs, :condition_effects_mobility, :illness_type_3
rename_column :case_logs, :condition_effects_dexterity, :illness_type_4
rename_column :case_logs, :condition_effects_stamina, :illness_type_8
rename_column :case_logs, :condition_effects_learning, :illness_type_5
rename_column :case_logs, :condition_effects_memory, :illness_type_6
rename_column :case_logs, :condition_effects_mental_health, :illness_type_7
rename_column :case_logs, :condition_effects_social_or_behavioral, :illness_type_9
rename_column :case_logs, :condition_effects_other, :illness_type_10
rename_column :case_logs, :tenancy_start_date, :startdate
rename_column :case_logs, :starter_tenancy, :startertenancy
rename_column :case_logs, :fixed_term_tenancy, :tenancylength
rename_column :case_logs, :tenancy_type, :tenancy
rename_column :case_logs, :other_tenancy_type, :tenancyother
rename_column :case_logs, :letting_type, :lettype
rename_column :case_logs, :letting_provider, :landlord
rename_column :case_logs, :property_vacancy_reason, :rsnvac
rename_column :case_logs, :property_unit_type, :unittype_gn
rename_column :case_logs, :property_number_of_bedrooms, :beds
rename_column :case_logs, :property_number_of_times_relet, :offered
rename_column :case_logs, :property_wheelchair_accessible, :wchair
rename_column :case_logs, :net_income, :earnings
rename_column :case_logs, :net_income_frequency, :incfreq
rename_column :case_logs, :net_income_uc_proportion, :benefits
rename_column :case_logs, :rent_frequency, :period
rename_column :case_logs, :basic_rent, :brent
rename_column :case_logs, :service_charge, :scharge
rename_column :case_logs, :personal_service_charge, :pscharge
rename_column :case_logs, :support_charge, :supcharg
rename_column :case_logs, :total_charge, :tcharge
rename_column :case_logs, :time_lived_in_la, :layear
rename_column :case_logs, :time_on_la_waiting_list, :lawaitlist
rename_column :case_logs, :reasonable_preference, :reasonpref
rename_column :case_logs, :reasonable_preference_reason_homeless, :rp_homeless
rename_column :case_logs, :reasonable_preference_reason_unsatisfactory_housing, :rp_insan_unsat
rename_column :case_logs, :reasonable_preference_reason_medical_grounds, :rp_medwel
rename_column :case_logs, :reasonable_preference_reason_avoid_hardship, :rp_hardship
rename_column :case_logs, :reasonable_preference_reason_do_not_know, :rp_dontknow
rename_column :case_logs, :cbl_letting, :cbl
rename_column :case_logs, :chr_letting, :chr
rename_column :case_logs, :cap_letting, :cap
end
end

17
db/migrate/20211102100820_add_about_this_log_readable_columns.rb

@ -0,0 +1,17 @@
class AddAboutThisLogReadableColumns < ActiveRecord::Migration[6.1]
def change
change_table :case_logs, bulk: true do |t|
t.column :gdpr_acceptance, :string
t.column :gdpr_declined, :string
t.column :property_owner_organisation, :string
t.column :property_manager_organisation, :string
t.column :sale_or_letting, :string
t.column :tenant_same_property_renewal, :string
t.column :rent_type, :string
t.column :intermediate_rent_product_name, :string
t.column :needs_type, :string
t.column :sale_completion_date, :string
t.column :purchaser_code, :string
end
end
end

131
db/migrate/20211103090530_change_field_types.rb

@ -0,0 +1,131 @@
class ChangeFieldTypes < ActiveRecord::Migration[6.1]
def up
change_table :case_logs, bulk: true do |t|
t.change :ethnic, "integer USING ethnic::integer"
t.change :national, "integer USING national::integer"
t.change :ecstat1, "integer USING ecstat1::integer"
t.change :ecstat2, "integer USING ecstat2::integer"
t.change :ecstat3, "integer USING ecstat3::integer"
t.change :ecstat4, "integer USING ecstat4::integer"
t.change :ecstat5, "integer USING ecstat5::integer"
t.change :ecstat6, "integer USING ecstat6::integer"
t.change :ecstat7, "integer USING ecstat7::integer"
t.change :ecstat8, "integer USING ecstat8::integer"
t.change :prevten, "integer USING prevten::integer"
t.change :homeless, "integer USING homeless::integer"
t.change :underoccupation_benefitcap, "integer USING underoccupation_benefitcap::integer"
t.change :reservist, "integer USING reservist::integer"
t.change :leftreg, "integer USING leftreg::integer"
t.change :illness, "integer USING illness::integer"
t.change :preg_occ, "integer USING preg_occ::integer"
t.change :housingneeds_a, "integer USING housingneeds_a::integer"
t.change :housingneeds_b, "integer USING housingneeds_b::integer"
t.change :housingneeds_c, "integer USING housingneeds_c::integer"
t.change :housingneeds_f, "integer USING housingneeds_f::integer"
t.change :housingneeds_g, "integer USING housingneeds_g::integer"
t.change :housingneeds_h, "integer USING housingneeds_h::integer"
t.change :illness_type_1, "integer USING illness_type_1::integer"
t.change :illness_type_2, "integer USING illness_type_2::integer"
t.change :illness_type_3, "integer USING illness_type_3::integer"
t.change :illness_type_4, "integer USING illness_type_4::integer"
t.change :illness_type_5, "integer USING illness_type_5::integer"
t.change :illness_type_6, "integer USING illness_type_6::integer"
t.change :illness_type_7, "integer USING illness_type_7::integer"
t.change :illness_type_8, "integer USING illness_type_8::integer"
t.change :illness_type_9, "integer USING illness_type_9::integer"
t.change :illness_type_10, "integer USING illness_type_10::integer"
t.change :rp_homeless, "integer USING rp_homeless::integer"
t.change :rp_insan_unsat, "integer USING rp_insan_unsat::integer"
t.change :rp_medwel, "integer USING rp_medwel::integer"
t.change :rp_hardship, "integer USING rp_hardship::integer"
t.change :rp_dontknow, "integer USING rp_dontknow::integer"
t.change :cbl, "integer USING cbl::integer"
t.change :chr, "integer USING chr::integer"
t.change :cap, "integer USING cap::integer"
t.change :startertenancy, "integer USING startertenancy::integer"
t.change :tenancylength, "integer USING tenancylength::integer"
t.change :tenancy, "integer USING tenancy::integer"
t.change :landlord, "integer USING landlord::integer"
t.change :rsnvac, "integer USING rsnvac::integer"
t.change :unittype_gn, "integer USING unittype_gn::integer"
t.change :beds, "integer USING beds::integer"
t.change :wchair, "integer USING wchair::integer"
t.change :incfreq, "integer USING incfreq::integer"
t.change :benefits, "integer USING benefits::integer"
t.change :period, "integer USING period::integer"
t.change :brent, "integer USING brent::integer"
t.change :scharge, "integer USING scharge::integer"
t.change :pscharge, "integer USING pscharge::integer"
t.change :supcharg, "integer USING supcharg::integer"
t.change :tcharge, "integer USING tcharge::integer"
t.change :layear, "integer USING layear::integer"
t.change :lawaitlist, "integer USING lawaitlist::integer"
t.change :reasonpref, "integer USING reasonpref::integer"
end
end
def down
change_table :case_logs, bulk: true do |t|
t.change :ethnic, :string
t.change :national, :string
t.change :ecstat1, :string
t.change :ecstat2, :string
t.change :ecstat3, :string
t.change :ecstat4, :string
t.change :ecstat5, :string
t.change :ecstat6, :string
t.change :ecstat7, :string
t.change :ecstat8, :string
t.change :prevten, :string
t.change :homeless, :string
t.change :underoccupation_benefitcap, :string
t.change :reservist, :string
t.change :leftreg, :string
t.change :illness, :string
t.change :preg_occ, :string
t.change :housingneeds_a, "boolean USING housingneeds_a::boolean"
t.change :housingneeds_b, "boolean USING housingneeds_b::boolean"
t.change :housingneeds_c, "boolean USING housingneeds_c::boolean"
t.change :housingneeds_f, "boolean USING housingneeds_f::boolean"
t.change :housingneeds_g, "boolean USING housingneeds_g::boolean"
t.change :housingneeds_h, "boolean USING housingneeds_h::boolean"
t.change :illness_type_1, "boolean USING illness_type_1::boolean"
t.change :illness_type_2, "boolean USING illness_type_2::boolean"
t.change :illness_type_3, "boolean USING illness_type_3::boolean"
t.change :illness_type_4, "boolean USING illness_type_4::boolean"
t.change :illness_type_5, "boolean USING illness_type_5::boolean"
t.change :illness_type_6, "boolean USING illness_type_6::boolean"
t.change :illness_type_7, "boolean USING illness_type_7::boolean"
t.change :illness_type_8, "boolean USING illness_type_8::boolean"
t.change :illness_type_9, "boolean USING illness_type_9::boolean"
t.change :illness_type_10, "boolean USING illness_type_10::boolean"
t.change :rp_homeless, :boolean
t.change :rp_insan_unsat, :boolean
t.change :rp_medwel, :boolean
t.change :rp_hardship, :boolean
t.change :rp_dontknow, :boolean
t.change :cbl_letting, :string
t.change :chr_letting, :string
t.change :cap_letting, :string
t.change :startertenancy, :string
t.change :tenancylength, :string
t.change :tenancy, :string
t.change :landlord, :string
t.change :rsnvac, :string
t.change :unittype_gn, :string
t.change :beds, :string
t.change :wchair, :string
t.change :incfreq, :string
t.change :benefits, :string
t.change :period, :string
t.change :brent, :string
t.change :scharge, :string
t.change :pscharge, :string
t.change :supcharg, :string
t.change :tcharge, :string
t.change :layear, :string
t.change :lawaitlist, :string
t.change :reasonpref, :string
end
end
end

9
db/migrate/20211105164644_change_net_income_overide.rb

@ -0,0 +1,9 @@
class ChangeNetIncomeOveride < ActiveRecord::Migration[6.1]
def up
change_column :case_logs, :override_net_income_validation, "integer USING CAST(override_net_income_validation AS integer)"
end
def down
change_column :case_logs, :override_net_income_validation, "boolean USING override_net_income_validation::boolean"
end
end

15
db/migrate/20211108091320_change_checkbox_types.rb

@ -0,0 +1,15 @@
class ChangeCheckboxTypes < ActiveRecord::Migration[6.1]
def up
change_table :case_logs, bulk: true do |t|
t.change :accessibility_requirements_prefer_not_to_say, "integer USING accessibility_requirements_prefer_not_to_say::integer"
t.change :condition_effects_prefer_not_to_say, "integer USING condition_effects_prefer_not_to_say::integer"
end
end
def down
change_table :case_logs, bulk: true do |t|
t.change :accessibility_requirements_prefer_not_to_say, "boolean USING accessibility_requirements_prefer_not_to_say::boolean"
t.change :condition_effects_prefer_not_to_say, "boolean USING condition_effects_prefer_not_to_say::boolean"
end
end
end

57
db/migrate/20211108134601_further_core_migrations.rb

@ -0,0 +1,57 @@
class FurtherCoreMigrations < ActiveRecord::Migration[6.1]
def up
change_table :case_logs, bulk: true do |t|
t.remove :condition_effects_prefer_not_to_say
t.remove :reason_for_leaving_last_settled_home
t.column :reason, :integer
t.remove :property_reference
t.column :propcode, :string
t.remove :property_major_repairs
t.column :majorrepairs, :integer
t.remove :property_location
t.column :la, :string
t.remove :previous_la
t.column :prevloc, :string
t.remove :housing_benefit
t.column :hb, :integer
t.remove :outstanding_rent_or_charges
t.column :hbrentshortfall, :integer
t.remove :outstanding_amount
t.column :tshortfall, :integer
t.column :postcode, :string
t.column :postcod2, :string
t.column :ppostc1, :string
t.column :ppostc2, :string
t.remove :property_relet
t.column :property_relet, :integer
end
end
def down
change_table :case_logs, bulk: true do |t|
t.column :condition_effects_prefer_not_to_say, :integer
t.column :reason_for_leaving_last_settled_home, :string
t.remove :reason
t.column :property_reference, :string
t.remove :propcode
t.column :property_major_repairs, :string
t.remove :majorrepairs
t.column :property_location, :string
t.remove :la
t.column :previous_la, :string
t.remove :prevloc
t.column :housing_benefit, :string
t.remove :hb
t.column :outstanding_rent_or_charges, :string
t.remove :hbrentshortfall
t.column :outstanding_amount, :string
t.remove :tshortfall
t.remove :postcode
t.remove :postcod2
t.remove :ppostc1
t.remove :ppostc2
t.remove :property_relet
t.column :property_relet, :string
end
end
end

21
db/migrate/20211110140928_add_mrc_dates.rb

@ -0,0 +1,21 @@
class AddMrcDates < ActiveRecord::Migration[6.1]
def up
change_table :case_logs, bulk: true do |t|
t.remove :property_major_repairs_date
t.column :mrcdate, :datetime
t.column :mrcday, :integer
t.column :mrcmonth, :integer
t.column :mrcyear, :integer
end
end
def down
change_table :case_logs, bulk: true do |t|
t.column :property_major_repairs_date, :string
t.remove :mrcdate
t.remove :mrcday
t.remove :mrcmonth
t.remove :mrcyear
end
end
end

7
db/migrate/20211111143319_add_other_members_column.rb

@ -0,0 +1,7 @@
class AddOtherMembersColumn < ActiveRecord::Migration[6.1]
def change
change_table :case_logs, bulk: true do |t|
t.column :other_hhmemb, :integer
end
end
end

8
db/migrate/20211112105348_add_incref_field.rb

@ -0,0 +1,8 @@
class AddIncrefField < ActiveRecord::Migration[6.1]
def change
change_table :case_logs, bulk: true do |t|
t.column :incref, :integer
end
end
end

216
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_11_02_100820) do ActiveRecord::Schema.define(version: 2021_11_12_105348) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -20,119 +20,110 @@ ActiveRecord::Schema.define(version: 2021_11_02_100820) do
t.datetime "created_at", precision: 6, null: false t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false
t.string "tenant_code" t.string "tenant_code"
t.integer "person_1_age" t.integer "age1"
t.string "person_1_gender" t.string "sex1"
t.string "tenant_ethnic_group" t.integer "ethnic"
t.string "tenant_nationality" t.integer "national"
t.string "previous_housing_situation" t.integer "prevten"
t.string "armed_forces" t.string "armed_forces"
t.string "person_1_economic_status" t.integer "ecstat1"
t.integer "household_number_of_other_members" t.integer "hhmemb"
t.string "person_2_relationship" t.string "relat2"
t.integer "person_2_age" t.integer "age2"
t.string "person_2_gender" t.string "sex2"
t.string "person_2_economic_status" t.integer "ecstat2"
t.string "person_3_relationship" t.string "relat3"
t.integer "person_3_age" t.integer "age3"
t.string "person_3_gender" t.string "sex3"
t.string "person_3_economic_status" t.integer "ecstat3"
t.string "person_4_relationship" t.string "relat4"
t.integer "person_4_age" t.integer "age4"
t.string "person_4_gender" t.string "sex4"
t.string "person_4_economic_status" t.integer "ecstat4"
t.string "person_5_relationship" t.string "relat5"
t.integer "person_5_age" t.integer "age5"
t.string "person_5_gender" t.string "sex5"
t.string "person_5_economic_status" t.integer "ecstat5"
t.string "person_6_relationship" t.string "relat6"
t.integer "person_6_age" t.integer "age6"
t.string "person_6_gender" t.string "sex6"
t.string "person_6_economic_status" t.integer "ecstat6"
t.string "person_7_relationship" t.string "relat7"
t.integer "person_7_age" t.integer "age7"
t.string "person_7_gender" t.string "sex7"
t.string "person_7_economic_status" t.integer "ecstat7"
t.string "person_8_relationship" t.string "relat8"
t.integer "person_8_age" t.integer "age8"
t.string "person_8_gender" t.string "sex8"
t.string "person_8_economic_status" t.integer "ecstat8"
t.string "homelessness" t.integer "homeless"
t.string "reason_for_leaving_last_settled_home" t.integer "underoccupation_benefitcap"
t.string "benefit_cap_spare_room_subsidy" t.integer "leftreg"
t.string "armed_forces_active" t.integer "reservist"
t.string "armed_forces_injured"
t.string "armed_forces_partner" t.string "armed_forces_partner"
t.string "medical_conditions" t.integer "illness"
t.string "pregnancy" t.integer "preg_occ"
t.string "accessibility_requirements" t.string "accessibility_requirements"
t.string "condition_effects" t.string "condition_effects"
t.string "tenancy_code" t.string "tenancy_code"
t.string "tenancy_start_date" t.string "startdate"
t.string "starter_tenancy" t.integer "startertenancy"
t.string "fixed_term_tenancy" t.integer "tenancylength"
t.string "tenancy_type" t.integer "tenancy"
t.string "letting_type" t.string "lettype"
t.string "letting_provider" t.integer "landlord"
t.string "property_location"
t.string "previous_postcode" t.string "previous_postcode"
t.string "property_relet" t.integer "rsnvac"
t.string "property_vacancy_reason" t.integer "unittype_gn"
t.string "property_reference"
t.string "property_unit_type"
t.string "property_building_type" t.string "property_building_type"
t.string "property_number_of_bedrooms" t.integer "beds"
t.string "property_void_date" t.string "property_void_date"
t.string "property_major_repairs" t.integer "offered"
t.string "property_major_repairs_date" t.integer "wchair"
t.integer "property_number_of_times_relet" t.integer "earnings"
t.string "property_wheelchair_accessible" t.integer "incfreq"
t.integer "net_income" t.integer "benefits"
t.string "net_income_frequency" t.integer "period"
t.string "net_income_uc_proportion" t.integer "brent"
t.string "housing_benefit" t.integer "scharge"
t.string "rent_frequency" t.integer "pscharge"
t.string "basic_rent" t.integer "supcharg"
t.string "service_charge" t.integer "tcharge"
t.string "personal_service_charge" t.integer "layear"
t.string "support_charge" t.integer "lawaitlist"
t.string "total_charge"
t.string "outstanding_amount"
t.string "time_lived_in_la"
t.string "time_on_la_waiting_list"
t.string "previous_la"
t.string "property_postcode" t.string "property_postcode"
t.string "reasonable_preference" t.integer "reasonpref"
t.string "reasonable_preference_reason" t.string "reasonable_preference_reason"
t.string "cbl_letting" t.integer "cbl"
t.string "chr_letting" t.integer "chr"
t.string "cap_letting" t.integer "cap"
t.string "outstanding_rent_or_charges"
t.string "other_reason_for_leaving_last_settled_home" t.string "other_reason_for_leaving_last_settled_home"
t.boolean "accessibility_requirements_fully_wheelchair_accessible_housing" t.integer "housingneeds_a"
t.boolean "accessibility_requirements_wheelchair_access_to_essential_rooms" t.integer "housingneeds_b"
t.boolean "accessibility_requirements_level_access_housing" t.integer "housingneeds_c"
t.boolean "accessibility_requirements_other_disability_requirements" t.integer "housingneeds_f"
t.boolean "accessibility_requirements_no_disability_requirements" t.integer "housingneeds_g"
t.boolean "accessibility_requirements_do_not_know" t.integer "housingneeds_h"
t.boolean "accessibility_requirements_prefer_not_to_say" t.integer "accessibility_requirements_prefer_not_to_say"
t.boolean "condition_effects_vision" t.integer "illness_type_1"
t.boolean "condition_effects_hearing" t.integer "illness_type_2"
t.boolean "condition_effects_mobility" t.integer "illness_type_3"
t.boolean "condition_effects_dexterity" t.integer "illness_type_4"
t.boolean "condition_effects_stamina" t.integer "illness_type_8"
t.boolean "condition_effects_learning" t.integer "illness_type_5"
t.boolean "condition_effects_memory" t.integer "illness_type_6"
t.boolean "condition_effects_mental_health" t.integer "illness_type_7"
t.boolean "condition_effects_social_or_behavioral" t.integer "illness_type_9"
t.boolean "condition_effects_other" t.integer "illness_type_10"
t.boolean "condition_effects_prefer_not_to_say" t.integer "rp_homeless"
t.boolean "reasonable_preference_reason_homeless" t.integer "rp_insan_unsat"
t.boolean "reasonable_preference_reason_unsatisfactory_housing" t.integer "rp_medwel"
t.boolean "reasonable_preference_reason_medical_grounds" t.integer "rp_hardship"
t.boolean "reasonable_preference_reason_avoid_hardship" t.integer "rp_dontknow"
t.boolean "reasonable_preference_reason_do_not_know"
t.datetime "discarded_at" t.datetime "discarded_at"
t.string "other_tenancy_type" t.string "tenancyother"
t.integer "override_net_income_validation"
t.string "net_income_known"
t.string "gdpr_acceptance" t.string "gdpr_acceptance"
t.string "gdpr_declined" t.string "gdpr_declined"
t.string "property_owner_organisation" t.string "property_owner_organisation"
@ -144,8 +135,25 @@ ActiveRecord::Schema.define(version: 2021_11_02_100820) do
t.string "needs_type" t.string "needs_type"
t.string "sale_completion_date" t.string "sale_completion_date"
t.string "purchaser_code" t.string "purchaser_code"
t.boolean "override_net_income_validation" t.integer "reason"
t.string "net_income_known" t.string "propcode"
t.integer "majorrepairs"
t.string "la"
t.string "prevloc"
t.integer "hb"
t.integer "hbrentshortfall"
t.integer "tshortfall"
t.string "postcode"
t.string "postcod2"
t.string "ppostc1"
t.string "ppostc2"
t.integer "property_relet"
t.datetime "mrcdate"
t.integer "mrcday"
t.integer "mrcmonth"
t.integer "mrcyear"
t.integer "other_hhmemb"
t.integer "incref"
t.index ["discarded_at"], name: "index_case_logs_on_discarded_at" t.index ["discarded_at"], name: "index_case_logs_on_discarded_at"
end end

11
docs/adr/adr-008-field-names.md

@ -0,0 +1,11 @@
### ADR - 008: Field Names
We are changing the schema to reflect the way the data is stored in CORE.
This is due to the SPSS queries that are being performed by ADD and the complexity that would come with changing them.
The field names are saved lowercase as opposed to the uppercase versions we see in CORE.
This is due to Ruby expecting the uppercase parameters to be constants and database fields are expected to be lower case.
These fields could be mapped to their uppercase versions during the replication if needed.
A lot of the values are now also being stored as enums.
This gives as some validation by default as the values not defined in the enums will fail to save.

673
docs/api/DLUHC-CORE-Data.v1.json

File diff suppressed because it is too large Load Diff

99
spec/controllers/case_logs_controller_spec.rb

@ -49,15 +49,15 @@ RSpec.describe CaseLogsController, type: :controller do
let(:id) { case_log.id } let(:id) { case_log.id }
let(:case_log_form_params) do let(:case_log_form_params) do
{ accessibility_requirements: { accessibility_requirements:
%w[ accessibility_requirements_fully_wheelchair_accessible_housing %w[ housingneeds_a
accessibility_requirements_wheelchair_access_to_essential_rooms housingneeds_b
accessibility_requirements_level_access_housing], housingneeds_c],
page: "accessibility_requirements" } page: "accessibility_requirements" }
end end
let(:new_case_log_form_params) do let(:new_case_log_form_params) do
{ {
accessibility_requirements: %w[accessibility_requirements_level_access_housing], accessibility_requirements: %w[housingneeds_c],
page: "accessibility_requirements", page: "accessibility_requirements",
} }
end end
@ -66,27 +66,27 @@ RSpec.describe CaseLogsController, type: :controller do
post :submit_form, params: { id: id, case_log: case_log_form_params } post :submit_form, params: { id: id, case_log: case_log_form_params }
case_log.reload case_log.reload
expect(case_log.accessibility_requirements_fully_wheelchair_accessible_housing).to eq(true) expect(case_log.housingneeds_a).to eq("Yes")
expect(case_log.accessibility_requirements_wheelchair_access_to_essential_rooms).to eq(true) expect(case_log.housingneeds_b).to eq("Yes")
expect(case_log.accessibility_requirements_level_access_housing).to eq(true) expect(case_log.housingneeds_c).to eq("Yes")
end end
it "sets previously submitted items to false when resubmitted with new values" do it "sets previously submitted items to false when resubmitted with new values" do
post :submit_form, params: { id: id, case_log: new_case_log_form_params } post :submit_form, params: { id: id, case_log: new_case_log_form_params }
case_log.reload case_log.reload
expect(case_log.accessibility_requirements_fully_wheelchair_accessible_housing).to eq(false) expect(case_log.housingneeds_a).to eq("No")
expect(case_log.accessibility_requirements_wheelchair_access_to_essential_rooms).to eq(false) expect(case_log.housingneeds_b).to eq("No")
expect(case_log.accessibility_requirements_level_access_housing).to eq(true) expect(case_log.housingneeds_c).to eq("Yes")
end end
context "given a page with checkbox and non-checkbox questions" do context "given a page with checkbox and non-checkbox questions" do
let(:tenant_code) { "BZ355" } let(:tenant_code) { "BZ355" }
let(:case_log_form_params) do let(:case_log_form_params) do
{ accessibility_requirements: { accessibility_requirements:
%w[ accessibility_requirements_fully_wheelchair_accessible_housing %w[ housingneeds_a
accessibility_requirements_wheelchair_access_to_essential_rooms housingneeds_b
accessibility_requirements_level_access_housing], housingneeds_c],
tenant_code: tenant_code, tenant_code: tenant_code,
page: "accessibility_requirements" } page: "accessibility_requirements" }
end end
@ -95,13 +95,13 @@ RSpec.describe CaseLogsController, type: :controller do
{ {
"type" => "checkbox", "type" => "checkbox",
"answer_options" => "answer_options" =>
{ "accessibility_requirements_fully_wheelchair_accessible_housing" => "Fully wheelchair accessible housing", { "housingneeds_a" => "Fully wheelchair accessible housing",
"accessibility_requirements_wheelchair_access_to_essential_rooms" => "Wheelchair access to essential rooms", "housingneeds_b" => "Wheelchair access to essential rooms",
"accessibility_requirements_level_access_housing" => "Level access housing", "housingneeds_c" => "Level access housing",
"accessibility_requirements_other_disability_requirements" => "Other disability requirements", "housingneeds_f" => "Other disability requirements",
"accessibility_requirements_no_disability_requirements" => "No disability requirements", "housingneeds_g" => "No disability requirements",
"divider_a" => true, "divider_a" => true,
"accessibility_requirements_do_not_know" => "Do not know", "housingneeds_h" => "Do not know",
"divider_b" => true, "divider_b" => true,
"accessibility_requirements_prefer_not_to_say" => "Prefer not to say" }, "accessibility_requirements_prefer_not_to_say" => "Prefer not to say" },
}, },
@ -116,9 +116,9 @@ RSpec.describe CaseLogsController, type: :controller do
post :submit_form, params: { id: id, case_log: case_log_form_params } post :submit_form, params: { id: id, case_log: case_log_form_params }
case_log.reload case_log.reload
expect(case_log.accessibility_requirements_fully_wheelchair_accessible_housing).to eq(true) expect(case_log.housingneeds_a).to eq("Yes")
expect(case_log.accessibility_requirements_wheelchair_access_to_essential_rooms).to eq(true) expect(case_log.housingneeds_b).to eq("Yes")
expect(case_log.accessibility_requirements_level_access_housing).to eq(true) expect(case_log.housingneeds_c).to eq("Yes")
expect(case_log.tenant_code).to eq(tenant_code) expect(case_log.tenant_code).to eq(tenant_code)
end end
end end
@ -130,14 +130,14 @@ RSpec.describe CaseLogsController, type: :controller do
let(:case_log_form_conditional_question_yes_params) do let(:case_log_form_conditional_question_yes_params) do
{ {
pregnancy: "Yes", preg_occ: "Yes",
page: "conditional_question", page: "conditional_question",
} }
end end
let(:case_log_form_conditional_question_no_params) do let(:case_log_form_conditional_question_no_params) do
{ {
pregnancy: "No", preg_occ: "No",
page: "conditional_question", page: "conditional_question",
} }
end end
@ -150,6 +150,55 @@ RSpec.describe CaseLogsController, type: :controller do
expect(response).to redirect_to("/case_logs/#{id}/conditional_question_no_page") expect(response).to redirect_to("/case_logs/#{id}/conditional_question_no_page")
end end
end end
context "partition postcode" do
let(:case_log_with_postcode) do
{
property_postcode: "M1 1AE",
previous_postcode: "M2 2AE",
page: "property_postcode",
}
end
it "saves full and partial postcodes" do
post :submit_form, params: { id: id, case_log: case_log_with_postcode }
case_log.reload
expect(case_log.property_postcode).to eq("M1 1AE")
expect(case_log.postcode).to eq("M1")
expect(case_log.postcod2).to eq("1AE")
end
it "saves full and partial previous postcodes" do
post :submit_form, params: { id: id, case_log: case_log_with_postcode }
case_log.reload
expect(case_log.previous_postcode).to eq("M2 2AE")
expect(case_log.ppostc1).to eq("M2")
expect(case_log.ppostc2).to eq("2AE")
end
end
context "partition date" do
let(:case_log_with_date) do
{
"mrcdate(1i)": "2021",
"mrcdate(2i)": "05",
"mrcdate(3i)": "04",
page: "major_repairs_date",
}
end
it "saves full and partial dates" do
post :submit_form, params: { id: id, case_log: case_log_with_date }
case_log.reload
expect(case_log.mrcdate.day).to eq(4)
expect(case_log.mrcdate.month).to eq(5)
expect(case_log.mrcdate.year).to eq(2021)
expect(case_log.mrcday).to eq(4)
expect(case_log.mrcmonth).to eq(5)
expect(case_log.mrcyear).to eq(2021)
end
end
end end
describe "get_next_page_path" do describe "get_next_page_path" do
@ -170,7 +219,7 @@ RSpec.describe CaseLogsController, type: :controller do
it "returns a correct page path if there is conditional routing" do it "returns a correct page path if there is conditional routing" do
responses_for_page = {} responses_for_page = {}
responses_for_page["pregnancy"] = "No" responses_for_page["preg_occ"] = "No"
expect(case_log_controller.send(:get_next_page_path, form, previous_conditional_page, responses_for_page)).to eq("case_log_conditional_question_no_page_path") expect(case_log_controller.send(:get_next_page_path, form, previous_conditional_page, responses_for_page)).to eq("case_log_conditional_question_no_page_path")
end end
end end

12
spec/factories/case_log.rb

@ -4,15 +4,21 @@ FactoryBot.define do
trait :in_progress do trait :in_progress do
status { 1 } status { 1 }
tenant_code { "TH356" } tenant_code { "TH356" }
property_postcode { "SW2 6HI" } property_postcode { "P0 5ST" }
previous_postcode { "P0 5ST" } previous_postcode { "SW2 6HI" }
person_1_age { "18" } age1 { "17" }
end end
trait :completed do trait :completed do
status { 2 } status { 2 }
tenant_code { "BZ737" } tenant_code { "BZ737" }
property_postcode { "NW1 7TY" } property_postcode { "NW1 7TY" }
end end
trait :soft_validations_triggered do
status { 1 }
ecstat1 { "Full-time - 30 hours or more" }
earnings { 750 }
incfreq { "Weekly" }
end
created_at { Time.zone.now } created_at { Time.zone.now }
updated_at { Time.zone.now } updated_at { Time.zone.now }
end end

176
spec/features/case_log_spec.rb

@ -6,26 +6,26 @@ RSpec.describe "Test Features" do
let(:status) { case_log.status } let(:status) { case_log.status }
question_answers = { question_answers = {
tenant_code: { type: "text", answer: "BZ737" }, tenant_code: { type: "text", answer: "BZ737", path: "tenant_code" },
person_1_age: { type: "numeric", answer: 25 }, age1: { type: "numeric", answer: 25, path: "person_1_age" },
person_1_gender: { type: "radio", answer: "Female" }, sex1: { type: "radio", answer: "Female", path: "person_1_gender" },
household_number_of_other_members: { type: "numeric", answer: 2 }, other_hhmemb: { type: "numeric", answer: 2, path: "household_number_of_other_members" },
} }
def fill_in_number_question(case_log_id, question, value) def fill_in_number_question(case_log_id, question, value, path)
visit("/case_logs/#{case_log_id}/#{question}") visit("/case_logs/#{case_log_id}/#{path}")
fill_in("case-log-#{question.to_s.dasherize}-field", with: value) fill_in("case-log-#{question.to_s.dasherize}-field", with: value)
click_button("Save and continue") click_button("Save and continue")
end end
def answer_all_questions_in_income_subsection def answer_all_questions_in_income_subsection
visit("/case_logs/#{empty_case_log.id}/net_income") visit("/case_logs/#{empty_case_log.id}/net_income")
fill_in("case-log-net-income-field", with: 18_000) fill_in("case-log-earnings-field", with: 18_000)
choose("case-log-net-income-frequency-yearly-field") choose("case-log-incfreq-yearly-field")
click_button("Save and continue") click_button("Save and continue")
choose("case-log-net-income-uc-proportion-all-field") choose("case-log-benefits-all-field")
click_button("Save and continue") click_button("Save and continue")
choose("case-log-housing-benefit-housing-benefit-but-not-universal-credit-field") choose("case-log-hb-housing-benefit-but-not-universal-credit-field")
click_button("Save and continue") click_button("Save and continue")
end end
@ -84,65 +84,66 @@ RSpec.describe "Test Features" do
let(:case_log_with_checkbox_questions_answered) do let(:case_log_with_checkbox_questions_answered) do
FactoryBot.create( FactoryBot.create(
:case_log, :in_progress, :case_log, :in_progress,
accessibility_requirements_fully_wheelchair_accessible_housing: true, housingneeds_a: "Yes",
accessibility_requirements_level_access_housing: true housingneeds_c: "Yes"
) )
end end
context "Validate pregnancy questions" do context "Validate pregnancy questions" do
it "Cannot answer yes if no female tenants" do it "Cannot answer yes if no female tenants" do
expect { expect {
CaseLog.create!(pregnancy: "Yes", CaseLog.create!(preg_occ: "Yes",
person_1_gender: "Male", sex1: "Male",
person_1_age: 20) age1: 20)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Cannot answer yes if no female tenants within age range" do it "Cannot answer yes if no female tenants within age range" do
expect { expect {
CaseLog.create!(pregnancy: "Yes", CaseLog.create!(preg_occ: "Yes",
person_1_gender: "Female", sex1: "Female",
person_1_age: 51) age1: 51)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Cannot answer prefer not to say if no valid tenants" do it "Cannot answer prefer not to say if no valid tenants" do
expect { expect {
CaseLog.create!(pregnancy: "Prefer not to say", CaseLog.create!(preg_occ: "Prefer not to say",
person_1_gender: "Male", sex1: "Male",
person_1_age: 20) age1: 20)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Can answer yes if valid tenants" do it "Can answer yes if valid tenants" do
expect { expect {
CaseLog.create!(pregnancy: "Yes", CaseLog.create!(preg_occ: "Yes",
person_1_gender: "Female", sex1: "Female",
person_1_age: 20) age1: 20)
}.not_to raise_error }.not_to raise_error
end end
it "Can answer yes if valid second tenant" do it "Can answer yes if valid second tenant" do
expect { expect {
CaseLog.create!(pregnancy: "Yes", CaseLog.create!(preg_occ: "Yes",
person_1_gender: "Male", person_1_age: 99, sex1: "Male", age1: 99,
person_2_gender: "Female", sex2: "Female",
person_2_age: 20) age2: 20)
}.not_to raise_error }.not_to raise_error
end end
end end
it "can be accessed by url" do it "can be accessed by url" do
visit("/case_logs/#{id}/person_1_age") visit("/case_logs/#{id}/person_1_age")
expect(page).to have_field("case-log-person-1-age-field") expect(page).to have_field("case-log-age1-field")
end end
it "updates model attributes correctly for each question" do it "updates model attributes correctly for each question" do
question_answers.each do |question, hsh| question_answers.each do |question, hsh|
type = hsh[:type] type = hsh[:type]
answer = hsh[:answer] answer = hsh[:answer]
path = hsh[:path]
original_value = case_log.send(question) original_value = case_log.send(question)
visit("/case_logs/#{id}/#{question}") visit("/case_logs/#{id}/#{path}")
case type case type
when "text" when "text"
fill_in("case-log-#{question.to_s.dasherize}-field", with: answer) fill_in("case-log-#{question.to_s.dasherize}-field", with: answer)
@ -160,42 +161,42 @@ RSpec.describe "Test Features" do
it "updates total value of the rent", js: true do it "updates total value of the rent", js: true do
visit("/case_logs/#{id}/rent") visit("/case_logs/#{id}/rent")
fill_in("case-log-basic-rent-field", with: 3) fill_in("case-log-brent-field", with: 3)
expect(page).to have_field("case-log-total-charge-field", with: "3") expect(page).to have_field("case-log-tcharge-field", with: "3")
fill_in("case-log-service-charge-field", with: 2) fill_in("case-log-scharge-field", with: 2)
expect(page).to have_field("case-log-total-charge-field", with: "5") expect(page).to have_field("case-log-tcharge-field", with: "5")
fill_in("case-log-personal-service-charge-field", with: 1) fill_in("case-log-pscharge-field", with: 1)
expect(page).to have_field("case-log-total-charge-field", with: "6") expect(page).to have_field("case-log-tcharge-field", with: "6")
fill_in("case-log-support-charge-field", with: 4) fill_in("case-log-supcharg-field", with: 4)
expect(page).to have_field("case-log-total-charge-field", with: "10") expect(page).to have_field("case-log-tcharge-field", with: "10")
end end
it "displays number answers in inputs if they are already saved" do it "displays number answers in inputs if they are already saved" do
visit("/case_logs/#{id}/previous_postcode") visit("/case_logs/#{id}/property_postcode")
expect(page).to have_field("case-log-previous-postcode-field", with: "P0 5ST") expect(page).to have_field("case-log-property-postcode-field", with: "P0 5ST")
end end
it "displays text answers in inputs if they are already saved" do it "displays text answers in inputs if they are already saved" do
visit("/case_logs/#{id}/person_1_age") visit("/case_logs/#{id}/person_1_age")
expect(page).to have_field("case-log-person-1-age-field", with: "18") expect(page).to have_field("case-log-age1-field", with: "17")
end end
it "displays checkbox answers in inputs if they are already saved" do it "displays checkbox answers in inputs if they are already saved" do
visit("/case_logs/#{case_log_with_checkbox_questions_answered.id}/accessibility_requirements") visit("/case_logs/#{case_log_with_checkbox_questions_answered.id}/accessibility_requirements")
# Something about our styling makes the selenium webdriver think the actual radio buttons are not visible so we pass false here # Something about our styling makes the selenium webdriver think the actual radio buttons are not visible so we pass false here
expect(page).to have_checked_field( expect(page).to have_checked_field(
"case-log-accessibility-requirements-accessibility-requirements-fully-wheelchair-accessible-housing-field", "case-log-accessibility-requirements-housingneeds-a-field",
visible: false, visible: false,
) )
expect(page).to have_unchecked_field( expect(page).to have_unchecked_field(
"case-log-accessibility-requirements-accessibility-requirements-wheelchair-access-to-essential-rooms-field", "case-log-accessibility-requirements-housingneeds-b-field",
visible: false, visible: false,
) )
expect(page).to have_checked_field( expect(page).to have_checked_field(
"case-log-accessibility-requirements-accessibility-requirements-level-access-housing-field", "case-log-accessibility-requirements-housingneeds-c-field",
visible: false, visible: false,
) )
end end
@ -216,13 +217,24 @@ RSpec.describe "Test Features" do
click_link(text: "Back") click_link(text: "Back")
expect(page).to have_field("case-log-tenant-code-field") expect(page).to have_field("case-log-tenant-code-field")
end end
it "doesn't get stuck in infinite loops", js: true do
visit("/case_logs")
visit("/case_logs/#{id}/net_income")
fill_in("case-log-earnings-field", with: 740)
choose("case-log-incfreq-weekly-field", allow_label_click: true)
click_button("Save and continue")
click_link(text: "Back")
click_link(text: "Back")
expect(page).to have_current_path("/case_logs")
end
end end
end end
describe "Form flow is correct" do describe "Form flow is correct" do
context "given an ordered list of pages" do context "given an ordered list of pages" do
it "leads to the next one in the correct order" do it "leads to the next one in the correct order" do
pages = question_answers.keys pages = question_answers.map { |_key, val| val[:path] }
pages[0..-2].each_with_index do |val, index| pages[0..-2].each_with_index do |val, index|
visit("/case_logs/#{id}/#{val}") visit("/case_logs/#{id}/#{val}")
click_button("Save and continue") click_button("Save and continue")
@ -230,7 +242,7 @@ RSpec.describe "Test Features" do
end end
end end
context "when changing an answer from the check answers page" do context "when changing an answer from the check answers page", js: true do
it "the back button routes correctly" do it "the back button routes correctly" do
visit("/case_logs/#{id}/household_characteristics/check_answers") visit("/case_logs/#{id}/household_characteristics/check_answers")
first("a", text: /Answer/).click first("a", text: /Answer/).click
@ -253,7 +265,7 @@ RSpec.describe "Test Features" do
let(:last_question_for_subsection) { "household_number_of_other_members" } let(:last_question_for_subsection) { "household_number_of_other_members" }
it "redirects to the check answers page when answering the last question and clicking save and continue" do it "redirects to the check answers page when answering the last question and clicking save and continue" do
fill_in_number_question(id, last_question_for_subsection, 0) fill_in_number_question(id, "other_hhmemb", 0, last_question_for_subsection)
expect(page).to have_current_path("/case_logs/#{id}/#{subsection}/check_answers") expect(page).to have_current_path("/case_logs/#{id}/#{subsection}/check_answers")
end end
@ -266,8 +278,8 @@ RSpec.describe "Test Features" do
end end
it "should display answers given by the user for the question in the subsection" do it "should display answers given by the user for the question in the subsection" do
fill_in_number_question(empty_case_log.id, "person_1_age", 28) fill_in_number_question(empty_case_log.id, "age1", 28, "person_1_age")
choose("case-log-person-1-gender-non-binary-field") choose("case-log-sex1-non-binary-field")
click_button("Save and continue") click_button("Save and continue")
visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers")
expect(page).to have_content("28") expect(page).to have_content("28")
@ -282,7 +294,7 @@ RSpec.describe "Test Features" do
end end
it "should have a change link for answered questions" do it "should have a change link for answered questions" do
fill_in_number_question(empty_case_log.id, "person_1_age", 28) fill_in_number_question(empty_case_log.id, "age1", 28, "person_1_age")
visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers") visit("/case_logs/#{empty_case_log.id}/#{subsection}/check_answers")
assert_selector "a", text: /Answer\z/, count: 3 assert_selector "a", text: /Answer\z/, count: 3
assert_selector "a", text: "Change", count: 1 assert_selector "a", text: "Change", count: 1
@ -296,7 +308,7 @@ RSpec.describe "Test Features" do
end end
it "should have a link pointing to the next empty question if some questions are answered" do it "should have a link pointing to the next empty question if some questions are answered" do
fill_in_number_question(empty_case_log.id, "net_income", 18_000) fill_in_number_question(empty_case_log.id, "earnings", 18_000, "net_income")
visit("/case_logs/#{empty_case_log.id}/income_and_benefits/check_answers") visit("/case_logs/#{empty_case_log.id}/income_and_benefits/check_answers")
expect(page).to have_content("You answered 1 of 4 questions") expect(page).to have_content("You answered 1 of 4 questions")
@ -324,7 +336,7 @@ RSpec.describe "Test Features" do
it "displays conditional question that were visited" do it "displays conditional question that were visited" do
visit("/case_logs/#{id}/conditional_question") visit("/case_logs/#{id}/conditional_question")
choose("case-log-pregnancy-no-field") choose("case-log-preg-occ-no-field")
click_button("Save and continue") click_button("Save and continue")
visit("/case_logs/#{id}/#{conditional_subsection}/check_answers") visit("/case_logs/#{id}/#{conditional_subsection}/check_answers")
question_labels = ["Has the condition been met?", "Has the condition not been met?"] question_labels = ["Has the condition been met?", "Has the condition not been met?"]
@ -351,13 +363,13 @@ RSpec.describe "Test Features" do
visit("/case_logs/#{id}/armed_forces") visit("/case_logs/#{id}/armed_forces")
# Something about our styling makes the selenium webdriver think the actual radio buttons are not visible so we allow label click here # Something about our styling makes the selenium webdriver think the actual radio buttons are not visible so we allow label click here
choose("case-log-armed-forces-yes-a-regular-field", allow_label_click: true) choose("case-log-armed-forces-yes-a-regular-field", allow_label_click: true)
expect(page).to have_selector("#armed_forces_injured_div") expect(page).to have_selector("#reservist_div")
choose("case-log-armed-forces-injured-no-field", allow_label_click: true) choose("case-log-reservist-no-field", allow_label_click: true)
expect(page).to have_checked_field("case-log-armed-forces-injured-no-field", visible: false) expect(page).to have_checked_field("case-log-reservist-no-field", visible: false)
choose("case-log-armed-forces-no-field", allow_label_click: true) choose("case-log-armed-forces-no-field", allow_label_click: true)
expect(page).not_to have_selector("#armed_forces_injured_div") expect(page).not_to have_selector("#reservist_div")
choose("case-log-armed-forces-yes-a-regular-field", allow_label_click: true) choose("case-log-armed-forces-yes-a-regular-field", allow_label_click: true)
expect(page).to have_unchecked_field("case-log-armed-forces-injured-no-field", visible: false) expect(page).to have_unchecked_field("case-log-reservist-no-field", visible: false)
end end
end end
end end
@ -366,32 +378,32 @@ RSpec.describe "Test Features" do
context "given an invalid tenant age" do context "given an invalid tenant age" do
it " of less than 0 it shows validation" do it " of less than 0 it shows validation" do
visit("/case_logs/#{id}/person_1_age") visit("/case_logs/#{id}/person_1_age")
fill_in_number_question(empty_case_log.id, "person_1_age", -5) fill_in_number_question(empty_case_log.id, "age1", -5, "person_1_age")
expect(page).to have_selector("#error-summary-title") expect(page).to have_selector("#error-summary-title")
expect(page).to have_selector("#case-log-person-1-age-error") expect(page).to have_selector("#case-log-age1-error")
expect(page).to have_selector("#case-log-person-1-age-field-error") expect(page).to have_selector("#case-log-age1-field-error")
end end
it " of greater than 120 it shows validation" do it " of greater than 120 it shows validation" do
visit("/case_logs/#{id}/person_1_age") visit("/case_logs/#{id}/person_1_age")
fill_in_number_question(empty_case_log.id, "person_1_age", 121) fill_in_number_question(empty_case_log.id, "age1", 121, "person_1_age")
expect(page).to have_selector("#error-summary-title") expect(page).to have_selector("#error-summary-title")
expect(page).to have_selector("#case-log-person-1-age-error") expect(page).to have_selector("#case-log-age1-error")
expect(page).to have_selector("#case-log-person-1-age-field-error") expect(page).to have_selector("#case-log-age1-field-error")
end end
end end
end end
describe "Soft Validation" do describe "Soft Validation" do
context "given a weekly net income that is above the expected amount for the given economic status but below the hard max" do context "given a weekly net income that is above the expected amount for the given economic status but below the hard max" do
let!(:case_log) { FactoryBot.create(:case_log, :in_progress, person_1_economic_status: "Full-time - 30 hours or more") } let(:case_log) { FactoryBot.create(:case_log, :in_progress, ecstat1: "Full-time - 30 hours or more") }
let(:income_over_soft_limit) { 750 } let(:income_over_soft_limit) { 750 }
let(:income_under_soft_limit) { 700 } let(:income_under_soft_limit) { 700 }
it "prompts the user to confirm the value is correct" do it "prompts the user to confirm the value is correct", js: true do
visit("/case_logs/#{case_log.id}/net_income") visit("/case_logs/#{case_log.id}/net_income")
fill_in("case-log-net-income-field", with: income_over_soft_limit) fill_in("case-log-earnings-field", with: income_over_soft_limit)
choose("case-log-net-income-frequency-weekly-field", allow_label_click: true) choose("case-log-incfreq-weekly-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_content("Are you sure this is correct?") expect(page).to have_content("Are you sure this is correct?")
check("case-log-override-net-income-validation-override-net-income-validation-field", allow_label_click: true) check("case-log-override-net-income-validation-override-net-income-validation-field", allow_label_click: true)
@ -401,10 +413,10 @@ RSpec.describe "Test Features" do
it "does not require confirming the value if the value is amended" do it "does not require confirming the value if the value is amended" do
visit("/case_logs/#{case_log.id}/net_income") visit("/case_logs/#{case_log.id}/net_income")
fill_in("case-log-net-income-field", with: income_over_soft_limit) fill_in("case-log-earnings-field", with: income_over_soft_limit)
choose("case-log-net-income-frequency-weekly-field", allow_label_click: true) choose("case-log-incfreq-weekly-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
fill_in("case-log-net-income-field", with: income_under_soft_limit) fill_in("case-log-earnings-field", with: income_under_soft_limit)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/case_logs/#{case_log.id}/net_income_uc_proportion") expect(page).to have_current_path("/case_logs/#{case_log.id}/net_income_uc_proportion")
case_log.reload case_log.reload
@ -413,19 +425,19 @@ RSpec.describe "Test Features" do
it "clears the confirmation question if the amount was amended and the page is returned to using the back button", js: true do it "clears the confirmation question if the amount was amended and the page is returned to using the back button", js: true do
visit("/case_logs/#{case_log.id}/net_income") visit("/case_logs/#{case_log.id}/net_income")
fill_in("case-log-net-income-field", with: income_over_soft_limit) fill_in("case-log-earnings-field", with: income_over_soft_limit)
choose("case-log-net-income-frequency-weekly-field", allow_label_click: true) choose("case-log-incfreq-weekly-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
fill_in("case-log-net-income-field", with: income_under_soft_limit) fill_in("case-log-earnings-field", with: income_under_soft_limit)
click_button("Save and continue") click_button("Save and continue")
click_link(text: "Back") click_link(text: "Back")
expect(page).not_to have_content("Are you sure this is correct?") expect(page).to have_no_content("Are you sure this is correct?")
end end
it "does not clear the confirmation question if the page is returned to using the back button and the amount is still over the soft limit", js: true do it "does not clear the confirmation question if the page is returned to using the back button and the amount is still over the soft limit", js: true do
visit("/case_logs/#{case_log.id}/net_income") visit("/case_logs/#{case_log.id}/net_income")
fill_in("case-log-net-income-field", with: income_over_soft_limit) fill_in("case-log-earnings-field", with: income_over_soft_limit)
choose("case-log-net-income-frequency-weekly-field", allow_label_click: true) choose("case-log-incfreq-weekly-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
check("case-log-override-net-income-validation-override-net-income-validation-field", allow_label_click: true) check("case-log-override-net-income-validation-override-net-income-validation-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
@ -442,19 +454,21 @@ RSpec.describe "Test Features" do
it "can route the user to a different page based on their answer on the current page" do it "can route the user to a different page based on their answer on the current page" do
visit("case_logs/#{id}/conditional_question") visit("case_logs/#{id}/conditional_question")
choose("case-log-pregnancy-yes-field", allow_label_click: true) # using a question name that is already in the db to avoid
# having to add a new column to the db for this test
choose("case-log-preg-occ-yes-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/case_logs/#{id}/conditional_question_yes_page") expect(page).to have_current_path("/case_logs/#{id}/conditional_question_yes_page")
click_link(text: "Back") click_link(text: "Back")
expect(page).to have_current_path("/case_logs/#{id}/conditional_question") expect(page).to have_current_path("/case_logs/#{id}/conditional_question")
choose("case-log-pregnancy-no-field", allow_label_click: true) choose("case-log-preg-occ-no-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/case_logs/#{id}/conditional_question_no_page") expect(page).to have_current_path("/case_logs/#{id}/conditional_question_no_page")
end end
it "can route based on page inclusion rules" do it "can route based on page inclusion rules" do
visit("/case_logs/#{id}/conditional_question_yes_page") visit("/case_logs/#{id}/conditional_question_yes_page")
choose("case-log-cbl-letting-yes-field", allow_label_click: true) choose("case-log-cbl-yes-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/case_logs/#{id}/conditional_question/check_answers") expect(page).to have_current_path("/case_logs/#{id}/conditional_question/check_answers")
end end
@ -467,10 +481,10 @@ RSpec.describe "Test Features" do
it "can route based on multiple conditions" do it "can route based on multiple conditions" do
visit("/case_logs/#{id}/person_1_gender") visit("/case_logs/#{id}/person_1_gender")
choose("case-log-person-1-gender-female-field", allow_label_click: true) choose("case-log-sex1-female-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
visit("/case_logs/#{id}/conditional_question") visit("/case_logs/#{id}/conditional_question")
choose("case-log-pregnancy-yes-field", allow_label_click: true) choose("case-log-preg-occ-yes-field", allow_label_click: true)
click_button("Save and continue") click_button("Save and continue")
expect(page).to have_current_path("/case_logs/#{id}/rent") expect(page).to have_current_path("/case_logs/#{id}/rent")
end end

225
spec/fixtures/complete_case_log.json vendored

@ -1,118 +1,141 @@
{ {
"case_log": "case_log": {
{
"tenant_code": "T657", "tenant_code": "T657",
"person_1_age": 35, "age1": 35,
"person_1_gender": "Female", "sex1": "Female",
"tenant_ethnic_group": "White: English/Scottish/Welsh/Northern Irish/British", "ethnic": "White: English/Scottish/Welsh/Northern Irish/British",
"tenant_nationality": "UK national resident in UK", "national": "UK national resident in UK",
"previous_housing_situation": "Private sector tenancy", "prevten": "Private sector tenancy",
"armed_forces": "Yes - a regular", "armed_forces": "Yes - a regular",
"person_1_economic_status": "Full-time - 30 hours or more", "ecstat1": "Full-time - 30 hours or more",
"household_number_of_other_members": 7, "other_hhmemb": 7,
"person_2_relationship": "Partner", "hhmemb": 8,
"person_2_age": 32, "relat2": "Partner",
"person_2_gender": "Male", "age2": 32,
"person_2_economic_status": "Not seeking work", "sex2": "Male",
"person_3_relationship": "Child - includes young adult and grown-up", "ecstat2": "Not seeking work",
"person_3_age": 12, "relat3": "Child - includes young adult and grown-up",
"person_3_gender": "Male", "age3": 12,
"person_3_economic_status": "Child under 16", "sex3": "Male",
"person_4_relationship": "Child - includes young adult and grown-up", "ecstat3": "Child under 16",
"person_4_age": 12, "relat4": "Child - includes young adult and grown-up",
"person_4_gender": "Female", "age4": 12,
"person_4_economic_status": "Child under 16", "sex4": "Female",
"person_5_relationship": "Child - includes young adult and grown-up", "ecstat4": "Child under 16",
"person_5_age": 10, "relat5": "Child - includes young adult and grown-up",
"person_5_gender": "Non-binary", "age5": 10,
"person_5_economic_status": "Child under 16", "sex5": "Non-binary",
"person_6_relationship": "Child - includes young adult and grown-up", "ecstat5": "Child under 16",
"person_6_age": 5, "relat6": "Child - includes young adult and grown-up",
"person_6_gender": "Prefer not to say", "age6": 5,
"person_6_economic_status": "Child under 16", "sex6": "Prefer not to say",
"person_7_relationship": "Child - includes young adult and grown-up", "ecstat6": "Child under 16",
"person_7_age": 5, "relat7": "Child - includes young adult and grown-up",
"person_7_gender": "Prefer not to say", "age7": 5,
"person_7_economic_status": "Child under 16", "sex7": "Prefer not to say",
"person_8_relationship": "Child - includes young adult and grown-up", "ecstat7": "Child under 16",
"person_8_age": 2, "relat8": "Child - includes young adult and grown-up",
"person_8_gender": "Prefer not to say", "age8": 2,
"person_8_economic_status": "Child under 16", "sex8": "Prefer not to say",
"homelessness": "Yes - other homelessness", "ecstat8": "Child under 16",
"reason_for_leaving_last_settled_home": "Other problems with neighbours", "homeless": "Yes - other homelessness",
"benefit_cap_spare_room_subsidy": "No", "reason": 1,
"armed_forces_active": "No", "underoccupation_benefitcap": "No",
"armed_forces_injured": "No", "leftreg": "No - they left up to 5 years ago",
"reservist": "No",
"armed_forces_partner": "No", "armed_forces_partner": "No",
"medical_conditions": "Yes", "illness": "Yes",
"pregnancy": "No", "preg_occ": "No",
"accessibility_requirements": "No", "accessibility_requirements": "No",
"condition_effects": "dummy", "condition_effects": "dummy",
"tenancy_code": "BZ757", "tenancy_code": "BZ757",
"tenancy_start_date": "12/03/2019", "startdate": "12/03/2019",
"starter_tenancy": "No", "startertenancy": "No",
"fixed_term_tenancy": "5", "tenancylength": "5",
"tenancy_type": "Fixed term – Secure", "tenancy": "Fixed term – Secure",
"letting_type": "Affordable Rent - General Needs", "lettype": "Affordable Rent - General Needs",
"letting_provider": "This landlord", "landlord": "This landlord",
"property_location": "Barnet", "la": "Barnet",
"previous_postcode": "NW1 5TY", "property_postcode": "NW1 5TY",
"property_relet": "No", "property_relet": "No",
"property_vacancy_reason": "Relet - tenant abandoned property", "rsnvac": "Relet - tenant abandoned property",
"property_reference": "P9876", "property_reference": "P9876",
"property_unit_type": "House", "unittype_gn": "House",
"property_building_type": "dummy", "property_building_type": "dummy",
"property_number_of_bedrooms": 3, "beds": 3,
"property_void_date": "03/11/2019", "property_void_date": "03/11/2019",
"property_major_repairs": "Yes", "majorrepairs": "Yes",
"property_major_repairs_date": "05/05/2020", "mrcdate": "05/05/2020",
"property_number_of_times_relet": 2, "mrcday": 5,
"property_wheelchair_accessible": true, "mrcmonth": 5,
"mrcyear": 2020,
"offered": 2,
"wchair": "Yes",
"net_income_known": "Yes", "net_income_known": "Yes",
"net_income": 0, "earnings": 0,
"net_income_frequency": null, "incfreq": null,
"net_income_uc_proportion": "Some", "benefits": "Some",
"housing_benefit": "Universal Credit with housing element, but not Housing Benefit", "hb": "Universal Credit with housing element, but not Housing Benefit",
"rent_frequency": "Weekly", "period": "Fortnightly",
"basic_rent": 200, "brent": 200,
"service_charge": 50, "scharge": 50,
"personal_service_charge": 40, "pscharge": 40,
"support_charge": 35, "supcharg": 35,
"total_charge": 325, "tcharge": 325,
"outstanding_amount": "Yes", "outstanding_amount": "Yes",
"time_lived_in_la": "1 to 2 years", "layear": "1 to 2 years",
"time_on_la_waiting_list": "Less than 1 year", "lawaitlist": "Less than 1 year",
"previous_la": "Ashford", "prevloc": "Ashford",
"property_postcode": "SE2 6RT", "previous_postcode": "SE2 6RT",
"reasonable_preference": "Yes", "reasonpref": "Yes",
"reasonable_preference_reason": "dummy", "reasonable_preference_reason": "dummy",
"cbl_letting": true, "cbl": "Yes",
"chr_letting": false, "chr": "Yes",
"cap_letting": false, "cap": "No",
"outstanding_rent_or_charges": 25, "hbrentshortfall": "Yes",
"tshortfall": 12,
"other_reason_for_leaving_last_settled_home": null, "other_reason_for_leaving_last_settled_home": null,
"accessibility_requirements_fully_wheelchair_accessible_housing": true, "housingneeds_a": "Yes",
"accessibility_requirements_wheelchair_access_to_essential_rooms": false, "housingneeds_b": "No",
"accessibility_requirements_level_access_housing": false, "housingneeds_c": "No",
"accessibility_requirements_other_disability_requirements": false, "housingneeds_f": "No",
"accessibility_requirements_no_disability_requirements": false, "housingneeds_g": "No",
"accessibility_requirements_do_not_know": false, "housingneeds_h": "No",
"accessibility_requirements_prefer_not_to_say": false, "accessibility_requirements_prefer_not_to_say": "No",
"condition_effects_vision": false, "illness_type_1": "No",
"condition_effects_hearing": true, "illness_type_2": "Yes",
"condition_effects_mobility": false, "illness_type_3": "No",
"condition_effects_dexterity": false, "illness_type_4": "No",
"condition_effects_stamina": false, "illness_type_8": "No",
"condition_effects_learning": false, "illness_type_5": "No",
"condition_effects_memory": false, "illness_type_6": "No",
"condition_effects_mental_health": false, "illness_type_7": "No",
"condition_effects_social_or_behavioral": false, "illness_type_9": "No",
"condition_effects_other": false, "illness_type_10": "No",
"condition_effects_prefer_not_to_say": true, "condition_effects_prefer_not_to_say": "Yes",
"reasonable_preference_reason_homeless": false, "rp_homeless": "Yes",
"reasonable_preference_reason_unsatisfactory_housing": false, "rp_insan_unsat": "No",
"reasonable_preference_reason_medical_grounds": false, "rp_medwel": "No",
"reasonable_preference_reason_avoid_hardship": false, "rp_hardship": "No",
"reasonable_preference_reason_do_not_know": true "rp_dontknow": "No",
"discarded_at": "05/05/2020",
"override_net_income_validation": "",
"gdpr_acceptance": "",
"gdpr_declined": "",
"property_owner_organisation": "",
"property_manager_organisation": "",
"sale_or_letting": "",
"tenant_same_property_renewal": "",
"rent_type": "",
"intermediate_rent_product_name": "",
"needs_type": "",
"sale_completion_date": "",
"purchaser_code": "",
"propcode": "123",
"majorrepairs": "Yes",
"postcode": "a1",
"postcod2": "w3",
"ppostc1": "w3",
"ppostc2": "w3"
} }
} }

180
spec/fixtures/forms/test_aboutthislog.json vendored

@ -0,0 +1,180 @@
{
"form_type": "lettings",
"sections": {
"about_this_log": {
"label": "About this log",
"subsections": {
"about_this_log": {
"label": "About this log",
"pages": {
"gdpr_acceptance": {
"header": "DLUHC Privacy Notice Acceptance",
"description": "",
"questions": {
"gdpr_acceptance": {
"check_answer_label": "GDPR acceptance",
"header": "Has the tenant or buyer seen the DLUHC privacy notice?",
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "Yes",
"1": "No"
}
}
},
"conditional_route_to": {
"organisation_details": { "gdpr_acceptance": "Yes" }
},
"default_next_page": "gdpr_declined"
},
"gdpr_declined": {
"header": "You cannot use this service",
"hint_text": "",
"description": "We cannot accept data about a tenant or buyer unless they’ve seen the DLUHC privacy notice.",
"questions": {
},
"default_next_page" : "check_answers"
},
"organisation_details": {
"header": "About this log",
"description": "Organisation Details",
"questions": {
"property_owner_organisation": {
"check_answer_label": "",
"header": "Which organisation owns this property?",
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "A",
"1": "B"
}
},
"property_manager_organisation": {
"check_answer_label": "",
"header": "Which organisation manages this property?",
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "A",
"1": "B"
}
}
}
},
"sale_or_letting": {
"header": "About this log",
"description": "Is this a sale or a letting?",
"questions": {
"sale_or_letting": {
"check_answer_label": "",
"header": "Is this a sale or a letting?",
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "Sale",
"1": "Letting"
}
}
},
"conditional_route_to": {
"tenant_same_property_renewal": { "sale_or_letting": "Letting" }
},
"default_next_page" : "check_answers"
},
"tenant_same_property_renewal": {
"header": "About this log",
"description": "Is this a renewal to the same tenant in the same property?",
"questions": {
"tenant_same_property_renewal": {
"check_answer_label": "",
"header": "Is this a renewal to the same tenant in the same property?",
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "Yes",
"1": "No"
}
}
}
},
"tenancy_start_date": {
"header": "About this log",
"description": "",
"questions": {
"tenancy_start_date": {
"check_answer_label": "When is the tenancy start date?",
"header": "What is the tenancy start date?",
"hint_text": "For example, 27 3 2007",
"type": "date"
}
}
},
"letting_type": {
"header": "About this log",
"description": "",
"questions": {
"rent_type": {
"check_answer_label": "What is the rent type?",
"header": "What is the rent type?",
"hint_text": "",
"type": "select",
"answer_options": {
"0": "Social Rent",
"1": "Affordable Rent",
"2": "London Affordable Rent",
"3": "Rent To Buy",
"4": "London Living Rent",
"5": "Other Intermediate Rent Product"
},
"conditional_for": {
"intermediate_rent_product_name": ["Other Intermediate Rent Product"]
}
},
"intermediate_rent_product_name": {
"check_answer_label": "Enter the product name",
"header": "What is intermediate rent product name?",
"type": "text"
},
"needs_type": {
"check_answer_label": "What is the needs type?",
"header": "What is the needs type?",
"hint_text": "",
"type": "select",
"answer_options": {
"0": "Supported Housing",
"1": "General Needs"
}
}
}
},
"sale_completion_date": {
"header": "About this log",
"description": "",
"questions": {
"sale_completion_date": {
"check_answer_label": "What is the sale completion date?",
"header": "What is the sale completion date?",
"hint_text": "For example, 27 3 2007",
"type": "date"
}
}
},
"purchaser_code": {
"header": "About this log",
"description": "",
"questions": {
"purchaser_code": {
"check_answer_label": "What is the purchaser code?",
"header": "What is the purchaser code?",
"hint_text": "",
"type": "text"
}
}
}
}
}
}
}
}
}

38
spec/helpers/check_answers_helper_spec.rb

@ -6,14 +6,14 @@ RSpec.describe CheckAnswersHelper do
FactoryBot.create( FactoryBot.create(
:case_log, :case_log,
:in_progress, :in_progress,
household_number_of_other_members: 1, other_hhmemb: 1,
person_2_relationship: "Partner", relat2: "Partner",
) )
end end
let(:case_log_with_met_radio_condition) do let(:case_log_with_met_radio_condition) do
FactoryBot.create(:case_log, armed_forces: "Yes - a regular", FactoryBot.create(:case_log, armed_forces: "Yes - a regular",
armed_forces_injured: "No", reservist: "No",
armed_forces_active: "Yes") leftreg: "Yes")
end end
let(:subsection) { "income_and_benefits" } let(:subsection) { "income_and_benefits" }
let(:subsection_with_numeric_conditionals) { "household_characteristics" } let(:subsection_with_numeric_conditionals) { "household_characteristics" }
@ -29,7 +29,7 @@ RSpec.describe CheckAnswersHelper do
end end
it "returns 1 if 1 question gets answered" do it "returns 1 if 1 question gets answered" do
case_log["net_income"] = "123" case_log["earnings"] = "123"
expect(total_answered_questions(subsection, case_log, form)).to equal(1) expect(total_answered_questions(subsection, case_log, form)).to equal(1)
end end
@ -52,8 +52,8 @@ RSpec.describe CheckAnswersHelper do
end end
it "includes conditional questions with met radio conditions" do it "includes conditional questions with met radio conditions" do
case_log_with_met_radio_condition["armed_forces_injured"] = "No" case_log_with_met_radio_condition["reservist"] = "No"
case_log_with_met_radio_condition["medical_conditions"] = "No" case_log_with_met_radio_condition["illness"] = "No"
expect(total_answered_questions( expect(total_answered_questions(
subsection_with_radio_conditionals, subsection_with_radio_conditionals,
case_log_with_met_radio_condition, case_log_with_met_radio_condition,
@ -102,7 +102,7 @@ RSpec.describe CheckAnswersHelper do
end end
it "raises an error" do it "raises an error" do
allow_any_instance_of(Form).to receive(:pages_for_subsection).and_return(unimplemented_conditional) allow_any_instance_of(Form).to receive(:questions_for_page).and_return(unimplemented_conditional)
expect { total_number_of_questions(subsection, case_log, form) }.to raise_error(RuntimeError, "Not implemented yet") expect { total_number_of_questions(subsection, case_log, form) }.to raise_error(RuntimeError, "Not implemented yet")
end end
end end
@ -113,12 +113,12 @@ RSpec.describe CheckAnswersHelper do
end end
it "counts correct questions when the conditional question is answered" do it "counts correct questions when the conditional question is answered" do
case_log["pregnancy"] = "Yes" case_log["preg_occ"] = "Yes"
expect(total_number_of_questions(conditional_routing_subsection, case_log, form)).to eq(2) expect(total_number_of_questions(conditional_routing_subsection, case_log, form)).to eq(2)
end end
it "counts correct questions when the conditional question is answered" do it "counts correct questions when the conditional question is answered" do
case_log["pregnancy"] = "No" case_log["preg_occ"] = "No"
expect(total_number_of_questions(conditional_routing_subsection, case_log, form)).to eq(3) expect(total_number_of_questions(conditional_routing_subsection, case_log, form)).to eq(3)
end end
end end
@ -127,21 +127,21 @@ RSpec.describe CheckAnswersHelper do
it "returns total questions" do it "returns total questions" do
result = total_questions(subsection, case_log, form) result = total_questions(subsection, case_log, form)
expect(result.class).to eq(Hash) expect(result.class).to eq(Hash)
expected_keys = %w[net_income net_income_frequency net_income_uc_proportion housing_benefit] expected_keys = %w[earnings incfreq benefits hb]
expect(result.keys).to eq(expected_keys) expect(result.keys).to eq(expected_keys)
end end
context "conditional questions on the same page" do context "conditional questions on the same page" do
it "it filters out conditional questions that were not displayed" do it "it filters out conditional questions that were not displayed" do
result = total_questions(conditional_page_subsection, case_log, form) result = total_questions(conditional_page_subsection, case_log, form)
expected_keys = %w[armed_forces medical_conditions accessibility_requirements condition_effects] expected_keys = %w[armed_forces illness accessibility_requirements condition_effects]
expect(result.keys).to eq(expected_keys) expect(result.keys).to eq(expected_keys)
end end
it "it includes conditional questions that were displayed" do it "it includes conditional questions that were displayed" do
case_log["armed_forces"] = "Yes - a regular" case_log["armed_forces"] = "Yes - a regular"
result = total_questions(conditional_page_subsection, case_log, form) result = total_questions(conditional_page_subsection, case_log, form)
expected_keys = %w[armed_forces armed_forces_active armed_forces_injured medical_conditions accessibility_requirements condition_effects] expected_keys = %w[armed_forces leftreg reservist illness accessibility_requirements condition_effects]
expect(result.keys).to eq(expected_keys) expect(result.keys).to eq(expected_keys)
end end
end end
@ -149,22 +149,22 @@ RSpec.describe CheckAnswersHelper do
context "conditional routing" do context "conditional routing" do
it "it ignores skipped pages and the questions therein when conditional routing" do it "it ignores skipped pages and the questions therein when conditional routing" do
result = total_questions(conditional_routing_subsection, case_log, form) result = total_questions(conditional_routing_subsection, case_log, form)
expected_keys = %w[pregnancy] expected_keys = %w[preg_occ]
expect(result.keys).to match_array(expected_keys) expect(result.keys).to match_array(expected_keys)
end end
it "it includes conditional pages and questions that were displayed" do it "it includes conditional pages and questions that were displayed" do
case_log["pregnancy"] = "Yes" case_log["preg_occ"] = "Yes"
case_log["person_1_gender"] = "Female" case_log["sex1"] = "Female"
result = total_questions(conditional_routing_subsection, case_log, form) result = total_questions(conditional_routing_subsection, case_log, form)
expected_keys = %w[pregnancy] expected_keys = %w[preg_occ]
expect(result.keys).to match_array(expected_keys) expect(result.keys).to match_array(expected_keys)
end end
it "it includes conditional pages and questions that were displayed" do it "it includes conditional pages and questions that were displayed" do
case_log["pregnancy"] = "No" case_log["preg_occ"] = "No"
result = total_questions(conditional_routing_subsection, case_log, form) result = total_questions(conditional_routing_subsection, case_log, form)
expected_keys = %w[pregnancy conditional_question_no_question conditional_question_no_second_question] expected_keys = %w[preg_occ conditional_question_no_question conditional_question_no_second_question]
expect(result.keys).to match_array(expected_keys) expect(result.keys).to match_array(expected_keys)
end end
end end

4
spec/helpers/conditional_questions_helper_spec.rb

@ -7,7 +7,7 @@ RSpec.describe ConditionalQuestionsHelper do
let(:page) { form.all_pages[page_key] } let(:page) { form.all_pages[page_key] }
describe "conditional questions for page" do describe "conditional questions for page" do
let(:conditional_pages) { %w[armed_forces_active armed_forces_injured] } let(:conditional_pages) { %w[leftreg reservist] }
it "returns the question keys of all conditional questions on the given page" do it "returns the question keys of all conditional questions on the given page" do
expect(conditional_questions_for_page(page)).to eq(conditional_pages) expect(conditional_questions_for_page(page)).to eq(conditional_pages)
@ -16,7 +16,7 @@ RSpec.describe ConditionalQuestionsHelper do
describe "display question key div" do describe "display question key div" do
let(:question_key) { "armed_forces" } let(:question_key) { "armed_forces" }
let(:conditional_question_key) { "armed_forces_injured" } let(:conditional_question_key) { "reservist" }
it "returns a non visible div for conditional questions" do it "returns a non visible div for conditional questions" do
expect(display_question_key_div(page, conditional_question_key)).to match("style='display:none;'") expect(display_question_key_div(page, conditional_question_key)).to match("style='display:none;'")

12
spec/helpers/question_attribute_helper_spec.rb

@ -7,15 +7,15 @@ RSpec.describe QuestionAttributeHelper do
describe "html attributes" do describe "html attributes" do
it "returns empty hash if fields-to-add or result-field are empty " do it "returns empty hash if fields-to-add or result-field are empty " do
expect(stimulus_html_attributes(questions["total_charge"])).to eq({}) expect(stimulus_html_attributes(questions["tcharge"])).to eq({})
end end
it "returns html attributes if fields-to-add or result-field are not empty " do it "returns html attributes if fields-to-add or result-field are not empty " do
expect(stimulus_html_attributes(questions["basic_rent"])).to eq({ expect(stimulus_html_attributes(questions["brent"])).to eq({
"data-controller": "numeric-question", "data-controller": "numeric-question",
"data-action": "numeric-question#calculateFields", "data-action": "numeric-question#calculateFields",
"data-target": "case-log-#{questions['basic_rent']['result-field'].to_s.dasherize}-field", "data-target": "case-log-#{questions['brent']['result-field'].to_s.dasherize}-field",
"data-calculated": questions["basic_rent"]["fields-to-add"].to_json, "data-calculated": questions["brent"]["fields-to-add"].to_json,
}) })
end end
@ -28,8 +28,8 @@ RSpec.describe QuestionAttributeHelper do
"type" => "numeric", "type" => "numeric",
"min" => 0, "min" => 0,
"step" => 1, "step" => 1,
"fields-to-add" => %w[basic_rent service_charge personal_service_charge support_charge], "fields-to-add" => %w[brent scharge pscharge supcharg],
"result-field" => "total_charge", "result-field" => "tcharge",
"conditional_for" => { "conditional_for" => {
"next_question": ">1", "next_question": ">1",
}, },

6
spec/helpers/tasklist_helper_spec.rb

@ -30,7 +30,11 @@ RSpec.describe TasklistHelper do
end end
it "returns completed if all the questions in the subsection have been answered" do it "returns completed if all the questions in the subsection have been answered" do
%w[net_income net_income_frequency net_income_uc_proportion housing_benefit].each { |x| case_log[x] = "value" } case_log["earnings"] = "value"
case_log["incfreq"] = "Weekly"
case_log["benefits"] = "All"
case_log["hb"] = "Do not know"
status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions) status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions)
expect(status).to eq(:completed) expect(status).to eq(:completed)
end end

176
spec/models/case_log_spec.rb

@ -3,46 +3,46 @@ require "rails_helper"
RSpec.describe Form, type: :model do RSpec.describe Form, type: :model do
describe "#new" do describe "#new" do
it "validates age is a number" do it "validates age is a number" do
expect { CaseLog.create!(person_1_age: "random") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age1: "random") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates age is under 120" do it "validates age is under 120" do
expect { CaseLog.create!(person_1_age: 121) }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age1: 121) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates age is over 0" do it "validates age is over 0" do
expect { CaseLog.create!(person_1_age: 0) }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age1: 0) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates number of relets is a number" do it "validates number of relets is a number" do
expect { CaseLog.create!(property_number_of_times_relet: "random") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(offered: "random") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates number of relets is under 20" do it "validates number of relets is under 20" do
expect { CaseLog.create!(property_number_of_times_relet: 21) }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(offered: 21) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validates number of relets is over 0" do it "validates number of relets is over 0" do
expect { CaseLog.create!(property_number_of_times_relet: 0) }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(offered: 0) }.to raise_error(ActiveRecord::RecordInvalid)
end end
context "reasonable preference validation" do context "reasonable preference validation" do
it "if given reasonable preference is yes a reason must be selected" do it "if given reasonable preference is yes a reason must be selected" do
expect { expect {
CaseLog.create!(reasonable_preference: "Yes", CaseLog.create!(reasonpref: "Yes",
reasonable_preference_reason_homeless: nil, rp_homeless: nil,
reasonable_preference_reason_unsatisfactory_housing: nil, rp_insan_unsat: nil,
reasonable_preference_reason_medical_grounds: nil, rp_medwel: nil,
reasonable_preference_reason_avoid_hardship: nil, rp_hardship: nil,
reasonable_preference_reason_do_not_know: nil) rp_dontknow: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "if not previously homeless reasonable preference should not be selected" do it "if not previously homeless reasonable preference should not be selected" do
expect { expect {
CaseLog.create!( CaseLog.create!(
homelessness: "No", homeless: "No",
reasonable_preference: "Yes", reasonpref: "Yes",
) )
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -50,9 +50,9 @@ RSpec.describe Form, type: :model do
it "if not given reasonable preference a reason should not be selected" do it "if not given reasonable preference a reason should not be selected" do
expect { expect {
CaseLog.create!( CaseLog.create!(
homelessness: "Yes", homeless: "Yes - other homelessness",
reasonable_preference: "No", reasonpref: "No",
reasonable_preference_reason_homeless: true, rp_homeless: "Yes",
) )
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -60,22 +60,22 @@ RSpec.describe Form, type: :model do
context "reason for leaving last settled home validation" do 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 it "Reason for leaving must be don't know if reason for leaving settled home (Q9a) is don't know." do
expect { expect {
CaseLog.create!(reason_for_leaving_last_settled_home: "Do not know", CaseLog.create!(reason: "Do not know",
benefit_cap_spare_room_subsidy: "Yes - benefit cap") underoccupation_benefitcap: "Yes - benefit cap")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
context "other reason for leaving last settled home validation" do 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 it "must be provided if main reason for leaving last settled home was given as other" do
expect { expect {
CaseLog.create!(reason_for_leaving_last_settled_home: "Other", CaseLog.create!(reason: "Other",
other_reason_for_leaving_last_settled_home: nil) other_reason_for_leaving_last_settled_home: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "must not be provided if the main reason for leaving settled home is not other" do it "must not be provided if the main reason for leaving settled home is not other" do
expect { expect {
CaseLog.create!(reason_for_leaving_last_settled_home: "Repossession", CaseLog.create!(reason: "Repossession",
other_reason_for_leaving_last_settled_home: "the other reason provided") other_reason_for_leaving_last_settled_home: "the other reason provided")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -85,14 +85,14 @@ RSpec.describe Form, type: :model do
it "must be answered if tenant was a regular or reserve in armed forces" do it "must be answered if tenant was a regular or reserve in armed forces" do
expect { expect {
CaseLog.create!(armed_forces: "Yes - a regular", CaseLog.create!(armed_forces: "Yes - a regular",
armed_forces_injured: nil) reservist: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "must be answered if tenant was not a regular or reserve in armed forces" do it "must be answered if tenant was not a regular or reserve in armed forces" do
expect { expect {
CaseLog.create!(armed_forces: "No", CaseLog.create!(armed_forces: "No",
armed_forces_injured: "Yes") reservist: "Yes")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
@ -100,38 +100,38 @@ RSpec.describe Form, type: :model do
context "Shared accomodation bedrooms validation" do context "Shared accomodation bedrooms validation" do
it "you must have more than zero bedrooms" do it "you must have more than zero bedrooms" do
expect { expect {
CaseLog.create!(property_unit_type: "Shared house", CaseLog.create!(unittype_gn: "Shared house",
property_number_of_bedrooms: 0) beds: 0)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "you must answer less than 8 bedrooms" do it "you must answer less than 8 bedrooms" do
expect { expect {
CaseLog.create!(property_unit_type: "Shared bungalow", CaseLog.create!(unittype_gn: "Shared bungalow",
property_number_of_bedrooms: 8, beds: 8,
household_number_of_other_members: 1) other_hhmemb: 1)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "you must answer less than 8 bedrooms" do it "you must answer less than 8 bedrooms" do
expect { expect {
CaseLog.create!(property_unit_type: "Shared bungalow", CaseLog.create!(unittype_gn: "Shared bungalow",
property_number_of_bedrooms: 4, beds: 4,
household_number_of_other_members: 0) other_hhmemb: 0)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "A bedsit must only have one room" do it "A bedsit must only have one room" do
expect { expect {
CaseLog.create!(property_unit_type: "Bed-sit", CaseLog.create!(unittype_gn: "Bed-sit",
property_number_of_bedrooms: 2) beds: 2)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "A bedsit must only have one room" do it "A bedsit must only have one room" do
expect { expect {
CaseLog.create!(property_unit_type: "Bed-sit", CaseLog.create!(unittype_gn: "Bed-sit",
property_number_of_bedrooms: 0) beds: 0)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
@ -139,15 +139,15 @@ RSpec.describe Form, type: :model do
context "outstanding rent or charges validation" do context "outstanding rent or charges validation" do
it "must be anwered if answered yes to outstanding rent or charges" do it "must be anwered if answered yes to outstanding rent or charges" do
expect { expect {
CaseLog.create!(outstanding_rent_or_charges: "Yes", CaseLog.create!(hbrentshortfall: "Yes",
outstanding_amount: nil) tshortfall: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "must be not be anwered if answered no to outstanding rent or charges" do it "must be not be anwered if answered no to outstanding rent or charges" do
expect { expect {
CaseLog.create!(outstanding_rent_or_charges: "No", CaseLog.create!(hbrentshortfall: "No",
outstanding_amount: 99) tshortfall: 99)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
@ -155,19 +155,19 @@ RSpec.describe Form, type: :model do
context "tenant’s income is from Universal Credit, state pensions or benefits" do context "tenant’s income is from Universal Credit, state pensions or benefits" do
it "Cannot be All if person 1 works full time" do it "Cannot be All if person 1 works full time" do
expect { expect {
CaseLog.create!(net_income_uc_proportion: "All", person_1_economic_status: "Full-time - 30 hours or more") CaseLog.create!(benefits: "All", ecstat1: "Full-time - 30 hours or more")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Cannot be All if person 1 works part time" do it "Cannot be All if person 1 works part time" do
expect { expect {
CaseLog.create!(net_income_uc_proportion: "All", person_1_economic_status: "Part-time - Less than 30 hours") CaseLog.create!(benefits: "All", ecstat1: "Part-time - Less than 30 hours")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Cannot be 1 All if any of persons 2-4 are person 1's partner and work part or full time" do it "Cannot be 1 All if any of persons 2-4 are person 1's partner and work part or full time" do
expect { expect {
CaseLog.create!(net_income_uc_proportion: "All", person_2_relationship: "Partner", person_2_economic_status: "Part-time - Less than 30 hours") CaseLog.create!(benefits: "All", relat2: "Partner", ecstat2: "Part-time - Less than 30 hours")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
@ -175,47 +175,47 @@ RSpec.describe Form, type: :model do
context "fixed term tenancy length" do context "fixed term tenancy length" do
it "Must not be completed if Type of main tenancy is not responded with either Secure or Assured shorthold " do it "Must not be completed if Type of main tenancy is not responded with either Secure or Assured shorthold " do
expect { expect {
CaseLog.create!(tenancy_type: "Other", CaseLog.create!(tenancy: "Other",
fixed_term_tenancy: 10) tenancylength: 10)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "Must be completed and between 2 and 99 if type of tenancy is Assured shorthold" do it "Must be completed and between 2 and 99 if type of tenancy is Assured shorthold" do
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Assured Shorthold Tenancy (AST)", CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
fixed_term_tenancy: 1) tenancylength: 1)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Assured Shorthold Tenancy (AST)", CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
fixed_term_tenancy: nil) tenancylength: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Assured Shorthold Tenancy (AST)", CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
fixed_term_tenancy: 2) tenancylength: 2)
}.not_to raise_error }.not_to raise_error
end end
it "Must be empty or between 2 and 99 if type of tenancy is Secure" do it "Must be empty or between 2 and 99 if type of tenancy is Secure" do
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Secure", CaseLog.create!(tenancy: "Fixed term – Secure",
fixed_term_tenancy: 1) tenancylength: 1)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Secure", CaseLog.create!(tenancy: "Fixed term – Secure",
fixed_term_tenancy: 100) tenancylength: 100)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Secure", CaseLog.create!(tenancy: "Fixed term – Secure",
fixed_term_tenancy: nil) tenancylength: nil)
}.not_to raise_error }.not_to raise_error
expect { expect {
CaseLog.create!(tenancy_type: "Fixed term – Secure", CaseLog.create!(tenancy: "Fixed term – Secure",
fixed_term_tenancy: 2) tenancylength: 2)
}.not_to raise_error }.not_to raise_error
end end
end end
@ -224,14 +224,14 @@ RSpec.describe Form, type: :model do
it "must be answered if ever served in the forces as a regular" do it "must be answered if ever served in the forces as a regular" do
expect { expect {
CaseLog.create!(armed_forces: "Yes - a regular", CaseLog.create!(armed_forces: "Yes - a regular",
armed_forces_active: nil) leftreg: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "must not be answered if not ever served as a regular" do it "must not be answered if not ever served as a regular" do
expect { expect {
CaseLog.create!(armed_forces: "No", CaseLog.create!(armed_forces: "No",
armed_forces_active: "Yes") leftreg: "Yes")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -239,68 +239,68 @@ RSpec.describe Form, type: :model do
it "must be answered if ever served in the forces as a regular" do it "must be answered if ever served in the forces as a regular" do
expect do expect do
CaseLog.create!(armed_forces: "Yes - a regular", CaseLog.create!(armed_forces: "Yes - a regular",
armed_forces_active: "Yes", leftreg: "Yes",
armed_forces_injured: "Yes") reservist: "Yes")
end end
end end
end end
context "household_member_validations" do context "household_member_validations" do
it "validate that persons aged under 16 must have relationship Child" do it "validate that persons aged under 16 must have relationship Child" do
expect { CaseLog.create!(person_2_age: 14, person_2_relationship: "Partner") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 14, relat2: "Partner") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that persons aged over 70 must be retired" do it "validate that persons aged over 70 must be retired" do
expect { CaseLog.create!(person_2_age: 71, person_2_economic_status: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 71, ecstat2: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that a male, retired persons must be over 65" do it "validate that a male, retired persons must be over 65" do
expect { CaseLog.create!(person_2_age: 64, person_2_gender: "Male", person_2_economic_status: "Retired") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 64, sex2: "Male", ecstat2: "Retired") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that a female, retired persons must be over 60" do it "validate that a female, retired persons must be over 60" do
expect { CaseLog.create!(person_2_age: 59, person_2_gender: "Female", person_2_economic_status: "Retired") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 59, sex2: "Female", ecstat2: "Retired") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that persons aged under 16 must be a child (economically speaking)" do it "validate that persons aged under 16 must be a child (economically speaking)" do
expect { CaseLog.create!(person_2_age: 15, person_2_economic_status: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 15, ecstat2: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that persons aged between 16 and 19 that are a child must be a full time student or economic status refused" do it "validate that persons aged between 16 and 19 that are a child must be a full time student or economic status refused" do
expect { CaseLog.create!(person_2_age: 17, person_2_relationship: "Child - includes young adult and grown-up", person_2_economic_status: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 17, relat2: "Child - includes young adult and grown-up", ecstat2: "Full-time - 30 hours or more") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that persons aged under 16 must be a child relationship" do it "validate that persons aged under 16 must be a child relationship" do
expect { CaseLog.create!(person_2_age: 15, person_2_relationship: "Partner") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(age2: 15, relat2: "Partner") }.to raise_error(ActiveRecord::RecordInvalid)
end end
it "validate that no more than 1 partner relationship exists" do it "validate that no more than 1 partner relationship exists" do
expect { CaseLog.create!(person_2_relationship: "Partner", person_3_relationship: "Partner") }.to raise_error(ActiveRecord::RecordInvalid) expect { CaseLog.create!(relat2: "Partner", relat3: "Partner") }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
context "other tenancy type validation" do context "other tenancy type validation" do
it "must be provided if tenancy type was given as other" do it "must be provided if tenancy type was given as other" do
expect { expect {
CaseLog.create!(tenancy_type: "Other", CaseLog.create!(tenancy: "Other",
other_tenancy_type: nil) tenancyother: nil)
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Other", CaseLog.create!(tenancy: "Other",
other_tenancy_type: "type") tenancyother: "type")
}.not_to raise_error }.not_to raise_error
end end
it "must not be provided if tenancy type is not other" do it "must not be provided if tenancy type is not other" do
expect { expect {
CaseLog.create!(tenancy_type: "Fixed", CaseLog.create!(tenancy: "Fixed term – Secure",
other_tenancy_type: "the other reason provided") tenancyother: "the other reason provided")
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
expect { expect {
CaseLog.create!(tenancy_type: "Fixed", CaseLog.create!(tenancy: "Fixed term – Secure",
other_tenancy_type: nil) tenancyother: nil)
}.not_to raise_error }.not_to raise_error
end end
end end
@ -309,9 +309,9 @@ RSpec.describe Form, type: :model do
it "validates net income maximum" do it "validates net income maximum" do
expect { expect {
CaseLog.create!( CaseLog.create!(
person_1_economic_status: "Full-time - 30 hours or more", ecstat1: "Full-time - 30 hours or more",
net_income: 5000, earnings: 5000,
net_income_frequency: "Weekly", incfreq: "Weekly",
) )
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -319,9 +319,9 @@ RSpec.describe Form, type: :model do
it "validates net income minimum" do it "validates net income minimum" do
expect { expect {
CaseLog.create!( CaseLog.create!(
person_1_economic_status: "Full-time - 30 hours or more", ecstat1: "Full-time - 30 hours or more",
net_income: 1, earnings: 1,
net_income_frequency: "Weekly", incfreq: "Weekly",
) )
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
end end
@ -347,20 +347,20 @@ RSpec.describe Form, type: :model do
describe "weekly_net_income" do describe "weekly_net_income" do
let(:net_income) { 5000 } let(:net_income) { 5000 }
let(:case_log) { FactoryBot.build(:case_log, net_income: net_income) } let(:case_log) { FactoryBot.build(:case_log, earnings: net_income) }
it "returns input income if frequency is already weekly" do it "returns input income if frequency is already weekly" do
case_log.net_income_frequency = "Weekly" case_log.incfreq = "Weekly"
expect(case_log.weekly_net_income).to eq(net_income) expect(case_log.weekly_net_income).to eq(net_income)
end end
it "calculates the correct weekly income from monthly income" do it "calculates the correct weekly income from monthly income" do
case_log.net_income_frequency = "Monthly" case_log.incfreq = "Monthly"
expect(case_log.weekly_net_income).to eq(1154) expect(case_log.weekly_net_income).to eq(1154)
end end
it "calculates the correct weekly income from yearly income" do it "calculates the correct weekly income from yearly income" do
case_log.net_income_frequency = "Yearly" case_log.incfreq = "Yearly"
expect(case_log.weekly_net_income).to eq(417) expect(case_log.weekly_net_income).to eq(417)
end end
end end

2
spec/models/form_handler_spec.rb

@ -15,7 +15,7 @@ RSpec.describe FormHandler do
form_handler = FormHandler.instance form_handler = FormHandler.instance
form = form_handler.get_form("test_form") form = form_handler.get_form("test_form")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.all_pages.count).to eq(22) expect(form.all_pages.count).to eq(23)
end end
end end

2
spec/models/form_spec.rb

@ -39,7 +39,7 @@ RSpec.describe Form, type: :model do
it "returns all questions for subsection" do it "returns all questions for subsection" do
result = form.questions_for_subsection(subsection) result = form.questions_for_subsection(subsection)
expect(result.length).to eq(4) expect(result.length).to eq(4)
expect(result.keys).to eq(%w[net_income net_income_frequency net_income_uc_proportion housing_benefit]) expect(result.keys).to eq(%w[earnings incfreq benefits hb])
end end
end end
end end

20
spec/requests/case_log_controller_spec.rb

@ -24,8 +24,8 @@ RSpec.describe CaseLogsController, type: :request do
describe "POST #create" do describe "POST #create" do
let(:tenant_code) { "T365" } let(:tenant_code) { "T365" }
let(:person_1_age) { 35 } let(:age1) { 35 }
let(:property_number_of_times_relet) { 12 } let(:offered) { 12 }
let(:property_postcode) { "SE11 6TY" } let(:property_postcode) { "SE11 6TY" }
let(:in_progress) { "in_progress" } let(:in_progress) { "in_progress" }
let(:completed) { "completed" } let(:completed) { "completed" }
@ -33,9 +33,9 @@ RSpec.describe CaseLogsController, type: :request do
let(:params) do let(:params) do
{ {
"tenant_code": tenant_code, "tenant_code": tenant_code,
"person_1_age": person_1_age, "age1": age1,
"property_postcode": property_postcode, "property_postcode": property_postcode,
"property_number_of_times_relet": property_number_of_times_relet, "offered": offered,
} }
end end
@ -55,18 +55,18 @@ RSpec.describe CaseLogsController, type: :request do
it "creates a case log with the values passed" do it "creates a case log with the values passed" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(json_response["tenant_code"]).to eq(tenant_code) expect(json_response["tenant_code"]).to eq(tenant_code)
expect(json_response["person_1_age"]).to eq(person_1_age) expect(json_response["age1"]).to eq(age1)
expect(json_response["property_postcode"]).to eq(property_postcode) expect(json_response["property_postcode"]).to eq(property_postcode)
end end
context "invalid json params" do context "invalid json params" do
let(:person_1_age) { 2000 } let(:age1) { 2000 }
let(:property_number_of_times_relet) { 21 } let(:offered) { 21 }
it "validates case log parameters" do it "validates case log parameters" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]).to match_array([["property_number_of_times_relet", ["Property number of times relet must be between 0 and 20"]], ["person_1_age", ["Tenant age must be an integer between 16 and 120"]]]) expect(json_response["errors"]).to match_array([["offered", ["Property number of times relet must be between 0 and 20"]], ["age1", ["Tenant age must be an integer between 16 and 120"]]])
end end
end end
@ -157,7 +157,7 @@ RSpec.describe CaseLogsController, type: :request do
end end
context "invalid case log params" do context "invalid case log params" do
let(:params) { { person_1_age: 200 } } let(:params) { { age1: 200 } }
it "returns 422" do it "returns 422" do
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
@ -165,7 +165,7 @@ RSpec.describe CaseLogsController, type: :request do
it "returns an error message" do it "returns an error message" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(json_response["errors"]).to eq({ "person_1_age" => ["Tenant age must be an integer between 16 and 120"] }) expect(json_response["errors"]).to eq({ "age1" => ["Tenant age must be an integer between 16 and 120"] })
end end
end end

39
spec/requests/soft_validations_controller_spec.rb

@ -0,0 +1,39 @@
require "rails_helper"
RSpec.describe SoftValidationsController, type: :request do
let(:params) { { case_log_id: case_log.id } }
let(:url) { "/case_logs/#{case_log.id}/net_income/soft_validations" }
before do
get url, params: {}
end
describe "GET #show" do
context "Soft validation overide required" do
let(:case_log) { FactoryBot.create(:case_log, :soft_validations_triggered) }
it "returns a success response" do
expect(response).to be_successful
end
it "returns a json with the soft validation fields" do
json_response = JSON.parse(response.body)
expect(json_response["show"]).to eq(true)
expect(json_response["label"]).to match(/Are you sure this is correct?/)
end
end
context "Soft validation overide not required" do
let(:case_log) { FactoryBot.create(:case_log, :in_progress) }
it "returns a success response" do
expect(response).to be_successful
end
it "returns a json with the soft validation fields" do
json_response = JSON.parse(response.body)
expect(json_response["show"]).to eq(false)
end
end
end
end
Loading…
Cancel
Save