Browse Source

CLDC-853 Added validations for sales income2 (#1101)

* CLDC-853 Added hard validations for sales income2

* CLDC-853 Added soft validation for sales income2

* CLDC-853 Fix tests broken by new code

* CLDC-853 Add new tests for new page and refactor slightly

* CLDC-853 Fix linting errors

* CLDC-853 Rename migration and update schema version

* CLDC-853 Fix broken sales income2 test

* CLDC-853 Rename migration

* CLDC-853 Move income 2 to cya card 2 and commonise combined income validation

* CLDC-853 Actually use the validate_combined_income method

* combine duplicate methods after rebase, ensure hard validations are triggered on all relevant fields

* move validation on child income to financial validations to stop it being triggered on lettings logs, minor amendments to tests broken by changes

* revamp financial validations tests against income to reflect updates

* amend child income validation to reflect specifications and write tests to cover this validation

* correct linting errors and play a little code golf

* change copy for some validations, add sales log method and amend interruption screen helper to support this

* extract duplicate code to private method

* update buyer 1 and 2 income value check to be consistent

* remove ecstat from income checks, the only ecstat we care about is child which is dealt with elsewhere

* rename constant struct with same anme as existing variable

* amend tests to reflect the chagnes in validations and copy

* enable currency formatting of numbers for inserting into informative_text or title_text

* update evil test in form handler spec

* rebase and fix conflicts and tests

* change a variable name and correct minor rebase errors

* update interruption screen helper tests

* correct linting errors, minor test failure and typo

* add tests for new sales log method for formatting currency

* fix merge conflicts

---------

Co-authored-by: Arthur Campbell <arfa.camble@gmail.com>
pull/1336/head
David May-Miller 2 years ago committed by GitHub
parent
commit
4a31906d45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      app/helpers/interruption_screen_helper.rb
  2. 6
      app/models/form/sales/pages/about_price_shared_ownership_value_check.rb
  3. 15
      app/models/form/sales/pages/buyer1_income_value_check.rb
  4. 35
      app/models/form/sales/pages/buyer2_income_value_check.rb
  5. 2
      app/models/form/sales/questions/buyer1_income_value_check.rb
  6. 1
      app/models/form/sales/questions/buyer2_income.rb
  7. 25
      app/models/form/sales/questions/buyer2_income_value_check.rb
  8. 3
      app/models/form/sales/subsections/household_characteristics.rb
  9. 1
      app/models/form/sales/subsections/income_benefits_and_savings.rb
  10. 4
      app/models/log.rb
  11. 18
      app/models/sales_log.rb
  12. 63
      app/models/validations/sales/financial_validations.rb
  13. 12
      app/models/validations/sales/soft_validations.rb
  14. 12
      config/locales/en.yml
  15. 5
      db/migrate/20230105103134_add_income2_value_check.rb
  16. 1
      db/schema.rb
  17. 53
      spec/helpers/interruption_screen_helper_spec.rb
  18. 2
      spec/models/form/sales/questions/buyer1_income_value_check_spec.rb
  19. 6
      spec/models/form/sales/subsections/household_characteristics_spec.rb
  20. 2
      spec/models/form/sales/subsections/income_benefits_and_savings_spec.rb
  21. 4
      spec/models/form_handler_spec.rb
  22. 23
      spec/models/sales_log_spec.rb
  23. 222
      spec/models/validations/sales/financial_validations_spec.rb

33
app/helpers/interruption_screen_helper.rb

@ -1,17 +1,10 @@
module InterruptionScreenHelper
def display_informative_text(informative_text, lettings_log)
def display_informative_text(informative_text, log)
return "" unless informative_text["arguments"]
translation_params = {}
informative_text["arguments"].each do |argument|
value = if argument["label"]
pre_casing_value = lettings_log.form.get_question(argument["key"], lettings_log).answer_label(lettings_log)
pre_casing_value.downcase
elsif argument["currency"]
number_to_currency(lettings_log.public_send(argument["key"]), delimiter: ",", format: "%n", unit: "£")
else
lettings_log.public_send(argument["key"])
end
value = get_value_from_argument(log, argument)
translation_params[argument["i18n_template"].to_sym] = value
end
@ -24,21 +17,27 @@ module InterruptionScreenHelper
end
end
def display_title_text(title_text, lettings_log)
def display_title_text(title_text, log)
return "" if title_text.nil?
translation_params = {}
arguments = title_text["arguments"] || {}
arguments.each do |argument|
value = if argument["label"]
lettings_log.form.get_question(argument["key"], lettings_log).answer_label(lettings_log).downcase
elsif argument["currency"]
number_to_currency(lettings_log.public_send(argument["key"]), delimiter: ",", format: "%n", unit: "£")
else
lettings_log.public_send(argument["key"])
end
value = get_value_from_argument(log, argument)
translation_params[argument["i18n_template"].to_sym] = value
end
I18n.t(title_text["translation"], **translation_params).to_s
end
private
def get_value_from_argument(log, argument)
if argument["label"]
log.form.get_question(argument["key"], log).answer_label(log).downcase
elsif argument["arguments_for_key"]
log.public_send(argument["key"], argument["arguments_for_key"])
else
log.public_send(argument["key"])
end
end
end

6
app/models/form/sales/pages/about_price_shared_ownership_value_check.rb

@ -20,14 +20,12 @@ class Form::Sales::Pages::AboutPriceSharedOwnershipValueCheck < ::Form::Page
"translation" => "soft_validations.purchase_price.hint_text",
"arguments" => [
{
"key" => "purchase_price_soft_min_or_soft_max",
"label" => false,
"key" => "field_formatted_as_currency",
"arguments_for_key" => "purchase_price_soft_min_or_soft_max",
"i18n_template" => "soft_min_or_soft_max",
"currency" => true,
},
{
"key" => "purchase_price_min_or_max_text",
"label" => false,
"i18n_template" => "min_or_max",
},
],

15
app/models/form/sales/pages/buyer1_income_value_check.rb

@ -6,6 +6,21 @@ class Form::Sales::Pages::Buyer1IncomeValueCheck < ::Form::Page
"income1_under_soft_min?" => true,
},
]
@title_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status",
"arguments" => [
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "income1",
"i18n_template" => "income",
},
{
"key" => "income_soft_min_for_ecstat",
"arguments_for_key" => "ecstat1",
"i18n_template" => "minimum",
},
],
}
@informative_text = {}
end

35
app/models/form/sales/pages/buyer2_income_value_check.rb

@ -0,0 +1,35 @@
class Form::Sales::Pages::Buyer2IncomeValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super
@header = ""
@description = ""
@subsection = subsection
@depends_on = [
{
"income2_under_soft_min?" => true,
},
]
@title_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status",
"arguments" => [
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "income2",
"i18n_template" => "income",
},
{
"key" => "income_soft_min_for_ecstat",
"arguments_for_key" => "ecstat2",
"i18n_template" => "minimum",
},
],
}
@informative_text = {}
end
def questions
@questions ||= [
Form::Sales::Questions::Buyer2IncomeValueCheck.new(nil, nil, self),
]
end
end

2
app/models/form/sales/questions/buyer1_income_value_check.rb

@ -3,7 +3,7 @@ class Form::Sales::Questions::Buyer1IncomeValueCheck < ::Form::Question
super
@id = "income1_value_check"
@check_answer_label = "Income confirmation"
@header = "Are you sure this income is correct?"
@header = "Are you sure this is correct?"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

1
app/models/form/sales/questions/buyer2_income.rb

@ -7,6 +7,7 @@ class Form::Sales::Questions::Buyer2Income < ::Form::Question
@type = "numeric"
@hint_text = "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
@min = 0
@max = 999_999
@step = 1
@width = 5
@prefix = "£"

25
app/models/form/sales/questions/buyer2_income_value_check.rb

@ -0,0 +1,25 @@
class Form::Sales::Questions::Buyer2IncomeValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "income2_value_check"
@check_answer_label = "Income confirmation"
@header = "Are you sure this is correct?"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
}
@hidden_in_check_answers = {
"depends_on" => [
{
"income2_value_check" => 0,
},
{
"income2_value_check" => 1,
},
],
}
@check_answers_card_number = 2
@page = page
end
end

3
app/models/form/sales/subsections/household_characteristics.rb

@ -34,7 +34,8 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::RetirementValueCheck.new("gender_2_buyer_retirement_value_check", nil, self, person_index: 2),
ethnic_pages_for_buyer_2,
Form::Sales::Pages::Buyer2WorkingSituation.new(nil, nil, self),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_buyer_retirement_value_check", nil, self, person_index: 2),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check_joint_purchase", nil, self, person_index: 2),
Form::Sales::Pages::Buyer2IncomeValueCheck.new("working_situation_buyer_2_income_value_check", nil, self),
Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::NumberOfOthersInProperty.new(nil, nil, self),
Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 2),

1
app/models/form/sales/subsections/income_benefits_and_savings.rb

@ -15,6 +15,7 @@ class Form::Sales::Subsections::IncomeBenefitsAndSavings < ::Form::Subsection
Form::Sales::Pages::MortgageValueCheck.new("buyer_1_mortgage_value_check", nil, self, 1),
Form::Sales::Pages::Buyer2Income.new(nil, nil, self),
Form::Sales::Pages::MortgageValueCheck.new("buyer_2_income_mortgage_value_check", nil, self, 2),
Form::Sales::Pages::Buyer2IncomeValueCheck.new("buyer_2_income_value_check", nil, self),
Form::Sales::Pages::Buyer2Mortgage.new(nil, nil, self),
Form::Sales::Pages::MortgageValueCheck.new("buyer_2_mortgage_value_check", nil, self, 2),
Form::Sales::Pages::HousingBenefits.new(nil, nil, self),

4
app/models/log.rb

@ -147,4 +147,8 @@ private
self[is_inferred_key] = false
self[postcode_key] = nil
end
def format_as_currency(num_string)
ActionController::Base.helpers.number_to_currency(num_string, unit: "£")
end
end

18
app/models/sales_log.rb

@ -124,6 +124,10 @@ class SalesLog < Log
la && LONDON_BOROUGHS.include?(la)
end
def property_not_in_london?
!london_property?
end
def income1_used_for_mortgage?
inc1mort == 1
end
@ -256,4 +260,18 @@ class SalesLog < Log
def purchase_price_soft_max
LaSaleRange.find_by(start_year: collection_start_year, la:, bedrooms: beds).soft_max
end
def income_soft_min_for_ecstat(ecstat_field)
economic_status_code = public_send(ecstat_field)
return unless ALLOWED_INCOME_RANGES_SALES
soft_min = ALLOWED_INCOME_RANGES_SALES[economic_status_code]&.soft_min
format_as_currency(soft_min)
end
def field_formatted_as_currency(field_name)
field_value = public_send(field_name)
format_as_currency(field_value)
end
end

63
app/models/validations/sales/financial_validations.rb

@ -3,20 +3,36 @@ module Validations::Sales::FinancialValidations
# or 'validate_' to run on submit as well
def validate_income1(record)
if record.ecstat1 && record.income1 && record.la && record.ownershipsch == 1
if record.london_property?
record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :ecstat1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :ownershipsch, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :la, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :postcode_full, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
elsif record.income1 > 80_000
record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :ecstat1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :ownershipsch, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :la, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000) if record.income1 > 80_000
record.errors.add :postcode_full, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000) if record.income1 > 80_000
end
return unless record.income1 && record.la && record.shared_ownership_scheme?
relevant_fields = %i[income1 ownershipsch la postcode_full]
if record.london_property? && record.income1 > 90_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_london") }
elsif record.property_not_in_london? && record.income1 > 80_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_outside_london") }
end
end
def validate_income2(record)
return unless record.income2 && record.la && record.shared_ownership_scheme?
relevant_fields = %i[income2 ownershipsch la postcode_full]
if record.london_property? && record.income2 > 90_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_london") }
elsif record.property_not_in_london? && record.income2 > 80_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.over_hard_max_for_outside_london") }
end
end
def validate_combined_income(record)
return unless record.income1 && record.income2 && record.la && record.shared_ownership_scheme?
combined_income = record.income1 + record.income2
relevant_fields = %i[income1 income2 ownershipsch la postcode_full]
if record.london_property? && combined_income > 90_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.combined_over_hard_max_for_london") }
elsif record.property_not_in_london? && combined_income > 80_000
relevant_fields.each { |field| record.errors.add field, I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london") }
end
end
@ -36,6 +52,15 @@ module Validations::Sales::FinancialValidations
end
end
def validate_child_income(record)
return unless record.income2 && record.ecstat2
if record.income2.positive? && is_economic_status_child?(record.ecstat2)
record.errors.add :ecstat2, I18n.t("validations.financial.income.child_has_income")
record.errors.add :income2, I18n.t("validations.financial.income.child_has_income")
end
end
def validate_percentage_owned_not_too_much_if_older_person(record)
return unless record.old_persons_shared_ownership? && record.stairowned
@ -44,4 +69,14 @@ module Validations::Sales::FinancialValidations
record.errors.add :type, I18n.t("validations.financial.staircasing.older_person_percentage_owned_maximum_75")
end
end
private
def is_relationship_child?(relationship)
relationship == "C"
end
def is_economic_status_child?(economic_status)
economic_status == 9
end
end

12
app/models/validations/sales/soft_validations.rb

@ -1,5 +1,5 @@
module Validations::Sales::SoftValidations
ALLOWED_INCOME_RANGES = {
ALLOWED_INCOME_RANGES_SALES = {
1 => OpenStruct.new(soft_min: 5000),
2 => OpenStruct.new(soft_min: 1500),
3 => OpenStruct.new(soft_min: 1000),
@ -8,9 +8,15 @@ module Validations::Sales::SoftValidations
}.freeze
def income1_under_soft_min?
return false unless ecstat1 && income1 && ALLOWED_INCOME_RANGES[ecstat1]
return false unless ecstat1 && income1 && ALLOWED_INCOME_RANGES_SALES[ecstat1]
income1 < ALLOWED_INCOME_RANGES[ecstat1][:soft_min]
income1 < ALLOWED_INCOME_RANGES_SALES[ecstat1][:soft_min]
end
def income2_under_soft_min?
return false unless ecstat2 && income2 && ALLOWED_INCOME_RANGES_SALES[ecstat2]
income2 < ALLOWED_INCOME_RANGES_SALES[ecstat2][:soft_min]
end
def staircase_bought_above_fifty?

12
config/locales/en.yml

@ -223,8 +223,12 @@ en:
under_hard_min: "Net income cannot be less than £%{hard_min} per week given the tenant’s working situation"
freq_missing: "Select how often the household receives income"
earnings_missing: "Enter how much income the household has in total"
income1:
over_hard_max: "Income must be lower than £%{hard_max}"
income:
over_hard_max_for_london: "Income must not exceed £90,000 for properties within London local authorities"
over_hard_max_for_outside_london: "Income must not exceed £80,000 for properties outside London local authorities"
combined_over_hard_max_for_london: "Combined income must not exceed £90,000 for properties within London local authorities"
combined_over_hard_max_for_outside_london: "Combined income must not exceed £80,000 for properties outside London local authorities"
child_has_income: "Child's income must be £0"
negative_currency: "Enter an amount above 0"
rent:
less_than_shortfall: "Enter an amount that is more than the shortfall in basic rent"
@ -467,6 +471,8 @@ en:
message: "Net income is lower than expected based on the lead tenant’s working situation. Are you sure this is correct?"
in_soft_max_range:
message: "Net income is higher than expected based on the lead tenant’s working situation. Are you sure this is correct?"
income:
under_soft_min_for_economic_status: "You said income was %{income}, which is below this working situation's minimum (%{minimum})"
rent:
outside_range_title: "You told us the rent is %{brent}"
min_hint_text: "The minimum rent expected for this type of property in this local authority is £%{soft_min_for_period}."
@ -559,4 +565,4 @@ en:
one_argument: "This is based on the tenant’s work situation: %{ecstat1}"
title_text:
no_argument: "Some test text"
one_argument: "You said this: %{ecstat1}"
one_argument: "You said this: %{argument}"

5
db/migrate/20230105103134_add_income2_value_check.rb

@ -0,0 +1,5 @@
class AddIncome2ValueCheck < ActiveRecord::Migration[7.0]
def change
add_column :sales_logs, :income2_value_check, :integer
end
end

1
db/schema.rb

@ -520,6 +520,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_10_143120) do
t.integer "value_value_check"
t.integer "old_persons_shared_ownership_value_check"
t.integer "staircase_bought_value_check"
t.integer "income2_value_check"
t.integer "monthly_charges_value_check"
t.integer "details_known_5"
t.integer "details_known_6"

53
spec/helpers/interruption_screen_helper_spec.rb

@ -13,6 +13,7 @@ RSpec.describe InterruptionScreenHelper do
earnings: 750,
incfreq: 1,
created_by: user,
sex1: "F",
)
end
@ -94,6 +95,54 @@ RSpec.describe InterruptionScreenHelper do
.to eq("")
end
end
context "when an argument is given not for a label" do
translation = "test.title_text.one_argument"
it "returns the correct text" do
informative_text_hash = {
"translation" => translation,
"arguments" => [
{
"key" => "earnings",
"i18n_template" => "argument",
},
],
}
expect(display_informative_text(informative_text_hash, lettings_log)).to eq(I18n.t(translation, argument: lettings_log.earnings))
end
end
context "when and argument is given with a key and arguments for the key" do
it "makes the correct method call" do
informative_text_hash = {
"arguments" => [
{
"key" => "retirement_age_for_person",
"arguments_for_key" => 1,
"i18n_template" => "argument",
},
],
}
allow(lettings_log).to receive(:retirement_age_for_person)
display_informative_text(informative_text_hash, lettings_log)
expect(lettings_log).to have_received(:retirement_age_for_person).with(1)
end
it "returns the correct text" do
translation = "test.title_text.one_argument"
informative_text_hash = {
"translation" => translation,
"arguments" => [
{
"key" => "retirement_age_for_person",
"arguments_for_key" => 1,
"i18n_template" => "argument",
},
],
}
expect(display_informative_text(informative_text_hash, lettings_log)).to eq(I18n.t(translation, argument: lettings_log.retirement_age_for_person(1)))
end
end
end
describe "display_title_text" do
@ -113,12 +162,12 @@ RSpec.describe InterruptionScreenHelper do
{
"key" => "ecstat1",
"label" => true,
"i18n_template" => "ecstat1",
"i18n_template" => "argument",
},
],
}
expect(display_title_text(title_text, lettings_log))
.to eq(I18n.t("test.title_text.one_argument", ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase))
.to eq(I18n.t("test.title_text.one_argument", argument: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase))
end
end

2
spec/models/form/sales/questions/buyer1_income_value_check_spec.rb

@ -16,7 +16,7 @@ RSpec.describe Form::Sales::Questions::Buyer1IncomeValueCheck, type: :model do
end
it "has the correct header" do
expect(question.header).to eq("Are you sure this income is correct?")
expect(question.header).to eq("Are you sure this is correct?")
end
it "has the correct check_answer_label" do

6
spec/models/form/sales/subsections/household_characteristics_spec.rb

@ -46,7 +46,8 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_2_gender_identity
gender_2_buyer_retirement_value_check
buyer_2_working_situation
working_situation_2_buyer_retirement_value_check
working_situation_2_retirement_value_check_joint_purchase
working_situation_buyer_2_income_value_check
buyer_2_live_in_property
number_of_others_in_property
person_2_known
@ -126,7 +127,8 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_2_ethnic_background_mixed
buyer_2_ethnic_background_white
buyer_2_working_situation
working_situation_2_buyer_retirement_value_check
working_situation_2_retirement_value_check_joint_purchase
working_situation_buyer_2_income_value_check
buyer_2_live_in_property
number_of_others_in_property
person_2_known

2
spec/models/form/sales/subsections/income_benefits_and_savings_spec.rb

@ -27,6 +27,7 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
buyer_1_mortgage_value_check
buyer_2_income
buyer_2_income_mortgage_value_check
buyer_2_income_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
housing_benefits
@ -52,6 +53,7 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
buyer_1_mortgage_value_check
buyer_2_income
buyer_2_income_mortgage_value_check
buyer_2_income_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
housing_benefits

4
spec/models/form_handler_spec.rb

@ -54,14 +54,14 @@ RSpec.describe FormHandler do
it "is able to load a current sales form" do
form = form_handler.get_form("current_sales")
expect(form).to be_a(Form)
expect(form.pages.count).to eq(179)
expect(form.pages.count).to eq(181)
expect(form.name).to eq("2022_2023_sales")
end
it "is able to load a previous sales form" do
form = form_handler.get_form("previous_sales")
expect(form).to be_a(Form)
expect(form.pages.count).to eq(179)
expect(form.pages.count).to eq(181)
expect(form.name).to eq("2021_2022_sales")
end
end

23
spec/models/sales_log_spec.rb

@ -266,6 +266,7 @@ RSpec.describe SalesLog, type: :model do
relat4: "X",
relat5: "X",
relat6: "P",
income2: 0,
ecstat2: 9,
ecstat3: 7,
age1: 47,
@ -370,4 +371,26 @@ RSpec.describe SalesLog, type: :model do
expect(completed_sales_log.expected_shared_ownership_deposit_value).to eq(500)
end
end
describe "#field_formatted_as_currency" do
let(:completed_sales_log) { FactoryBot.create(:sales_log, :completed) }
it "returns small numbers correctly formatted as currency" do
completed_sales_log.update!(savings: 4)
expect(completed_sales_log.field_formatted_as_currency("savings")).to eq("£4.00")
end
it "returns quite large numbers correctly formatted as currency" do
completed_sales_log.update!(savings: 40_000)
expect(completed_sales_log.field_formatted_as_currency("savings")).to eq("£40,000.00")
end
it "returns very large numbers correctly formatted as currency" do
completed_sales_log.update!(savings: 400_000_000)
expect(completed_sales_log.field_formatted_as_currency("savings")).to eq("£400,000,000.00")
end
end
end

222
spec/models/validations/sales/financial_validations_spec.rb

@ -5,75 +5,110 @@ RSpec.describe Validations::Sales::FinancialValidations do
let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } }
describe "income validations" do
let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1, la: "E08000035") }
context "with shared ownership" do
context "and non london borough" do
(0..8).each do |ecstat|
it "adds an error when buyer 1 income is over hard max for ecstat #{ecstat}" do
record.income1 = 85_000
record.ecstat1 = ecstat
financial_validator.validate_income1(record)
expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["ecstat1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["ownershipsch"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["la"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["postcode_full"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
end
end
it "validates that the income is within the expected range for the tenant’s employment status" do
record.income1 = 75_000
record.ecstat1 = 1
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty
expect(record.errors["ecstat1"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
expect(record.errors["la"]).to be_empty
expect(record.errors["postcode_full"]).to be_empty
end
end
context "and a london borough" do
before do
record.update!(la: "E09000030")
record.reload
end
(0..8).each do |ecstat|
it "adds an error when buyer 1 income is over hard max for ecstat #{ecstat}" do
record.income1 = 95_000
record.ecstat1 = ecstat
financial_validator.validate_income1(record)
expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["ecstat1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["ownershipsch"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["la"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["postcode_full"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
end
end
it "validates that the income is within the expected range for the tenant’s employment status" do
record.income1 = 85_000
record.ecstat1 = 1
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty
expect(record.errors["ecstat1"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
expect(record.errors["la"]).to be_empty
expect(record.errors["postcode_full"]).to be_empty
end
describe "income validations for shared ownership" do
let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1) }
context "when buying in a non london borough" do
before do
record.update!(la: "E08000035")
record.reload
end
it "adds errors if buyer 1 has income over 80,000" do
record.income1 = 85_000
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
end
it "adds errors if buyer 2 has income over 80,000" do
record.income2 = 85_000
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_outside_london"))
end
it "does not add errors if buyer 1 has income below 80_000" do
record.income1 = 75_000
financial_validator.validate_income1(record)
expect(record.errors).to be_empty
end
it "does not add errors if buyer 2 has income below 80_000" do
record.income2 = 75_000
financial_validator.validate_income2(record)
expect(record.errors).to be_empty
end
it "adds errors when combined income is over 80_000" do
record.income1 = 45_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london"))
end
it "does not add errors when combined income is under 80_000" do
record.income1 = 35_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors).to be_empty
end
end
context "when buying in a london borough" do
before do
record.update!(la: "E09000030")
record.reload
end
it "adds errors if buyer 1 has income over 90,000" do
record.income1 = 95_000
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
end
it "adds errors if buyer 2 has income over 90,000" do
record.income2 = 95_000
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.over_hard_max_for_london"))
end
it "does not add errors if buyer 1 has income below 90_000" do
record.income1 = 75_000
financial_validator.validate_income1(record)
expect(record.errors).to be_empty
end
it "does not add errors if buyer 2 has income below 90_000" do
record.income2 = 75_000
financial_validator.validate_income2(record)
expect(record.errors).to be_empty
end
it "adds errors when combined income is over 90_000" do
record.income1 = 55_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london"))
end
it "does not add errors when combined income is under 90_000" do
record.income1 = 35_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors).to be_empty
end
end
end
@ -96,7 +131,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "does not add an error if the cash discount is in the expected range" do
record.cashdis = 10_000
financial_validator.validate_cash_discount(record)
expect(record.errors["cashdis"]).to be_empty
expect(record.errors).to be_empty
end
end
@ -107,16 +142,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = 20
record.stairowned = 40
financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record)
expect(record.errors["stairbought"]).to be_empty
expect(record.errors["stairowned"]).to be_empty
expect(record.errors).to be_empty
end
it "does not add an error if the percentage bought is equal to the percentage owned" do
record.stairbought = 30
record.stairowned = 30
financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record)
expect(record.errors["stairbought"]).to be_empty
expect(record.errors["stairowned"]).to be_empty
expect(record.errors).to be_empty
end
it "adds an error to stairowned and not stairbought if the percentage bought is more than the percentage owned" do
@ -135,8 +168,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 2
record.stairowned = 80
financial_validator.validate_percentage_owned_not_too_much_if_older_person(record)
expect(record.errors["stairowned"]).to be_empty
expect(record.errors["type"]).to be_empty
expect(record.errors).to be_empty
end
end
@ -145,8 +177,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 24
record.stairowned = 50
financial_validator.validate_percentage_owned_not_too_much_if_older_person(record)
expect(record.errors["stairowned"]).to be_empty
expect(record.errors["type"]).to be_empty
expect(record.errors).to be_empty
end
it "adds an error when percentage owned after staircasing transaction exceeds 75%" do
@ -158,4 +189,39 @@ RSpec.describe Validations::Sales::FinancialValidations do
end
end
end
describe "#validate_child_income" do
let(:record) { FactoryBot.create(:sales_log) }
context "when buyer 2 is not a child" do
before do
record.update!(ecstat2: rand(0..8))
record.reload
end
it "does not add an error if buyer 2 has an income" do
record.ecstat2 = rand(0..8)
record.income2 = 40_000
financial_validator.validate_child_income(record)
expect(record.errors).to be_empty
end
end
context "when buyer 2 is a child" do
it "does not add an error if buyer 2 has no income" do
record.ecstat2 = 9
record.income2 = 0
financial_validator.validate_child_income(record)
expect(record.errors).to be_empty
end
it "adds errors if buyer 2 has an income" do
record.ecstat2 = 9
record.income2 = 40_000
financial_validator.validate_child_income(record)
expect(record.errors["ecstat2"]).to include(match I18n.t("validations.financial.income.child_has_income"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.child_has_income"))
end
end
end
end

Loading…
Cancel
Save