diff --git a/app/models/case_log.rb b/app/models/case_log.rb index 8d912354b..1e59c0819 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -101,6 +101,18 @@ class CaseLogValidator < ActiveModel::Validator conditions.each { |condition| condition[:condition] ? (record.errors.add :fixed_term_tenancy, condition[:error]) : nil } end + def validate_net_income(record) + return unless record.person_1_economic_status && record.weekly_net_income + + 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" + end + + 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" + end + end + def validate_other_tenancy_type(record) validate_other_field(record, "tenancy_type", "other_tenancy_type") end @@ -182,6 +194,23 @@ class CaseLog < ApplicationRecord status == "in_progress" end + def weekly_net_income + case net_income_frequency + when "Weekly" + net_income + when "Monthly" + ((net_income * 12) / 52.0).round(0) + when "Yearly" + (net_income / 12.0).round(0) + end + end + + def applicable_income_range + return unless person_1_economic_status + + IncomeRange::ALLOWED[person_1_economic_status.to_sym] + end + private def update_status! diff --git a/app/models/income_range.rb b/app/models/income_range.rb new file mode 100644 index 000000000..b21b1fa57 --- /dev/null +++ b/app/models/income_range.rb @@ -0,0 +1,15 @@ +class IncomeRange + ALLOWED = { + "Full-time - 30 hours or more": OpenStruct.new(soft_min: 143, soft_max: 730, hard_min: 90, hard_max: 1230), + "Part-time - Less than 30 hours": OpenStruct.new(soft_min: 67, soft_max: 620, hard_min: 50, hard_max: 950), + "In government training into work, such as New Deal": OpenStruct.new(soft_min: 80, soft_max: 480, hard_min: 40, hard_max: 990), + "Jobseeker": OpenStruct.new(soft_min: 50, soft_max: 370, hard_min: 10, hard_max: 450), + "Retired": OpenStruct.new(soft_min: 50, soft_max: 380, hard_min: 10, hard_max: 690), + "Not seeking work": OpenStruct.new(soft_min: 53, soft_max: 540, hard_min: 10, hard_max: 890), + "Full-time student": OpenStruct.new(soft_min: 47, soft_max: 460, hard_min: 10, hard_max: 1300), + "Unable to work because of long term sick or disability": OpenStruct.new(soft_min: 54, soft_max: 460, hard_min: 10, hard_max: 820), + "Child under 16": OpenStruct.new(soft_min: 50, soft_max: 450, hard_min: 10, hard_max: 750), + "Other": OpenStruct.new(soft_min: 50, soft_max: 580, hard_min: 10, hard_max: 1040), + "Prefer not to say": OpenStruct.new(soft_min: 47, soft_max: 730, hard_min: 10, hard_max: 1300) + } +end diff --git a/db/migrate/20211028083105_change_net_income_type.rb b/db/migrate/20211028083105_change_net_income_type.rb new file mode 100644 index 000000000..85fedcceb --- /dev/null +++ b/db/migrate/20211028083105_change_net_income_type.rb @@ -0,0 +1,9 @@ +class ChangeNetIncomeType < ActiveRecord::Migration[6.1] + def up + change_column :case_logs, :net_income, "integer USING CAST(property_number_of_times_relet AS integer)" + end + + def down + change_column :case_logs, :net_income, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 346f047c2..e7038ce2a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_27_123535) do +ActiveRecord::Schema.define(version: 2021_10_28_083105) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -86,7 +86,7 @@ ActiveRecord::Schema.define(version: 2021_10_27_123535) do t.string "property_major_repairs_date" t.integer "property_number_of_times_relet" t.string "property_wheelchair_accessible" - t.string "net_income" + t.integer "net_income" t.string "net_income_frequency" t.string "net_income_uc_proportion" t.string "housing_benefit" diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb index d95f000a7..5d1f07918 100644 --- a/spec/models/case_log_spec.rb +++ b/spec/models/case_log_spec.rb @@ -230,6 +230,28 @@ RSpec.describe Form, type: :model do }.not_to raise_error end end + + context "income ranges" do + it "validates net income maximum" do + expect { + CaseLog.create!( + person_1_economic_status: "Full-time - 30 hours or more", + net_income: 5000, + net_income_frequency: "Weekly", + ) + }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "validates net income minimum" do + expect { + CaseLog.create!( + person_1_economic_status: "Full-time - 30 hours or more", + net_income: 1, + net_income_frequency: "Weekly", + ) + }.to raise_error(ActiveRecord::RecordInvalid) + end + end end describe "status" do @@ -248,4 +270,24 @@ RSpec.describe Form, type: :model do expect(in_progress_case_log.completed?).to be(false) end end + + describe "weekly_net_income" do + let(:net_income) { 5000 } + let(:case_log) { FactoryBot.build(:case_log, net_income: net_income) } + + it "returns input income if frequency is already weekly" do + case_log.net_income_frequency = "Weekly" + expect(case_log.weekly_net_income).to eq(net_income) + end + + it "calculates the correct weekly income from monthly income" do + case_log.net_income_frequency = "Monthly" + expect(case_log.weekly_net_income).to eq(1154) + end + + it "calculates the correct weekly income from yearly income" do + case_log.net_income_frequency = "Yearly" + expect(case_log.weekly_net_income).to eq(417) + end + end end diff --git a/spec/requests/case_log_controller_spec.rb b/spec/requests/case_log_controller_spec.rb index e6c866c90..6ddbd0130 100644 --- a/spec/requests/case_log_controller_spec.rb +++ b/spec/requests/case_log_controller_spec.rb @@ -115,6 +115,14 @@ RSpec.describe CaseLogsController, type: :request do json_response = JSON.parse(response.body) expect(json_response["status"]).to eq(case_log.status) end + + context "invalid case log id" do + let(:id) { (CaseLog.order(:id).last&.id || 0) + 1 } + + it "returns 404" do + expect(response).to have_http_status(:not_found) + end + end end describe "PATCH" do