From cdd569a9aae151bde291fbaf3e14e4a68b9f3e9b Mon Sep 17 00:00:00 2001 From: Kat Date: Mon, 21 Mar 2022 14:54:20 +0000 Subject: [PATCH] Add rent ranges table and basic hard range validation Co-authored-by: baarkerlounger --- app/models/la_rent_range.rb | 14 +++++ .../validations/financial_validations.rb | 19 ++++-- config/locales/en.yml | 4 +- .../20220321093810_create_la_rent_ranges.rb | 21 +++++++ db/schema.rb | 18 ++++++ db/seeds.rb | 13 ++++ .../validations/financial_validations_spec.rb | 61 +++++++++++++++++++ 7 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 app/models/la_rent_range.rb create mode 100644 db/migrate/20220321093810_create_la_rent_ranges.rb diff --git a/app/models/la_rent_range.rb b/app/models/la_rent_range.rb new file mode 100644 index 000000000..cefdc92ae --- /dev/null +++ b/app/models/la_rent_range.rb @@ -0,0 +1,14 @@ +class LaRentRange < ApplicationRecord + PROVIDER_TYPE = { + "LA": 1, + "HA": 2, + }.freeze + + NEEDS_TYPE = { + "General Needs": 1, + "Supported Housing": 0, + }.freeze + + enum provider_type: PROVIDER_TYPE + enum needstype: NEEDS_TYPE +end diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb index 32ed2f1bd..230d2ece5 100644 --- a/app/models/validations/financial_validations.rb +++ b/app/models/validations/financial_validations.rb @@ -65,7 +65,7 @@ module Validations::FinancialValidations record.errors.add :tshortfall, I18n.t("validations.financial.tshortfall.more_than_rent") end - if record.tcharge.present? && weekly_value_in_range(record, "tcharge", 9.99) + if record.tcharge.present? && weekly_value_in_range(record, "tcharge", 0, 9.99) record.errors.add :tcharge, I18n.t("validations.financial.tcharge.under_10") end @@ -77,6 +77,7 @@ module Validations::FinancialValidations end validate_charges(record) + validate_rent_range(record) end private @@ -121,13 +122,23 @@ private %i[scharge pscharge supcharg].each do |charge| maximum = CHARGE_MAXIMUMS.dig(charge, LANDLORD_VALUES[record.landlord], NEEDSTYPE_VALUES[record.needstype]) - if maximum.present? && !weekly_value_in_range(record, charge, maximum) + if maximum.present? && !weekly_value_in_range(record, charge, 0, maximum) record.errors.add charge, I18n.t("validations.financial.rent.#{charge}.#{LANDLORD_VALUES[record.landlord]}.#{NEEDSTYPE_VALUES[record.needstype]}") end end end - def weekly_value_in_range(record, field, max) - record[field].present? && record.weekly_value(record[field]).present? && record.weekly_value(record[field]).between?(0, max) + def weekly_value_in_range(record, field, min, max) + record[field].present? && record.weekly_value(record[field]).present? && record.weekly_value(record[field]).between?(min, max) + end + + PROVIDER_TYPE = { "LA" => "LA", "PRP" => "HA" }.freeze + + def validate_rent_range(record) + rent_range = LaRentRange.find_by(year: record.year, ons_code: record.la, provider_type: PROVIDER_TYPE[record.managing_organisation.provider_type], needstype: record.needstype, beds: record.beds, renttype: record.renttype) + + if rent_range.present? && !weekly_value_in_range(record, "brent", rent_range.hard_min, rent_range.hard_max) + record.errors.add :brent, I18n.t("validations.financial.brent.not_in_range") + end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index b654ab394..8c1ad320d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -47,7 +47,7 @@ en: taken: "Email already exists" invalid: "Enter an email address in the correct format, like name@example.com" blank: "Enter an email address" - + setup: intermediate_rent_product_name: blank: "Enter name of other intermediate rent product" @@ -118,6 +118,8 @@ en: other_landlord: general_needs: "Support charge must be between £0 and £60 per week if the landlord is another RP and it is a general needs letting" supported_housing: "Support charge must be between £0 and £120 per week if the landlord is another RP and it is a suported housing letting" + brent: + not_in_range: "Basic rent is lower than expected based on the lettings type, local authority and number of bedrooms" charges: complete_1_of_3: 'Only one question out of "Total charge", "Charges for carehomes" and "Does the household pay rent or charges?" needs to be selected and completed' tcharge: diff --git a/db/migrate/20220321093810_create_la_rent_ranges.rb b/db/migrate/20220321093810_create_la_rent_ranges.rb new file mode 100644 index 000000000..a0d66842e --- /dev/null +++ b/db/migrate/20220321093810_create_la_rent_ranges.rb @@ -0,0 +1,21 @@ +class CreateLaRentRanges < ActiveRecord::Migration[7.0] + def change + create_table :la_rent_ranges do |t| + t.integer :ranges_rent_id + t.integer :needstype + t.integer :provider_type + t.string :ons_code + t.string :la + t.integer :beds + t.decimal :soft_min, precision: 10, scale: 2 + t.decimal :soft_max, precision: 10, scale: 2 + t.decimal :hard_min, precision: 10, scale: 2 + t.decimal :hard_max, precision: 10, scale: 2 + t.integer :year + t.integer :renttype + + t.index :year + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e28e022c4..7b8bf974a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -232,6 +232,24 @@ ActiveRecord::Schema[7.0].define(version: 202202071123100) do t.index ["owning_organisation_id"], name: "index_case_logs_on_owning_organisation_id" end + create_table "la_rent_ranges", force: :cascade do |t| + t.integer "ranges_rent_id" + t.integer "needstype" + t.integer "provider_type" + t.string "ons_code" + t.string "la" + t.integer "beds" + t.decimal "soft_min", precision: 10, scale: 2 + t.decimal "soft_max", precision: 10, scale: 2 + t.decimal "hard_min", precision: 10, scale: 2 + t.decimal "hard_max", precision: 10, scale: 2 + t.integer "year" + t.integer "renttype" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["year"], name: "index_la_rent_ranges_on_year" + end + create_table "organisations", force: :cascade do |t| t.string "name" t.string "phone" diff --git a/db/seeds.rb b/db/seeds.rb index 0e63f2e5a..bdb9b975d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -32,3 +32,16 @@ User.create!( ) AdminUser.create!(email: "admin@example.com", password: "password", phone: "000000000") + +LaRentRange.create!( + ranges_rent_id: "1", + lettype: "General Needs HA", + ons_code: "E07000223", + la: "Adur", + bedrooms: 1, + soft_min: 12.41, + soft_max: 89.54, + hard_min: 9.87, + hard_max: 100.99, + year: "2021", +) diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb index bc7128087..eebe22080 100644 --- a/spec/models/validations/financial_validations_spec.rb +++ b/spec/models/validations/financial_validations_spec.rb @@ -713,6 +713,67 @@ RSpec.describe Validations::FinancialValidations do expect(record.errors["household_charge"]) .to be_empty end + + context "when validating ranges based on LA and needstype" do + rent_range = LaRentRange.create!( + ranges_rent_id: "1", + needstype: "General Needs", + provider_type: "HA", + ons_code: "E07000223", + la: "Adur", + beds: 1, + soft_min: 12.41, + soft_max: 89.54, + hard_min: 9.87, + hard_max: 100.99, + year: 2021, + renttype: 1, + ) + + after do + rent_range.destroy + end + + it "validates hard minimum" do + record.needstype = 1 + record.period = 1 + record.managing_organisation.provider_type = 2 + record.la = "E07000223" + record.beds = 1 + record.year = 2021 + record.brent = 9.17 + record.renttype = 1 + + financial_validator.validate_rent_amount(record) + expect(record.errors["brent"]) + .to include(match I18n.t("validations.financial.brent.not_in_range")) + end + + it "validates hard max" do + record.needstype = 1 + record.period = 1 + record.managing_organisation.provider_type = 2 + record.la = "E07000223" + record.beds = 1 + record.year = 2021 + record.brent = 200 + record.renttype = 1 + + financial_validator.validate_rent_amount(record) + expect(record.errors["brent"]) + .to include(match I18n.t("validations.financial.brent.not_in_range")) + end + + it "does not error if some of the fields are missing" do + record.managing_organisation.provider_type = 2 + record.year = 2021 + record.brent = 200 + + financial_validator.validate_rent_amount(record) + expect(record.errors["brent"]) + .to be_empty + end + end end end end