Browse Source

Cldc 1675 rent validations (#959)

* feat: add 2022 rent range data, update rake task for population of this

* feat: change file format so ranges_rent_id is recognised

* feat: add updated error messages and casing

* tests: make tests pass

* feat: ensure there is a location_code in all locations and use this (and beds = 0) for supported housing rent validations

* feat: fix general needs validation behaviour

* feat: add local authorities enum to location.rb

* feat: ensure case when beds > 4 is accounted for

* feat: add error messages on property postcode page as well as la page

* feat: add error messages on scheme_id and location_id as well as la page

* feat: add error messages on scheme_id and location_id as well as la page

* feat: null coalescing and validations on changing las to one that invalidates rent in supported housing

* feat: nil protection

* refactor: linting

* refactor: combining duplicated logic

* tests: add hard validation tests split by needstype

* feat: update validations when beds > 4

* feat: update validations when beds > 4

* refactor: simplification, use preivous la method

* refactor: response to PR comments, fixing beds.negative validation

* feat: remove dynamic local auth name text from interruption screens - to be added back in later if this becomes a priority, would need some work on adding local auth name to log for supported housing logs not just leaving it in the location
pull/972/head
natdeanlewissoftwire 2 years ago committed by GitHub
parent
commit
d89e03cc62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      app/controllers/locations_controller.rb
  2. 6
      app/helpers/interruption_screen_helper.rb
  3. 5
      app/helpers/locations_helper.rb
  4. 1
      app/models/la_rent_range.rb
  5. 10
      app/models/lettings_log.rb
  6. 321
      app/models/location.rb
  7. 11
      app/models/validations/financial_validations.rb
  8. 4
      app/models/validations/property_validations.rb
  9. 10
      app/models/validations/soft_validations.rb
  10. 6
      app/views/locations/edit_local_authority.html.erb
  11. 10
      config/forms/2021_2022.json
  12. 10
      config/forms/2022_2023.json
  13. 15
      config/locales/en.yml
  14. 71
      spec/models/validations/financial_validations_spec.rb
  15. 2
      spec/models/validations/property_validations_spec.rb

43
app/controllers/locations_controller.rb

@ -61,27 +61,32 @@ class LocationsController < ApplicationController
error_message = I18n.t("validations.location_admin_district") error_message = I18n.t("validations.location_admin_district")
@location.errors.add :location_admin_district, error_message @location.errors.add :location_admin_district, error_message
render :edit_local_authority, status: :unprocessable_entity render :edit_local_authority, status: :unprocessable_entity
elsif @location.update(location_params) else
case page if page == "edit-local-authority"
when "edit" params[:location][:location_code] = Location.local_authorities.key(params[:location][:location_admin_district])
if @location.location_admin_district.nil? end
redirect_to(location_edit_local_authority_path(id: @scheme.id, location_id: @location.id, add_another_location: location_params[:add_another_location])) if @location.update(location_params)
elsif location_params[:add_another_location] == "Yes" case page
redirect_to(new_location_path(@location.scheme)) when "edit"
else if @location.location_admin_district.nil?
redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) redirect_to(location_edit_local_authority_path(id: @scheme.id, location_id: @location.id, add_another_location: location_params[:add_another_location]))
end elsif location_params[:add_another_location] == "Yes"
when "edit-name" redirect_to(new_location_path(@location.scheme))
redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) else
when "edit-local-authority" redirect_to(scheme_check_answers_path(@scheme, anchor: "locations"))
if params[:add_another_location] == "Yes" end
redirect_to(new_location_path(@location.scheme)) when "edit-name"
else
redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) redirect_to(scheme_check_answers_path(@scheme, anchor: "locations"))
when "edit-local-authority"
if params[:add_another_location] == "Yes"
redirect_to(new_location_path(@location.scheme))
else
redirect_to(scheme_check_answers_path(@scheme, anchor: "locations"))
end
end end
else
render :edit, status: :unprocessable_entity
end end
else
render :edit, status: :unprocessable_entity
end end
end end
@ -123,7 +128,7 @@ private
end end
def location_params def location_params
required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :add_another_location, :startdate, :mobility_type, :location_admin_district).merge(scheme_id: @scheme.id) required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :add_another_location, :startdate, :mobility_type, :location_admin_district, :location_code).merge(scheme_id: @scheme.id)
required_params[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode] required_params[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode]
required_params required_params
end end

6
app/helpers/interruption_screen_helper.rb

@ -6,11 +6,7 @@ module InterruptionScreenHelper
informative_text["arguments"].each do |argument| informative_text["arguments"].each do |argument|
value = if argument["label"] value = if argument["label"]
pre_casing_value = lettings_log.form.get_question(argument["key"], lettings_log).answer_label(lettings_log) pre_casing_value = lettings_log.form.get_question(argument["key"], lettings_log).answer_label(lettings_log)
if argument["key"] == "la" pre_casing_value.downcase
pre_casing_value
else
pre_casing_value.downcase
end
else else
lettings_log.public_send(argument["key"]) lettings_log.public_send(argument["key"])
end end

5
app/helpers/locations_helper.rb

@ -12,6 +12,11 @@ module LocationsHelper
selection_options(Location.type_of_units) selection_options(Location.type_of_units)
end end
def local_authorities_selection
null_option = [OpenStruct.new(id: "", name: "Select an option")]
null_option + Location.local_authorities.map { |code, name| OpenStruct.new(code:, name:) }
end
def selection_options(resource) def selection_options(resource)
return [] if resource.blank? return [] if resource.blank?

1
app/models/la_rent_range.rb

@ -1,2 +1,3 @@
class LaRentRange < ApplicationRecord class LaRentRange < ApplicationRecord
MAX_BEDS = 4
end end

10
app/models/lettings_log.rb

@ -435,13 +435,19 @@ class LettingsLog < Log
Csv::LettingsLogCsvService.new(user).to_csv Csv::LettingsLogCsvService.new(user).to_csv
end end
def beds_for_la_rent_range
return 0 if is_supported_housing?
beds.nil? ? nil : [beds, LaRentRange::MAX_BEDS].min
end
def soft_min_for_period def soft_min_for_period
soft_min = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:).soft_min soft_min = LaRentRange.find_by(start_year: collection_start_year, la:, beds: beds_for_la_rent_range, lettype:).soft_min
"#{soft_value_for_period(soft_min)} #{SUFFIX_FROM_PERIOD[period].presence || 'every week'}" "#{soft_value_for_period(soft_min)} #{SUFFIX_FROM_PERIOD[period].presence || 'every week'}"
end end
def soft_max_for_period def soft_max_for_period
soft_max = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype:).soft_max soft_max = LaRentRange.find_by(start_year: collection_start_year, la:, beds: beds_for_la_rent_range, lettype:).soft_max
"#{soft_value_for_period(soft_max)} #{SUFFIX_FROM_PERIOD[period].presence || 'every week'}" "#{soft_value_for_period(soft_max)} #{SUFFIX_FROM_PERIOD[period].presence || 'every week'}"
end end

321
app/models/location.rb

@ -17,6 +17,327 @@ class Location < ApplicationRecord
scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) } scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) }
scope :active, -> { where(confirmed: true).and(started) } scope :active, -> { where(confirmed: true).and(started) }
LOCAL_AUTHORITIES = {
"E07000223": "Adur",
"E07000026": "Allerdale",
"E07000032": "Amber Valley",
"E07000224": "Arun",
"E07000170": "Ashfield",
"E07000105": "Ashford",
"E07000200": "Babergh",
"E09000002": "Barking and Dagenham",
"E09000003": "Barnet",
"E08000016": "Barnsley",
"E07000027": "Barrow-in-Furness",
"E07000066": "Basildon",
"E07000084": "Basingstoke and Deane",
"E07000171": "Bassetlaw",
"E06000022": "Bath and North East Somerset",
"E06000055": "Bedford",
"E09000004": "Bexley",
"E08000025": "Birmingham",
"E07000129": "Blaby",
"E06000008": "Blackburn with Darwen",
"E06000009": "Blackpool",
"E07000033": "Bolsover",
"E08000001": "Bolton",
"E07000136": "Boston",
"E06000058": "Bournemouth, Christchurch and Poole",
"E06000036": "Bracknell Forest",
"E08000032": "Bradford",
"E07000067": "Braintree",
"E07000143": "Breckland",
"E09000005": "Brent",
"E07000068": "Brentwood",
"E06000043": "Brighton and Hove",
"E06000023": "Bristol, City of",
"E07000144": "Broadland",
"E09000006": "Bromley",
"E07000234": "Bromsgrove",
"E07000095": "Broxbourne",
"E07000172": "Broxtowe",
"E06000060": "Buckinghamshire",
"E07000117": "Burnley",
"E08000002": "Bury",
"E08000033": "Calderdale",
"E07000008": "Cambridge",
"E09000007": "Camden",
"E07000192": "Cannock Chase",
"E07000106": "Canterbury",
"E07000028": "Carlisle",
"E07000069": "Castle Point",
"E06000056": "Central Bedfordshire",
"E07000130": "Charnwood",
"E07000070": "Chelmsford",
"E07000078": "Cheltenham",
"E07000177": "Cherwell",
"E06000049": "Cheshire East",
"E06000050": "Cheshire West and Chester",
"E07000034": "Chesterfield",
"E07000225": "Chichester",
"E07000118": "Chorley",
"E09000001": "City of London",
"E07000071": "Colchester",
"E07000029": "Copeland",
"E07000150": "Corby",
"E06000052": "Cornwall",
"E07000079": "Cotswold",
"E06000047": "County Durham",
"E08000026": "Coventry",
"E07000163": "Craven",
"E07000226": "Crawley",
"E09000008": "Croydon",
"E07000096": "Dacorum",
"E06000005": "Darlington",
"E07000107": "Dartford",
"E07000151": "Daventry",
"E06000015": "Derby",
"E07000035": "Derbyshire Dales",
"E08000017": "Doncaster",
"E06000059": "Dorset",
"E07000108": "Dover",
"E08000027": "Dudley",
"E09000009": "Ealing",
"E07000009": "East Cambridgeshire",
"E07000040": "East Devon",
"E07000085": "East Hampshire",
"E07000242": "East Hertfordshire",
"E07000137": "East Lindsey",
"E07000152": "East Northamptonshire",
"E06000011": "East Riding of Yorkshire",
"E07000193": "East Staffordshire",
"E07000244": "East Suffolk",
"E07000061": "Eastbourne",
"E07000086": "Eastleigh",
"E07000030": "Eden",
"E07000207": "Elmbridge",
"E09000010": "Enfield",
"E07000072": "Epping Forest",
"E07000208": "Epsom and Ewell",
"E07000036": "Erewash",
"E07000041": "Exeter",
"E07000087": "Fareham",
"E07000010": "Fenland",
"E07000112": "Folkestone and Hythe",
"E07000080": "Forest of Dean",
"E07000119": "Fylde",
"E08000037": "Gateshead",
"E07000173": "Gedling",
"E07000081": "Gloucester",
"E07000088": "Gosport",
"E07000109": "Gravesham",
"E07000145": "Great Yarmouth",
"E09000011": "Greenwich",
"E07000209": "Guildford",
"W06000002": "Gwynedd",
"E09000012": "Hackney",
"E06000006": "Halton",
"E07000164": "Hambleton",
"E09000013": "Hammersmith and Fulham",
"E07000131": "Harborough",
"E09000014": "Haringey",
"E07000073": "Harlow",
"E07000165": "Harrogate",
"E09000015": "Harrow",
"E07000089": "Hart",
"E06000001": "Hartlepool",
"E07000062": "Hastings",
"E07000090": "Havant",
"E09000016": "Havering",
"E06000019": "Herefordshire, County of",
"E07000098": "Hertsmere",
"E07000037": "High Peak",
"S12000017": "Highland",
"E09000017": "Hillingdon",
"E07000132": "Hinckley and Bosworth",
"E07000227": "Horsham",
"E09000018": "Hounslow",
"E07000011": "Huntingdonshire",
"E07000120": "Hyndburn",
"E07000202": "Ipswich",
"E06000046": "Isle of Wight",
"E06000053": "Isles of Scilly",
"E09000019": "Islington",
"E09000020": "Kensington and Chelsea",
"E07000153": "Kettering",
"E07000146": "King’s Lynn and West Norfolk",
"E06000010": "Kingston upon Hull, City of",
"E09000021": "Kingston upon Thames",
"E08000034": "Kirklees",
"E08000011": "Knowsley",
"E09000022": "Lambeth",
"E07000121": "Lancaster",
"E08000035": "Leeds",
"E06000016": "Leicester",
"E07000063": "Lewes",
"E09000023": "Lewisham",
"E07000194": "Lichfield",
"E07000138": "Lincoln",
"E08000012": "Liverpool",
"E06000032": "Luton",
"E07000110": "Maidstone",
"E07000074": "Maldon",
"E07000235": "Malvern Hills",
"E08000003": "Manchester",
"E07000174": "Mansfield",
"E06000035": "Medway",
"E07000133": "Melton",
"E07000187": "Mendip",
"E09000024": "Merton",
"E07000042": "Mid Devon",
"E07000203": "Mid Suffolk",
"E07000228": "Mid Sussex",
"E06000002": "Middlesbrough",
"E06000042": "Milton Keynes",
"E07000210": "Mole Valley",
"E07000091": "New Forest",
"E07000175": "Newark and Sherwood",
"E08000021": "Newcastle upon Tyne",
"E07000195": "Newcastle-under-Lyme",
"E09000025": "Newham",
"E07000043": "North Devon",
"E07000038": "North East Derbyshire",
"E06000012": "North East Lincolnshire",
"E07000099": "North Hertfordshire",
"E07000139": "North Kesteven",
"E06000013": "North Lincolnshire",
"E07000147": "North Norfolk",
"E06000024": "North Somerset",
"E08000022": "North Tyneside",
"E07000218": "North Warwickshire",
"E07000134": "North West Leicestershire",
"E07000154": "Northampton",
"E06000057": "Northumberland",
"E07000148": "Norwich",
"E06000018": "Nottingham",
"E07000219": "Nuneaton and Bedworth",
"E07000135": "Oadby and Wigston",
"E08000004": "Oldham",
"E07000178": "Oxford",
"E07000122": "Pendle",
"E06000031": "Peterborough",
"E06000026": "Plymouth",
"E06000044": "Portsmouth",
"E07000123": "Preston",
"E06000038": "Reading",
"E09000026": "Redbridge",
"E06000003": "Redcar and Cleveland",
"E07000236": "Redditch",
"E07000211": "Reigate and Banstead",
"E07000124": "Ribble Valley",
"E09000027": "Richmond upon Thames",
"E07000166": "Richmondshire",
"E08000005": "Rochdale",
"E07000075": "Rochford",
"E07000125": "Rossendale",
"E07000064": "Rother",
"E08000018": "Rotherham",
"E07000220": "Rugby",
"E07000212": "Runnymede",
"E07000176": "Rushcliffe",
"E07000092": "Rushmoor",
"E06000017": "Rutland",
"E07000167": "Ryedale",
"E08000006": "Salford",
"E08000028": "Sandwell",
"E07000168": "Scarborough",
"E07000188": "Sedgemoor",
"E08000014": "Sefton",
"E07000169": "Selby",
"E07000111": "Sevenoaks",
"E08000019": "Sheffield",
"E06000051": "Shropshire",
"E06000039": "Slough",
"E08000029": "Solihull",
"E07000246": "Somerset West and Taunton",
"E07000012": "South Cambridgeshire",
"E07000039": "South Derbyshire",
"E06000025": "South Gloucestershire",
"E07000044": "South Hams",
"E07000140": "South Holland",
"E07000141": "South Kesteven",
"E07000031": "South Lakeland",
"E07000149": "South Norfolk",
"E07000155": "South Northamptonshire",
"E07000179": "South Oxfordshire",
"E07000126": "South Ribble",
"E07000189": "South Somerset",
"E07000196": "South Staffordshire",
"E08000023": "South Tyneside",
"E06000045": "Southampton",
"E06000033": "Southend-on-Sea",
"E09000028": "Southwark",
"E07000213": "Spelthorne",
"E07000240": "St Albans",
"E08000013": "St. Helens",
"E07000197": "Stafford",
"E07000198": "Staffordshire Moorlands",
"E07000243": "Stevenage",
"E08000007": "Stockport",
"E06000004": "Stockton-on-Tees",
"E06000021": "Stoke-on-Trent",
"E07000221": "Stratford-on-Avon",
"E07000082": "Stroud",
"E08000024": "Sunderland",
"E07000214": "Surrey Heath",
"E09000029": "Sutton",
"E07000113": "Swale",
"E06000030": "Swindon",
"E08000008": "Tameside",
"E07000199": "Tamworth",
"E07000215": "Tandridge",
"E07000045": "Teignbridge",
"E06000020": "Telford and Wrekin",
"E07000076": "Tendring",
"E07000093": "Test Valley",
"E07000083": "Tewkesbury",
"E07000114": "Thanet",
"E07000102": "Three Rivers",
"E06000034": "Thurrock",
"E07000115": "Tonbridge and Malling",
"E06000027": "Torbay",
"E07000046": "Torridge",
"E09000030": "Tower Hamlets",
"E08000009": "Trafford",
"E07000116": "Tunbridge Wells",
"E07000077": "Uttlesford",
"E07000180": "Vale of White Horse",
"E08000036": "Wakefield",
"E08000030": "Walsall",
"E09000031": "Waltham Forest",
"E09000032": "Wandsworth",
"E06000007": "Warrington",
"E07000222": "Warwick",
"E07000103": "Watford",
"E07000216": "Waverley",
"E07000065": "Wealden",
"E07000156": "Wellingborough",
"E07000241": "Welwyn Hatfield",
"E06000037": "West Berkshire",
"E07000047": "West Devon",
"E07000127": "West Lancashire",
"E07000142": "West Lindsey",
"E07000181": "West Oxfordshire",
"E07000245": "West Suffolk",
"E09000033": "Westminster",
"E08000010": "Wigan",
"E06000054": "Wiltshire",
"E07000094": "Winchester",
"E06000040": "Windsor and Maidenhead",
"E08000015": "Wirral",
"E07000217": "Woking",
"E06000041": "Wokingham",
"E08000031": "Wolverhampton",
"E07000237": "Worcester",
"E07000229": "Worthing",
"E07000238": "Wychavon",
"E07000128": "Wyre",
"E07000239": "Wyre Forest",
"E06000014": "York",
}.freeze
enum local_authorities: LOCAL_AUTHORITIES
MOBILITY_TYPE = { MOBILITY_TYPE = {
"Wheelchair-user standard": "W", "Wheelchair-user standard": "W",
"Fitted with equipment and adaptations": "A", "Fitted with equipment and adaptations": "A",

11
app/models/validations/financial_validations.rb

@ -181,20 +181,27 @@ private
return if record.startdate.blank? return if record.startdate.blank?
collection_year = record.collection_start_year collection_year = record.collection_start_year
rent_range = LaRentRange.find_by(start_year: collection_year, la: record.la, beds: record.beds, lettype: record.lettype)
rent_range = LaRentRange.find_by(start_year: collection_year, la: record.la, beds: record.beds_for_la_rent_range, lettype: record.lettype)
if rent_range.present? && !weekly_value_in_range(record, "brent", rent_range.hard_min, rent_range.hard_max) && record.brent.present? && record.period.present? if rent_range.present? && !weekly_value_in_range(record, "brent", rent_range.hard_min, rent_range.hard_max) && record.brent.present? && record.period.present?
if record.weekly_value(record["brent"]) < rent_range.hard_min if record.weekly_value(record["brent"]) < rent_range.hard_min
record.errors.add :brent, I18n.t("validations.financial.brent.below_hard_min") record.errors.add :brent, I18n.t("validations.financial.brent.below_hard_min")
record.errors.add :beds, I18n.t("validations.financial.brent.beds.below_hard_min") record.errors.add :beds, I18n.t("validations.financial.brent.beds.below_hard_min")
record.errors.add :la, I18n.t("validations.financial.brent.la.below_hard_min") record.errors.add :la, I18n.t("validations.financial.brent.la.below_hard_min")
record.errors.add :postcode_known, I18n.t("validations.financial.brent.postcode_known.below_hard_min")
record.errors.add :scheme_id, I18n.t("validations.financial.brent.scheme_id.below_hard_min")
record.errors.add :location_id, I18n.t("validations.financial.brent.location_id.below_hard_min")
record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.below_hard_min") record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.below_hard_min")
record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.below_hard_min") record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.below_hard_min")
record.errors.add :period, I18n.t("validations.financial.brent.period.below_hard_min") record.errors.add :period, I18n.t("validations.financial.brent.period.below_hard_min")
else elsif record.beds.blank? || record.beds < LaRentRange::MAX_BEDS
record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max") record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max")
record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max") record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max")
record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max") record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max")
record.errors.add :postcode_known, I18n.t("validations.financial.brent.postcode_known.above_hard_max")
record.errors.add :scheme_id, I18n.t("validations.financial.brent.scheme_id.above_hard_max")
record.errors.add :location_id, I18n.t("validations.financial.brent.location_id.above_hard_max")
record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.above_hard_max") record.errors.add :rent_type, I18n.t("validations.financial.brent.rent_type.above_hard_max")
record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.above_hard_max") record.errors.add :needstype, I18n.t("validations.financial.brent.needstype.above_hard_max")
record.errors.add :period, I18n.t("validations.financial.brent.period.above_hard_max") record.errors.add :period, I18n.t("validations.financial.brent.period.above_hard_max")

4
app/models/validations/property_validations.rb

@ -55,8 +55,8 @@ module Validations::PropertyValidations
end end
def validate_shared_housing_rooms(record) def validate_shared_housing_rooms(record)
if record.beds.present? && record.beds.negative? if record.beds.present? && record.beds <= 0
record.errors.add :beds, I18n.t("validations.property.beds.negative") record.errors.add :beds, I18n.t("validations.property.beds.non_positive")
end end
unless record.unittype_gn.nil? unless record.unittype_gn.nil?

10
app/models/validations/soft_validations.rb

@ -28,15 +28,19 @@ module Validations::SoftValidations
def rent_in_soft_min_range? def rent_in_soft_min_range?
return unless brent && weekly_value(brent) && startdate return unless brent && weekly_value(brent) && startdate
rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype: get_lettype) rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds: beds_for_la_rent_range, lettype: get_lettype)
rent_range.present? && weekly_value(brent).between?(rent_range.hard_min, rent_range.soft_min) rent_range.present? && weekly_value(brent).between?(rent_range.hard_min, rent_range.soft_min)
end end
def rent_in_soft_max_range? def rent_in_soft_max_range?
return unless brent && weekly_value(brent) && startdate return unless brent && weekly_value(brent) && startdate
rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds:, lettype: get_lettype) rent_range = LaRentRange.find_by(start_year: collection_start_year, la:, beds: beds_for_la_rent_range, lettype: get_lettype)
rent_range.present? && weekly_value(brent).between?(rent_range.soft_max, rent_range.hard_max) if beds.present? && rent_range.present? && beds > LaRentRange::MAX_BEDS
weekly_value(brent) > rent_range.soft_max
elsif rent_range.present?
weekly_value(brent).between?(rent_range.soft_max, rent_range.hard_max)
end
end end
(1..8).each do |person_num| (1..8).each do |person_num|

6
app/views/locations/edit_local_authority.html.erb

@ -12,12 +12,8 @@
<%= render partial: "organisations/headings", locals: { main: "What is the local authority of #{@location.postcode}?", sub: @scheme.service_name } %> <%= render partial: "organisations/headings", locals: { main: "What is the local authority of #{@location.postcode}?", sub: @scheme.service_name } %>
<% la_list = FormHandler.instance.current_lettings_form.get_question("la", nil).answer_options.values %>
<% las = la_list.map { |la| OpenStruct.new(name: la) } %>
<%= f.govuk_collection_select :location_admin_district, <%= f.govuk_collection_select :location_admin_district,
las, local_authorities_selection,
:name, :name,
:name, :name,
label: { hidden: true }, label: { hidden: true },

10
config/forms/2021_2022.json

@ -8430,11 +8430,6 @@
"informative_text": { "informative_text": {
"translation": "soft_validations.rent.min.hint_text", "translation": "soft_validations.rent.min.hint_text",
"arguments": [ "arguments": [
{
"key": "la",
"label": true,
"i18n_template": "la"
},
{ {
"key": "soft_min_for_period", "key": "soft_min_for_period",
"label": false, "label": false,
@ -8487,11 +8482,6 @@
"informative_text": { "informative_text": {
"translation": "soft_validations.rent.max.hint_text", "translation": "soft_validations.rent.max.hint_text",
"arguments": [ "arguments": [
{
"key": "la",
"label": true,
"i18n_template": "la"
},
{ {
"key": "soft_max_for_period", "key": "soft_max_for_period",
"label": false, "label": false,

10
config/forms/2022_2023.json

@ -8386,11 +8386,6 @@
"informative_text": { "informative_text": {
"translation": "soft_validations.rent.min.hint_text", "translation": "soft_validations.rent.min.hint_text",
"arguments": [ "arguments": [
{
"key": "la",
"label": true,
"i18n_template": "la"
},
{ {
"key": "soft_min_for_period", "key": "soft_min_for_period",
"label": false, "label": false,
@ -8443,11 +8438,6 @@
"informative_text": { "informative_text": {
"translation": "soft_validations.rent.max.hint_text", "translation": "soft_validations.rent.max.hint_text",
"arguments": [ "arguments": [
{
"key": "la",
"label": true,
"i18n_template": "la"
},
{ {
"key": "soft_max_for_period", "key": "soft_max_for_period",
"label": false, "label": false,

15
config/locales/en.yml

@ -146,7 +146,7 @@ en:
one_seven_bedroom_shared: "A shared house must have 1 to 7 bedrooms" one_seven_bedroom_shared: "A shared house must have 1 to 7 bedrooms"
one_three_bedroom_single_tenant_shared: "A shared house with fewer than two tenants must have 1 to 3 bedrooms" one_three_bedroom_single_tenant_shared: "A shared house with fewer than two tenants must have 1 to 3 bedrooms"
beds: beds:
negative: "Number of bedrooms has to be greater than 0" non_positive: "Number of bedrooms has to be greater than 0"
over_max: "Number of bedrooms cannot be more than 12" over_max: "Number of bedrooms cannot be more than 12"
financial: financial:
@ -190,6 +190,15 @@ en:
brent: brent:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms" below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms" above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
scheme_id:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period and local authority"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period and local authority"
location_id:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period and local authority"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period and local authority"
postcode_known:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and number of bedrooms"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and number of bedrooms"
la: la:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type based on this local authority" below_hard_min: "Rent is below the absolute minimum expected for a property of this type based on this local authority"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type based on this local authority" above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type based on this local authority"
@ -313,10 +322,10 @@ en:
rent: rent:
min: min:
title_text: "You told us the rent is %{brent}" title_text: "You told us the rent is %{brent}"
hint_text: "The minimum rent expected for this type of property in %{la} is £%{soft_min_for_period}." hint_text: "The minimum rent expected for this type of property in this local authority is £%{soft_min_for_period}."
max: max:
title_text: "You told us the rent is %{brent}" title_text: "You told us the rent is %{brent}"
hint_text: "The maximum rent expected for this type of property in %{la} is £%{soft_max_for_period}." hint_text: "The maximum rent expected for this type of property in this local authority is £%{soft_max_for_period}."
retirement: retirement:
min: min:
title: "You told us this person is under %{age} and retired" title: "You told us this person is under %{age} and retired"

71
spec/models/validations/financial_validations_spec.rb

@ -247,6 +247,8 @@ RSpec.describe Validations::FinancialValidations do
end end
describe "rent and charges validations" do describe "rent and charges validations" do
let!(:location) { FactoryBot.create(:location, location_code: "E07000223") }
context "when the owning organisation is a private registered provider" do context "when the owning organisation is a private registered provider" do
before { record.owning_organisation.provider_type = 2 } before { record.owning_organisation.provider_type = 2 }
@ -777,7 +779,7 @@ RSpec.describe Validations::FinancialValidations do
context "when validating ranges based on LA and needstype" do context "when validating ranges based on LA and needstype" do
before do before do
LaRentRange.create( LaRentRange.create!(
ranges_rent_id: "1", ranges_rent_id: "1",
la: "E07000223", la: "E07000223",
beds: 1, beds: 1,
@ -788,9 +790,21 @@ RSpec.describe Validations::FinancialValidations do
hard_max: 100.99, hard_max: 100.99,
start_year: 2021, start_year: 2021,
) )
LaRentRange.create!(
ranges_rent_id: "2",
la: "E07000223",
beds: 0,
lettype: 2,
soft_min: 12.41,
soft_max: 89.54,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2021,
)
end end
it "validates hard minimum" do it "validates hard minimum for general needs" do
record.needstype = 1
record.lettype = 1 record.lettype = 1
record.period = 1 record.period = 1
record.la = "E07000223" record.la = "E07000223"
@ -803,7 +817,21 @@ RSpec.describe Validations::FinancialValidations do
.to include(match I18n.t("validations.financial.brent.below_hard_min")) .to include(match I18n.t("validations.financial.brent.below_hard_min"))
end end
it "validates hard max" do it "validates hard minimum for supported housing" do
record.needstype = 2
record.lettype = 2
record.period = 1
record.location = location
record.startdate = Time.zone.local(2021, 9, 17)
record.brent = 9.17
financial_validator.validate_rent_amount(record)
expect(record.errors["brent"])
.to include(match I18n.t("validations.financial.brent.below_hard_min"))
end
it "validates hard max for general needs" do
record.needstype = 1
record.lettype = 1 record.lettype = 1
record.period = 1 record.period = 1
record.la = "E07000223" record.la = "E07000223"
@ -818,10 +846,47 @@ RSpec.describe Validations::FinancialValidations do
.to include(match I18n.t("validations.financial.brent.beds.above_hard_max")) .to include(match I18n.t("validations.financial.brent.beds.above_hard_max"))
expect(record.errors["la"]) expect(record.errors["la"])
.to include(match I18n.t("validations.financial.brent.la.above_hard_max")) .to include(match I18n.t("validations.financial.brent.la.above_hard_max"))
expect(record.errors["postcode_known"])
.to include(match I18n.t("validations.financial.brent.postcode_known.above_hard_max"))
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.financial.brent.scheme_id.above_hard_max"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.financial.brent.location_id.above_hard_max"))
expect(record.errors["rent_type"])
.to include(match I18n.t("validations.financial.brent.rent_type.above_hard_max"))
expect(record.errors["needstype"])
.to include(match I18n.t("validations.financial.brent.needstype.above_hard_max"))
expect(record.errors["period"])
.to include(match I18n.t("validations.financial.brent.period.above_hard_max"))
end
it "validates hard max for supported housing" do
record.needstype = 2
record.lettype = 2
record.period = 1
record.location = location
record.startdate = Time.zone.local(2021, 9, 17)
record.brent = 200
financial_validator.validate_rent_amount(record)
expect(record.errors["brent"])
.to include(match I18n.t("validations.financial.brent.above_hard_max"))
expect(record.errors["beds"])
.to include(match I18n.t("validations.financial.brent.beds.above_hard_max"))
expect(record.errors["la"])
.to include(match I18n.t("validations.financial.brent.la.above_hard_max"))
expect(record.errors["postcode_known"])
.to include(match I18n.t("validations.financial.brent.postcode_known.above_hard_max"))
expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.financial.brent.scheme_id.above_hard_max"))
expect(record.errors["location_id"])
.to include(match I18n.t("validations.financial.brent.location_id.above_hard_max"))
expect(record.errors["rent_type"]) expect(record.errors["rent_type"])
.to include(match I18n.t("validations.financial.brent.rent_type.above_hard_max")) .to include(match I18n.t("validations.financial.brent.rent_type.above_hard_max"))
expect(record.errors["needstype"]) expect(record.errors["needstype"])
.to include(match I18n.t("validations.financial.brent.needstype.above_hard_max")) .to include(match I18n.t("validations.financial.brent.needstype.above_hard_max"))
expect(record.errors["period"])
.to include(match I18n.t("validations.financial.brent.period.above_hard_max"))
end end
it "validates hard max for correct collection year" do it "validates hard max for correct collection year" do

2
spec/models/validations/property_validations_spec.rb

@ -134,7 +134,7 @@ RSpec.describe Validations::PropertyValidations do
it "adds an error" do it "adds an error" do
record.beds = -4 record.beds = -4
property_validator.validate_shared_housing_rooms(record) property_validator.validate_shared_housing_rooms(record)
expect(record.errors["beds"]).to include(I18n.t("validations.property.beds.negative")) expect(record.errors["beds"]).to include(I18n.t("validations.property.beds.non_positive"))
end end
end end

Loading…
Cancel
Save