Browse Source

CLDC-3753: Update soft income validations (#2779)

* CLDC-3753: Update soft income validations

* Update tests

* Fix linting

* Include reference to informative text translations copy

* Combine min and max checks for income based on ecstat

* Fixes

* Update tests
pull/2828/head^2
Rachael Booth 2 months ago committed by GitHub
parent
commit
b3dca51216
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      app/models/form/sales/pages/buyer1_income_discounted_max_value_check.rb
  2. 18
      app/models/form/sales/pages/buyer1_income_ecstat_value_check.rb
  3. 6
      app/models/form/sales/pages/buyer2_income_discounted_max_value_check.rb
  4. 18
      app/models/form/sales/pages/buyer2_income_ecstat_value_check.rb
  5. 2
      app/models/form/sales/pages/combined_income_max_value_check.rb
  6. 4
      app/models/form/sales/subsections/household_characteristics.rb
  7. 8
      app/models/form/sales/subsections/income_benefits_and_savings.rb
  8. 8
      app/models/form/sales/subsections/property_information.rb
  9. 77
      app/models/validations/sales/soft_validations.rb
  10. 8
      config/locales/forms/2023/sales/soft_validations.en.yml
  11. 12
      config/locales/forms/2024/sales/soft_validations.en.yml
  12. 22
      config/locales/forms/2025/sales/soft_validations.en.yml
  13. 4
      spec/models/form/sales/pages/buyer1_income_discounted_max_value_check_spec.rb
  14. 8
      spec/models/form/sales/pages/buyer1_income_ecstat_value_check_spec.rb
  15. 4
      spec/models/form/sales/pages/buyer2_income_discounted_max_value_check_spec.rb
  16. 8
      spec/models/form/sales/pages/buyer2_income_ecstat_value_check_spec.rb
  17. 2
      spec/models/form/sales/pages/combined_income_max_value_check_spec.rb
  18. 130
      spec/models/form/sales/subsections/household_characteristics_spec.rb
  19. 47
      spec/models/form/sales/subsections/income_benefits_and_savings_spec.rb
  20. 275
      spec/models/validations/sales/soft_validations_spec.rb
  21. 4
      spec/services/documentation_generator_spec.rb

6
app/models/form/sales/pages/buyer1_income_max_value_check.rb → app/models/form/sales/pages/buyer1_income_discounted_max_value_check.rb

@ -1,12 +1,12 @@
class Form::Sales::Pages::Buyer1IncomeMaxValueCheck < ::Form::Page
class Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck < ::Form::Page
def initialize(id, hsh, subsection, check_answers_card_number:)
super(id, hsh, subsection)
@depends_on = [
{
"income1_over_soft_max?" => true,
"income1_over_soft_max_for_discounted_ownership?" => true,
},
]
@copy_key = "sales.soft_validations.income1_value_check.max"
@copy_key = "sales.soft_validations.income1_value_check.discounted"
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [

18
app/models/form/sales/pages/buyer1_income_min_value_check.rb → app/models/form/sales/pages/buyer1_income_ecstat_value_check.rb

@ -1,12 +1,12 @@
class Form::Sales::Pages::Buyer1IncomeMinValueCheck < ::Form::Page
class Form::Sales::Pages::Buyer1IncomeEcstatValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super
@depends_on = [
{
"income1_under_soft_min?" => true,
"income1_outside_soft_range_for_ecstat?" => true,
},
]
@copy_key = "sales.soft_validations.income1_value_check.min"
@copy_key = "sales.soft_validations.income1_value_check.ecstat"
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
@ -15,16 +15,16 @@ class Form::Sales::Pages::Buyer1IncomeMinValueCheck < ::Form::Page
"arguments_for_key" => "income1",
"i18n_template" => "income",
},
{
"key" => "income_soft_min_for_ecstat",
"arguments_for_key" => "ecstat1",
"i18n_template" => "minimum",
},
],
}
@informative_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
"arguments" => [
{
"key" => "income1_more_or_less_text",
"i18n_template" => "more_or_less",
},
],
}
end

6
app/models/form/sales/pages/buyer2_income_max_value_check.rb → app/models/form/sales/pages/buyer2_income_discounted_max_value_check.rb

@ -1,12 +1,12 @@
class Form::Sales::Pages::Buyer2IncomeMaxValueCheck < ::Form::Page
class Form::Sales::Pages::Buyer2IncomeDiscountedMaxValueCheck < ::Form::Page
def initialize(id, hsh, subsection, check_answers_card_number:)
super(id, hsh, subsection)
@depends_on = [
{
"income2_over_soft_max?" => true,
"income2_over_soft_max_for_discounted_ownership?" => true,
},
]
@copy_key = "sales.soft_validations.income2_value_check.max"
@copy_key = "sales.soft_validations.income2_value_check.discounted"
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [

18
app/models/form/sales/pages/buyer2_income_min_value_check.rb → app/models/form/sales/pages/buyer2_income_ecstat_value_check.rb

@ -1,12 +1,12 @@
class Form::Sales::Pages::Buyer2IncomeMinValueCheck < ::Form::Page
class Form::Sales::Pages::Buyer2IncomeEcstatValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super
@depends_on = [
{
"income2_under_soft_min?" => true,
"income2_outside_soft_range_for_ecstat?" => true,
},
]
@copy_key = "sales.soft_validations.income2_value_check.min"
@copy_key = "sales.soft_validations.income2_value_check.ecstat"
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
@ -15,16 +15,16 @@ class Form::Sales::Pages::Buyer2IncomeMinValueCheck < ::Form::Page
"arguments_for_key" => "income2",
"i18n_template" => "income",
},
{
"key" => "income_soft_min_for_ecstat",
"arguments_for_key" => "ecstat2",
"i18n_template" => "minimum",
},
],
}
@informative_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
"arguments" => [
{
"key" => "income2_more_or_less_text",
"i18n_template" => "more_or_less",
},
],
}
end

2
app/models/form/sales/pages/combined_income_max_value_check.rb

@ -3,7 +3,7 @@ class Form::Sales::Pages::CombinedIncomeMaxValueCheck < ::Form::Page
super(id, hsh, subsection)
@depends_on = [
{
"combined_income_over_soft_max?" => true,
"combined_income_over_soft_max_for_discounted_ownership?" => true,
},
]
@copy_key = "sales.soft_validations.combined_income_value_check"

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

@ -35,7 +35,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::Buyer1WorkingSituation.new(nil, nil, self),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_1_retirement_value_check", nil, self, person_index: 1),
(Form::Sales::Pages::NotRetiredValueCheck.new("working_situation_1_not_retired_value_check", nil, self, person_index: 1) if form.start_year_2024_or_later?),
Form::Sales::Pages::Buyer1IncomeMinValueCheck.new("working_situation_buyer_1_income_min_value_check", nil, self),
Form::Sales::Pages::Buyer1IncomeEcstatValueCheck.new("working_situation_buyer_1_income_value_check", nil, self),
Form::Sales::Pages::Buyer1LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_1_live_in_property_value_check", nil, self, person_index: 1),
(form.start_year_2025_or_later? ? Form::Sales::Pages::Buyer2RelationshipToBuyer1YesNo.new(nil, nil, self) : Form::Sales::Pages::Buyer2RelationshipToBuyer1.new(nil, nil, self)),
@ -51,7 +51,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::Buyer2WorkingSituation.new(nil, nil, self),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check_joint_purchase", nil, self, person_index: 2),
(Form::Sales::Pages::NotRetiredValueCheck.new("working_situation_2_not_retired_value_check_joint_purchase", nil, self, person_index: 2) if form.start_year_2024_or_later?),
Form::Sales::Pages::Buyer2IncomeMinValueCheck.new("working_situation_buyer_2_income_min_value_check", nil, self),
Form::Sales::Pages::Buyer2IncomeEcstatValueCheck.new("working_situation_buyer_2_income_value_check", nil, self),
Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_working_situation_student_not_child_value_check", nil, self, person_index: 2),
Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_2_live_in_property_value_check", nil, self, person_index: 2),

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

@ -16,16 +16,16 @@ class Form::Sales::Subsections::IncomeBenefitsAndSavings < ::Form::Subsection
def pages
@pages ||= [
Form::Sales::Pages::Buyer1Income.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMinValueCheck.new("buyer_1_income_min_value_check", nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("buyer_1_income_max_value_check", nil, self, check_answers_card_number: 1),
Form::Sales::Pages::Buyer1IncomeEcstatValueCheck.new("buyer_1_income_ecstat_value_check", nil, self),
Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck.new("buyer_1_income_discounted_max_value_check", nil, self, check_answers_card_number: 1),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("buyer_1_combined_income_max_value_check", nil, self, check_answers_card_number: 1),
Form::Sales::Pages::MortgageValueCheck.new("buyer_1_income_mortgage_value_check", nil, self, 1),
Form::Sales::Pages::Buyer1Mortgage.new(nil, nil, self),
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::Buyer2IncomeMinValueCheck.new("buyer_2_income_min_value_check", nil, self),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("buyer_2_income_max_value_check", nil, self, check_answers_card_number: 2),
Form::Sales::Pages::Buyer2IncomeEcstatValueCheck.new("buyer_2_income_ecstat_value_check", nil, self),
Form::Sales::Pages::Buyer2IncomeDiscountedMaxValueCheck.new("buyer_2_income_discounted_max_value_check", nil, self, check_answers_card_number: 2),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("buyer_2_combined_income_max_value_check", nil, self, check_answers_card_number: 2),
Form::Sales::Pages::Buyer2Mortgage.new(nil, nil, self),
Form::Sales::Pages::MortgageValueCheck.new("buyer_2_mortgage_value_check", nil, self, 2),

8
app/models/form/sales/subsections/property_information.rb

@ -31,8 +31,8 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
Form::Sales::Pages::UprnSelection.new(nil, nil, self),
Form::Sales::Pages::AddressFallback.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeDiscountedMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("local_authority_combined_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
]
@ -42,8 +42,8 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::Address.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::Buyer1IncomeMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck.new("local_authority_buyer_1_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::Buyer2IncomeDiscountedMaxValueCheck.new("local_authority_buyer_2_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::CombinedIncomeMaxValueCheck.new("local_authority_combined_income_max_value_check", nil, self, check_answers_card_number: nil),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
]

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

@ -2,41 +2,59 @@ module Validations::Sales::SoftValidations
include Validations::Sales::SaleInformationValidations
ALLOWED_INCOME_RANGES_SALES = {
2024 => {
1 => OpenStruct.new(soft_min: 5000),
2 => OpenStruct.new(soft_min: 1500),
3 => OpenStruct.new(soft_min: 1000),
5 => OpenStruct.new(soft_min: 2000),
0 => OpenStruct.new(soft_min: 2000),
},
2025 => {
1 => OpenStruct.new(soft_min: 13_400, soft_max: 150_000),
2 => OpenStruct.new(soft_min: 2_600, soft_max: 80_000),
3 => OpenStruct.new(soft_min: 2_080, soft_max: 30_000),
4 => OpenStruct.new(soft_min: 520, soft_max: 23_400),
5 => OpenStruct.new(soft_min: 520, soft_max: 80_000),
6 => OpenStruct.new(soft_min: 520, soft_max: 50_000),
7 => OpenStruct.new(soft_min: 520, soft_max: 30_000),
8 => OpenStruct.new(soft_min: 520, soft_max: 150_000),
9 => OpenStruct.new(soft_min: 520, soft_max: 150_000),
0 => OpenStruct.new(soft_min: 520, soft_max: 150_000),
},
}.freeze
def income1_under_soft_min?
return false unless ecstat1 && income1 && ALLOWED_INCOME_RANGES_SALES[ecstat1]
def income1_outside_soft_range_for_ecstat?
income1_under_soft_min? || income1_over_soft_max_for_ecstat?
end
income1 < ALLOWED_INCOME_RANGES_SALES[ecstat1][:soft_min]
def income1_more_or_less_text
income1_under_soft_min? ? "less" : "more"
end
def income2_under_soft_min?
return false unless ecstat2 && income2 && ALLOWED_INCOME_RANGES_SALES[ecstat2]
def income2_outside_soft_range_for_ecstat?
income2_under_soft_min? || income2_over_soft_max_for_ecstat?
end
income2 < ALLOWED_INCOME_RANGES_SALES[ecstat2][:soft_min]
def income2_more_or_less_text
income2_under_soft_min? ? "less" : "more"
end
def income1_over_soft_max?
def income1_over_soft_max_for_discounted_ownership?
return unless income1 && la && discounted_ownership_sale?
income_over_soft_max?(income1)
income_over_discounted_sale_soft_max?(income1)
end
def income2_over_soft_max?
def income2_over_soft_max_for_discounted_ownership?
return unless income2 && la && discounted_ownership_sale?
income_over_soft_max?(income2)
income_over_discounted_sale_soft_max?(income2)
end
def combined_income_over_soft_max?
def combined_income_over_soft_max_for_discounted_ownership?
return unless income1 && income2 && la && discounted_ownership_sale?
income_over_soft_max?(income1 + income2)
income_over_discounted_sale_soft_max?(income1 + income2)
end
def staircase_bought_above_fifty?
@ -192,7 +210,40 @@ private
)
end
def income_over_soft_max?(income)
def income1_under_soft_min?
income_under_soft_min?(income1, ecstat1)
end
def income2_under_soft_min?
income_under_soft_min?(income2, ecstat2)
end
def income_under_soft_min?(income, ecstat)
return unless income && ecstat
income_ranges = form.start_year_2025_or_later? ? ALLOWED_INCOME_RANGES_SALES[2025] : ALLOWED_INCOME_RANGES_SALES[2024]
return false unless income_ranges[ecstat]
income < income_ranges[ecstat][:soft_min]
end
def income1_over_soft_max_for_ecstat?
income_over_soft_max?(income1, ecstat1)
end
def income2_over_soft_max_for_ecstat?
income_over_soft_max?(income2, ecstat2)
end
def income_over_soft_max?(income, ecstat)
return unless income && ecstat && form.start_year_2025_or_later?
return false unless ALLOWED_INCOME_RANGES_SALES[2025][ecstat]
income > ALLOWED_INCOME_RANGES_SALES[2025][ecstat][:soft_max]
end
def income_over_discounted_sale_soft_max?(income)
(london_property? && income > 90_000) || (property_not_in_london? && income > 80_000)
end
end

8
config/locales/forms/2023/sales/soft_validations.en.yml

@ -33,11 +33,11 @@ en:
check_answer_label: "Buyer 1 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
discounted:
page_header: ""
title_text: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
@ -45,11 +45,11 @@ en:
check_answer_label: "Buyer 2 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
discounted:
page_header: ""
title_text: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"

12
config/locales/forms/2024/sales/soft_validations.en.yml

@ -31,11 +31,11 @@ en:
check_answer_label: "Buyer 1 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
informative_text: "This is %{more_or_less} than we would expect for someone in this working situation."
discounted:
page_header: ""
title_text: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
@ -43,11 +43,11 @@ en:
check_answer_label: "Buyer 2 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
informative_text: "This is %{more_or_less} than we would expect for someone in this working situation."
discounted:
page_header: ""
title_text: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"

22
config/locales/forms/2025/sales/soft_validations.en.yml

@ -31,32 +31,32 @@ en:
check_answer_label: "Buyer 1 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 1 is %{income}."
informative_text: "This is %{more_or_less} than we would expect for someone in this working situation."
discounted:
page_header: ""
title_text: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
title_text: "You told us the income of buyer 1 is %{income}. This seems high for this sale type. Are you sure this is correct?"
income2_value_check:
check_answer_label: "Buyer 2 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
ecstat:
page_header: ""
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 2 is %{income}."
informative_text: "This is %{more_or_less} than we would expect for someone in this working situation."
discounted:
page_header: ""
title_text: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"
title_text: "You told us the income of buyer 2 is %{income}. This seems high for this sale type. Are you sure this is correct?"
combined_income_value_check:
page_header: ""
check_answer_label: "Combined income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
title_text: "You told us the combined income of this household is %{combined_income}. This seems high. Are you sure this is correct?"
title_text: "You told us the combined income of this household is %{combined_income}. This seems high for this sale type. Are you sure this is correct?"
mortgage_value_check:
page_header: ""

4
spec/models/form/sales/pages/buyer1_income_max_value_check_spec.rb → spec/models/form/sales/pages/buyer1_income_discounted_max_value_check_spec.rb

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer1IncomeMaxValueCheck, type: :model do
RSpec.describe Form::Sales::Pages::Buyer1IncomeDiscountedMaxValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, check_answers_card_number: 1) }
let(:page_id) { "prefix_buyer_1_income_max_value_check" }
@ -23,7 +23,7 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeMaxValueCheck, type: :model do
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"income1_over_soft_max?" => true,
"income1_over_soft_max_for_discounted_ownership?" => true,
},
])
end

8
spec/models/form/sales/pages/buyer1_income_min_value_check_spec.rb → spec/models/form/sales/pages/buyer1_income_ecstat_value_check_spec.rb

@ -1,9 +1,9 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer1IncomeMinValueCheck, type: :model do
RSpec.describe Form::Sales::Pages::Buyer1IncomeEcstatValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "prefix_buyer_1_income_min_value_check" }
let(:page_id) { "prefix_buyer_1_income_ecstat_value_check" }
let(:page_definition) { nil }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
@ -17,13 +17,13 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeMinValueCheck, type: :model do
end
it "has the correct id" do
expect(page.id).to eq("prefix_buyer_1_income_min_value_check")
expect(page.id).to eq("prefix_buyer_1_income_ecstat_value_check")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"income1_under_soft_min?" => true,
"income1_outside_soft_range_for_ecstat?" => true,
},
])
end

4
spec/models/form/sales/pages/buyer2_income_max_value_check_spec.rb → spec/models/form/sales/pages/buyer2_income_discounted_max_value_check_spec.rb

@ -1,6 +1,6 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer2IncomeMaxValueCheck, type: :model do
RSpec.describe Form::Sales::Pages::Buyer2IncomeDiscountedMaxValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, check_answers_card_number: 2) }
let(:page_id) { "prefix_buyer_2_income_max_value_check" }
@ -23,7 +23,7 @@ RSpec.describe Form::Sales::Pages::Buyer2IncomeMaxValueCheck, type: :model do
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"income2_over_soft_max?" => true,
"income2_over_soft_max_for_discounted_ownership?" => true,
},
])
end

8
spec/models/form/sales/pages/buyer2_income_min_value_check_spec.rb → spec/models/form/sales/pages/buyer2_income_ecstat_value_check_spec.rb

@ -1,9 +1,9 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer2IncomeMinValueCheck, type: :model do
RSpec.describe Form::Sales::Pages::Buyer2IncomeEcstatValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "prefix_buyer_2_income_min_value_check" }
let(:page_id) { "prefix_buyer_2_income_ecstat_value_check" }
let(:page_definition) { nil }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
@ -17,13 +17,13 @@ RSpec.describe Form::Sales::Pages::Buyer2IncomeMinValueCheck, type: :model do
end
it "has the correct id" do
expect(page.id).to eq("prefix_buyer_2_income_min_value_check")
expect(page.id).to eq("prefix_buyer_2_income_ecstat_value_check")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"income2_under_soft_min?" => true,
"income2_outside_soft_range_for_ecstat?" => true,
},
])
end

2
spec/models/form/sales/pages/combined_income_max_value_check_spec.rb

@ -23,7 +23,7 @@ RSpec.describe Form::Sales::Pages::CombinedIncomeMaxValueCheck, type: :model do
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"combined_income_over_soft_max?" => true,
"combined_income_over_soft_max_for_discounted_ownership?" => true,
},
])
end

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

@ -16,116 +16,6 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
expect(household_characteristics.section).to eq(section)
end
it "has the correct id" do
expect(household_characteristics.id).to eq("household_characteristics")
end
it "has the correct label" do
expect(household_characteristics.label).to eq("Household characteristics")
end
context "with 2022/23 form" do
before do
allow(form).to receive(:start_date).and_return(Time.zone.local(2022, 4, 1))
allow(form).to receive(:start_year_2024_or_later?).and_return(false)
allow(form).to receive(:start_year_2025_or_later?).and_return(false)
end
it "has correct pages" do
expect(household_characteristics.pages.map(&:id)).to eq(
%w[
buyer_interview_joint_purchase
buyer_interview
privacy_notice_joint_purchase
privacy_notice
buyer_1_age
age_1_retirement_value_check
age_1_old_persons_shared_ownership_joint_purchase_value_check
age_1_old_persons_shared_ownership_value_check
buyer_1_gender_identity
buyer_1_ethnic_group
buyer_1_ethnic_background_black
buyer_1_ethnic_background_asian
buyer_1_ethnic_background_arab
buyer_1_ethnic_background_mixed
buyer_1_ethnic_background_white
buyer_1_nationality
buyer_1_working_situation
working_situation_1_retirement_value_check
working_situation_buyer_1_income_min_value_check
buyer_1_live_in_property
buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
buyer_2_relationship_student_not_child_value_check
buyer_2_age
age_2_old_persons_shared_ownership_joint_purchase_value_check
age_2_old_persons_shared_ownership_value_check
age_2_buyer_retirement_value_check
buyer_2_age_student_not_child_value_check
buyer_2_gender_identity
buyer_2_working_situation
working_situation_2_retirement_value_check_joint_purchase
working_situation_buyer_2_income_min_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
buyer_2_live_in_property_value_check
number_of_others_in_property
number_of_others_in_property_joint_purchase
person_2_known
person_2_relationship_to_buyer_1
relationship_2_student_not_child_value_check
person_2_age
age_2_retirement_value_check
age_2_student_not_child_value_check
person_2_gender_identity
person_2_working_situation
working_situation_2_retirement_value_check
working_situation_2_student_not_child_value_check
person_3_known
person_3_relationship_to_buyer_1
relationship_3_student_not_child_value_check
person_3_age
age_3_retirement_value_check
age_3_student_not_child_value_check
person_3_gender_identity
person_3_working_situation
working_situation_3_retirement_value_check
working_situation_3_student_not_child_value_check
person_4_known
person_4_relationship_to_buyer_1
relationship_4_student_not_child_value_check
person_4_age
age_4_retirement_value_check
age_4_student_not_child_value_check
person_4_gender_identity
person_4_working_situation
working_situation_4_retirement_value_check
working_situation_4_student_not_child_value_check
person_5_known
person_5_relationship_to_buyer_1
relationship_5_student_not_child_value_check
person_5_age
age_5_retirement_value_check
age_5_student_not_child_value_check
person_5_gender_identity
person_5_working_situation
working_situation_5_retirement_value_check
working_situation_5_student_not_child_value_check
person_6_known
person_6_relationship_to_buyer_1
relationship_6_student_not_child_value_check
person_6_age
age_6_retirement_value_check
age_6_student_not_child_value_check
person_6_gender_identity
person_6_working_situation
working_situation_6_retirement_value_check
working_situation_6_student_not_child_value_check
],
)
end
end
context "with 2023/24 form" do
before do
allow(form).to receive(:start_date).and_return(Time.zone.local(2023, 4, 1))
@ -154,7 +44,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_1_nationality
buyer_1_working_situation
working_situation_1_retirement_value_check
working_situation_buyer_1_income_min_value_check
working_situation_buyer_1_income_value_check
buyer_1_live_in_property
buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
@ -174,7 +64,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_2_nationality
buyer_2_working_situation
working_situation_2_retirement_value_check_joint_purchase
working_situation_buyer_2_income_min_value_check
working_situation_buyer_2_income_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
buyer_2_live_in_property_value_check
@ -281,7 +171,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_1_working_situation
working_situation_1_retirement_value_check
working_situation_1_not_retired_value_check
working_situation_buyer_1_income_min_value_check
working_situation_buyer_1_income_value_check
buyer_1_live_in_property
buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
@ -303,7 +193,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_2_working_situation
working_situation_2_retirement_value_check_joint_purchase
working_situation_2_not_retired_value_check_joint_purchase
working_situation_buyer_2_income_min_value_check
working_situation_buyer_2_income_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
buyer_2_live_in_property_value_check
@ -396,10 +286,6 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
allow(form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct depends on" do
expect(household_characteristics.depends_on).to eq([{ "setup_completed?" => true }])
end
it "has correct pages" do
expect(household_characteristics.pages.map(&:id)).to eq(
%w[
@ -419,7 +305,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_1_working_situation
working_situation_1_retirement_value_check
working_situation_1_not_retired_value_check
working_situation_buyer_1_income_min_value_check
working_situation_buyer_1_income_value_check
buyer_1_live_in_property
buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
@ -441,7 +327,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
buyer_2_working_situation
working_situation_2_retirement_value_check_joint_purchase
working_situation_2_not_retired_value_check_joint_purchase
working_situation_buyer_2_income_min_value_check
working_situation_buyer_2_income_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
buyer_2_live_in_property_value_check
@ -525,5 +411,9 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
],
)
end
it "has correct depends on" do
expect(household_characteristics.depends_on).to eq([{ "setup_completed?" => true }])
end
end
end

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

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
let(:subsection_id) { nil }
let(:subsection_definition) { nil }
let(:section) { instance_double(Form::Sales::Sections::Household) }
let(:section) { instance_double(Form::Sales::Sections::Household, form:) }
let(:form) { instance_double(Form, start_date: Time.utc(2024, 4, 1), start_year_2025_or_later?: false) }
it "has correct section" do
expect(subsection.section).to eq(section)
@ -19,26 +20,23 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
expect(subsection.label).to eq("Income, benefits and savings")
end
describe "pages" do
let(:section) { instance_double(Form::Sales::Sections::Household, form: instance_double(Form, start_date:, start_year_2025_or_later?: false)) }
context "when 2022" do
let(:start_date) { Time.utc(2022, 2, 8) }
context "when before 2025" do
let(:form) { instance_double(Form, start_date: Time.utc(2024, 4, 1), start_year_2025_or_later?: false) }
it "has correct pages" do
expect(subsection.pages.compact.map(&:id)).to eq(
expect(subsection.pages.map(&:id)).to eq(
%w[
buyer_1_income
buyer_1_income_min_value_check
buyer_1_income_max_value_check
buyer_1_income_ecstat_value_check
buyer_1_income_discounted_max_value_check
buyer_1_combined_income_max_value_check
buyer_1_income_mortgage_value_check
buyer_1_mortgage
buyer_1_mortgage_value_check
buyer_2_income
buyer_2_income_mortgage_value_check
buyer_2_income_min_value_check
buyer_2_income_max_value_check
buyer_2_income_ecstat_value_check
buyer_2_income_discounted_max_value_check
buyer_2_combined_income_max_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
@ -52,28 +50,33 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
savings_deposit_value_check
previous_ownership_joint_purchase
previous_ownership_not_joint_purchase
previous_shared
],
)
end
it "has correct depends on" do
expect(subsection.depends_on).to eq([{ "setup_completed?" => true }])
end
end
context "when 2023" do
let(:start_date) { Time.utc(2023, 2, 8) }
context "when 2025" do
let(:form) { instance_double(Form, start_date: Time.utc(2025, 4, 1), start_year_2025_or_later?: true) }
it "has correct pages" do
expect(subsection.pages.map(&:id)).to eq(
%w[
buyer_1_income
buyer_1_income_min_value_check
buyer_1_income_max_value_check
buyer_1_income_ecstat_value_check
buyer_1_income_discounted_max_value_check
buyer_1_combined_income_max_value_check
buyer_1_income_mortgage_value_check
buyer_1_mortgage
buyer_1_mortgage_value_check
buyer_2_income
buyer_2_income_mortgage_value_check
buyer_2_income_min_value_check
buyer_2_income_max_value_check
buyer_2_income_ecstat_value_check
buyer_2_income_discounted_max_value_check
buyer_2_combined_income_max_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
@ -92,16 +95,6 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
)
end
it "has correct depends on" do
expect(subsection.depends_on).to eq([{ "setup_completed?" => true }])
end
end
end
context "when 2025" do
let(:start_date) { Time.utc(2025, 2, 8) }
let(:section) { instance_double(Form::Sales::Sections::Household, form: instance_double(Form, start_date:, start_year_2025_or_later?: true)) }
it "has correct depends on" do
expect(subsection.depends_on).to eq([{ "setup_completed?" => true, "is_staircase?" => false }])
end

275
spec/models/validations/sales/soft_validations_spec.rb

@ -3,85 +3,222 @@ require "rails_helper"
RSpec.describe Validations::Sales::SoftValidations do
let(:record) { build(:sales_log) }
describe "income1 min validations" do
context "when validating soft min" do
it "returns false if no income1 is given" do
describe "income validations" do
context "when validating soft range based on ecstat" do
it "does not trigger for income1 if no income1 is given" do
record.income1 = nil
expect(record).not_to be_income1_under_soft_min
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
it "returns false if no ecstat1 is given" do
it "does not trigger for low income1 if no ecstat1 is given" do
record.income1 = 50
record.ecstat1 = nil
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
expect(record).not_to be_income1_under_soft_min
it "does not trigger for income2 if no income2 is given" do
record.income2 = nil
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
[
{
income1: 4500,
ecstat1: 1,
},
{
income1: 1400,
ecstat1: 2,
},
{
income1: 999,
ecstat1: 3,
},
{
income1: 1899,
ecstat1: 5,
},
{
income1: 1888,
ecstat1: 0,
},
].each do |test_case|
it "returns true if income1 is below soft min for ecstat1 #{test_case[:ecstat1]}" do
record.income1 = test_case[:income1]
record.ecstat1 = test_case[:ecstat1]
expect(record)
.to be_income1_under_soft_min
it "does not trigger for low income2 if no ecstat2 is given" do
record.income2 = 50
record.ecstat2 = nil
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
context "when log year is before 2025" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2024, 12, 25)) }
it "does not trigger for low income1 if ecstat1 has no soft min" do
record.income1 = 50
record.ecstat1 = 4
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
[
{
income1: 5001,
ecstat1: 1,
},
{
income1: 1600,
ecstat1: 2,
},
{
income1: 1004,
ecstat1: 3,
},
{
income1: 2899,
ecstat1: 4,
},
{
income1: 2899,
ecstat1: 5,
},
{
income1: 5,
ecstat1: 6,
},
{
income1: 10_888,
ecstat1: 0,
},
].each do |test_case|
it "returns false if income1 is over soft min for ecstat1 #{test_case[:ecstat1]}" do
record.income1 = test_case[:income1]
record.ecstat1 = test_case[:ecstat1]
expect(record)
.not_to be_income1_under_soft_min
it "returns true if income1 is below soft min for ecstat1" do
record.income1 = 4500
record.ecstat1 = 1
expect(record).to be_income1_outside_soft_range_for_ecstat
end
it "returns false if income1 is >= soft min for ecstat1" do
record.income1 = 1500
record.ecstat1 = 2
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
it "does not trigger for income2 if ecstat2 has no soft min" do
record.income2 = 50
record.ecstat2 = 8
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
it "returns true if income2 is below soft min for ecstat2" do
record.income2 = 999
record.ecstat2 = 3
expect(record).to be_income2_outside_soft_range_for_ecstat
end
it "returns false if income2 is >= soft min for ecstat2" do
record.income2 = 2500
record.ecstat2 = 5
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
it "does not trigger for being over maxima" do
record.ecstat1 = 1
record.income1 = 200_000
record.ecstat2 = 2
record.income2 = 100_000
expect(record).not_to be_income1_outside_soft_range_for_ecstat
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
end
context "when log year is 2025" do
let(:record) { build(:sales_log, saledate: Time.zone.local(2025, 12, 25)) }
it "returns true if income1 is below soft min for ecstat1" do
record.income1 = 13_399
record.ecstat1 = 1
expect(record).to be_income1_outside_soft_range_for_ecstat
end
it "returns false if income1 is >= soft min for ecstat1" do
record.income1 = 2600
record.ecstat1 = 2
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
it "returns true if income2 is below soft min for ecstat2" do
record.income2 = 2079
record.ecstat2 = 3
expect(record).to be_income2_outside_soft_range_for_ecstat
end
it "returns false if income2 is >= soft min for ecstat2" do
record.income2 = 520
record.ecstat2 = 5
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
it "returns true if income1 is above soft max for ecstat1" do
record.income1 = 80_001
record.ecstat1 = 2
expect(record).to be_income1_outside_soft_range_for_ecstat
end
it "returns false if income1 is <= soft max for ecstat1" do
record.income1 = 80_000
record.ecstat1 = 2
expect(record).not_to be_income1_outside_soft_range_for_ecstat
end
it "returns true if income2 is above soft max for ecstat2" do
record.income2 = 50_001
record.ecstat2 = 6
expect(record).to be_income2_outside_soft_range_for_ecstat
end
it "returns false if income2 is <= soft max for ecstat2" do
record.income2 = 50_000
record.ecstat2 = 6
expect(record).not_to be_income2_outside_soft_range_for_ecstat
end
end
end
context "when validating soft max for discounted ownership" do
it "does not trigger if la is not set" do
record.la = nil
record.income1 = 100_000
record.income2 = 95_000
record.ownershipsch = 2
expect(record).not_to be_income1_over_soft_max_for_discounted_ownership
expect(record).not_to be_income2_over_soft_max_for_discounted_ownership
expect(record).not_to be_combined_income_over_soft_max_for_discounted_ownership
end
it "does not trigger if sale is not discounted ownership" do
record.la = "E09000001"
record.income1 = 100_000
record.income2 = 95_000
record.ownershipsch = 1
expect(record).not_to be_income1_over_soft_max_for_discounted_ownership
expect(record).not_to be_income2_over_soft_max_for_discounted_ownership
expect(record).not_to be_combined_income_over_soft_max_for_discounted_ownership
end
context "when property is in London for a discounted ownership sale" do
let(:record) { build(:sales_log, ownershipsch: 2, la: "E09000001") }
it "returns true for income1 if income1 > London threshold" do
record.income1 = 90_001
expect(record).to be_income1_over_soft_max_for_discounted_ownership
end
it "returns false for income1 if income1 <= London threshold" do
record.income1 = 90_000
expect(record).not_to be_income1_over_soft_max_for_discounted_ownership
end
it "returns true for income2 if income2 > London threshold" do
record.income2 = 100_000
expect(record).to be_income2_over_soft_max_for_discounted_ownership
end
it "returns false for income2 if income2 <= London threshold" do
record.income2 = 30_000
expect(record).not_to be_income2_over_soft_max_for_discounted_ownership
end
it "returns true for combined income if > London threshold" do
record.income1 = 61_000
record.income2 = 30_000
expect(record).to be_combined_income_over_soft_max_for_discounted_ownership
end
it "returns false for combined income if <= London threshold" do
record.income1 = 40_000
record.income2 = 20_000
expect(record).not_to be_combined_income_over_soft_max_for_discounted_ownership
end
end
context "when property is not in London for a discounted ownership sale" do
let(:record) { build(:sales_log, ownershipsch: 2, la: "E08000001") }
it "returns true for income1 if income1 > non-London threshold" do
record.income1 = 80_001
expect(record).to be_income1_over_soft_max_for_discounted_ownership
end
it "returns false for income1 if income1 <= non-London threshold" do
record.income1 = 80_000
expect(record).not_to be_income1_over_soft_max_for_discounted_ownership
end
it "returns true for income2 if income2 > non-London threshold" do
record.income2 = 85_000
expect(record).to be_income2_over_soft_max_for_discounted_ownership
end
it "returns false for income2 if income2 <= non-London threshold" do
record.income2 = 30_000
expect(record).not_to be_income2_over_soft_max_for_discounted_ownership
end
it "returns true for combined income if > non-London threshold" do
record.income1 = 61_000
record.income2 = 20_000
expect(record).to be_combined_income_over_soft_max_for_discounted_ownership
end
it "returns false for combined income if <= non-London threshold" do
record.income1 = 40_000
record.income2 = 20_000
expect(record).not_to be_combined_income_over_soft_max_for_discounted_ownership
end
end
end

4
spec/services/documentation_generator_spec.rb

@ -127,11 +127,11 @@ describe DocumentationGenerator do
context "when the service is run for sales" do
let(:log_type) { "sales" }
let(:all_validation_methods) { ["income2_under_soft_min?"] }
let(:all_validation_methods) { ["income2_outside_soft_range_for_ecstat?"] }
it "creates new validation documentation records" do
expect { described_class.new.describe_soft_validations(client, all_validation_methods, all_helper_methods, log_type) }.to change(LogValidation, :count)
expect(LogValidation.where(validation_name: "income2_under_soft_min?").count).to be_positive
expect(LogValidation.where(validation_name: "income2_outside_soft_range_for_ecstat?").count).to be_positive
any_validation = LogValidation.first
expect(any_validation.description).to eq("Validates the format.")
expect(any_validation.field).not_to be_empty

Loading…
Cancel
Save