Browse Source

CLDC-1575 Add shared ownership validations (#1217)

* Add income error to ownership type and ecstat fields

* Add shared_ownership_deposit_value_check field

* Add shared_ownership_deposit_invalid? soft validation

* Add shared ownership deposit check pages and questions

* Add pages to the subsection and update validation message

* tests

* Update validation to only trigger if la is given

* Run the soft validation when mortgage isn't used or cash discount isn't given

* test
pull/1232/head^2
kosiakkatrina 2 years ago committed by GitHub
parent
commit
7bd76c4d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
  2. 23
      app/models/form/sales/questions/shared_ownership_deposit_value_check.rb
  3. 5
      app/models/form/sales/subsections/shared_ownership_scheme.rb
  4. 6
      app/models/sales_log.rb
  5. 10
      app/models/validations/sales/financial_validations.rb
  6. 10
      app/models/validations/sales/soft_validations.rb
  7. 2
      config/locales/en.yml
  8. 7
      db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb
  9. 1
      db/schema.rb
  10. 50
      spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
  11. 61
      spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb
  12. 3
      spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
  13. 4
      spec/models/form_handler_spec.rb
  14. 8
      spec/models/sales_log_spec.rb
  15. 26
      spec/models/validations/sales/financial_validations_spec.rb
  16. 104
      spec/models/validations/sales/soft_validations_spec.rb

27
app/models/form/sales/pages/shared_ownership_deposit_value_check.rb

@ -0,0 +1,27 @@
class Form::Sales::Pages::SharedOwnershipDepositValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super
@depends_on = [
{
"shared_ownership_deposit_invalid?" => true,
},
]
@informative_text = {}
@title_text = {
"translation" => "soft_validations.shared_owhership_deposit.title_text",
"arguments" => [
{
"key" => "expected_shared_ownership_deposit_value",
"label" => false,
"i18n_template" => "expected_shared_ownership_deposit_value",
},
],
}
end
def questions
@questions ||= [
Form::Sales::Questions::SharedOwnershipDepositValueCheck.new(nil, nil, self),
]
end
end

23
app/models/form/sales/questions/shared_ownership_deposit_value_check.rb

@ -0,0 +1,23 @@
class Form::Sales::Questions::SharedOwnershipDepositValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "shared_ownership_deposit_value_check"
@check_answer_label = "Shared ownership deposit confirmation"
@type = "interruption_screen"
@header = "Are you sure this is correct?"
@answer_options = {
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
}
@hidden_in_check_answers = {
"depends_on" => [
{
"shared_ownership_deposit_value_check" => 0,
},
{
"shared_ownership_deposit_value_check" => 1,
},
],
}
end
end

5
app/models/form/sales/subsections/shared_ownership_scheme.rb

@ -21,15 +21,18 @@ class Form::Sales::Subsections::SharedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::PreviousPropertyType.new(nil, nil, self), Form::Sales::Pages::PreviousPropertyType.new(nil, nil, self),
Form::Sales::Pages::PreviousTenure.new(nil, nil, self), Form::Sales::Pages::PreviousTenure.new(nil, nil, self),
Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self), Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_equity_value_check", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_mortgage_amount_value_check", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_shared_ownership", nil, self), Form::Sales::Pages::MortgageLender.new("mortgage_lender_shared_ownership", nil, self),
Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_shared_ownership", nil, self), Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_shared_ownership", nil, self),
Form::Sales::Pages::MortgageLength.new("mortgage_length_shared_ownership", nil, self), Form::Sales::Pages::MortgageLength.new("mortgage_length_shared_ownership", nil, self),
Form::Sales::Pages::ExtraBorrowing.new("extra_borrowing_shared_ownership", nil, self), Form::Sales::Pages::ExtraBorrowing.new("extra_borrowing_shared_ownership", nil, self),
Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self), Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self), Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self),
Form::Sales::Pages::DepositValueCheck.new("shared_ownership_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("deposit_value_check", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_deposit_value_check", nil, self),
Form::Sales::Pages::MonthlyRent.new(nil, nil, self), Form::Sales::Pages::MonthlyRent.new(nil, nil, self),
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_shared_ownership", nil, self), Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_shared_ownership", nil, self),
] ]

6
app/models/sales_log.rb

@ -159,6 +159,12 @@ class SalesLog < Log
end end
end end
def expected_shared_ownership_deposit_value
return unless value && equity
(value * equity / 100).round(2)
end
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key) def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
return if postcode.blank? return if postcode.blank?

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

@ -3,11 +3,19 @@ module Validations::Sales::FinancialValidations
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_income1(record) def validate_income1(record)
if record.ecstat1 && record.income1 && record.ownershipsch == 1 if record.ecstat1 && record.income1 && record.la && record.ownershipsch == 1
if record.london_property? 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 :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 elsif record.income1 > 80_000
record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 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 end
end end
end end

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

@ -43,6 +43,16 @@ module Validations::Sales::SoftValidations
extrabor != 1 && mortgage + deposit > value - value * discount / 100 extrabor != 1 && mortgage + deposit > value - value * discount / 100
end end
def shared_ownership_deposit_invalid?
return unless mortgage || mortgageused == 2
return unless cashdis || !is_type_discount?
return unless deposit && value && equity
cash_discount = cashdis || 0
mortgage_value = mortgage || 0
mortgage_value + deposit + cash_discount != value * equity / 100
end
def hodate_3_years_or_more_saledate? def hodate_3_years_or_more_saledate?
return unless hodate && saledate return unless hodate && saledate

2
config/locales/en.yml

@ -461,6 +461,8 @@ en:
title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years" title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years"
void_date: void_date:
title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years" title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years"
shared_owhership_deposit:
title_text: "Mortgage, deposit and cash discount total should equal £%{expected_shared_ownership_deposit_value}"
devise: devise:
two_factor_authentication: two_factor_authentication:

7
db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb

@ -0,0 +1,7 @@
class AddSharedOwnershipDepositValueCheck < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :shared_ownership_deposit_value_check, :integer
end
end
end

1
db/schema.rb

@ -507,6 +507,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_26_145529) do
t.integer "hodate_check" t.integer "hodate_check"
t.integer "extrabor_value_check" t.integer "extrabor_value_check"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.integer "shared_ownership_deposit_value_check"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"
t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id" t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id"

50
spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb

@ -0,0 +1,50 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::SharedOwnershipDepositValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "shared_ownership_deposit_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[shared_ownership_deposit_value_check])
end
it "has the correct id" do
expect(page.id).to eq("shared_ownership_deposit_value_check")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"shared_ownership_deposit_invalid?" => true,
},
])
end
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.shared_owhership_deposit.title_text",
"arguments" => [
{
"key" => "expected_shared_ownership_deposit_value",
"label" => false,
"i18n_template" => "expected_shared_ownership_deposit_value",
},
],
})
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({})
end
end

61
spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb

@ -0,0 +1,61 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::SharedOwnershipDepositValueCheck, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("shared_ownership_deposit_value_check")
end
it "has the correct header" do
expect(question.header).to eq("Are you sure this is correct?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Shared ownership deposit confirmation")
end
it "has the correct type" do
expect(question.type).to eq("interruption_screen")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
# it "has a correct check_answers_card_number" do
# expect(question.check_answers_card_number).to eq(0)
# end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
})
end
it "has the correct hidden_in_check_answers" do
expect(question.hidden_in_check_answers).to eq({
"depends_on" => [
{
"shared_ownership_deposit_value_check" => 0,
},
{
"shared_ownership_deposit_value_check" => 1,
},
],
})
end
end

3
spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb

@ -27,14 +27,17 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipScheme, type: :model do
previous_property_type previous_property_type
shared_ownership_previous_tenure shared_ownership_previous_tenure
about_price_shared_ownership about_price_shared_ownership
shared_ownership_equity_value_check
mortgage_used_shared_ownership mortgage_used_shared_ownership
mortgage_amount_shared_ownership mortgage_amount_shared_ownership
shared_ownership_mortgage_amount_value_check
mortgage_lender_shared_ownership mortgage_lender_shared_ownership
mortgage_lender_other_shared_ownership mortgage_lender_other_shared_ownership
mortgage_length_shared_ownership mortgage_length_shared_ownership
extra_borrowing_shared_ownership extra_borrowing_shared_ownership
about_deposit_with_discount about_deposit_with_discount
about_deposit_shared_ownership about_deposit_shared_ownership
deposit_value_check
shared_ownership_deposit_value_check shared_ownership_deposit_value_check
monthly_rent monthly_rent
leasehold_charges_shared_ownership leasehold_charges_shared_ownership

4
spec/models/form_handler_spec.rb

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

8
spec/models/sales_log_spec.rb

@ -339,4 +339,12 @@ RSpec.describe SalesLog, type: :model do
expect(record_from_db["prevloc"]).to eq(nil) expect(record_from_db["prevloc"]).to eq(nil)
end end
end end
describe "expected_shared_ownership_deposit_value" do
let!(:completed_sales_log) { create(:sales_log, :completed, ownershipsch: 1, type: 2, value: 1000, equity: 50) }
it "is set to completed for a completed sales log" do
expect(completed_sales_log.expected_shared_ownership_deposit_value).to eq(500)
end
end
end end

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

@ -6,7 +6,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } } let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } }
describe "income validations" do describe "income validations" do
let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1) } let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1, la: "E08000035") }
context "with shared ownership" do context "with shared ownership" do
context "and non london borough" do context "and non london borough" do
@ -17,6 +17,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]) expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)) .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
end end
@ -25,6 +33,10 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.ecstat1 = 1 record.ecstat1 = 1
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty 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
end end
@ -41,6 +53,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]) expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000)) .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
end end
@ -49,6 +69,10 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.ecstat1 = 1 record.ecstat1 = 1
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty 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
end end
end end

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

@ -321,6 +321,110 @@ RSpec.describe Validations::Sales::SoftValidations do
.not_to be_deposit_over_soft_max .not_to be_deposit_over_soft_max
end end
end end
context "when validating shared ownership deposit" do
it "returns false if MORTGAGE + DEPOSIT + CASHDIS are equal VALUE * EQUITY/100" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if mortgage is used and no mortgage is given" do
record.mortgage = nil
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if mortgage is not used and no mortgage is given" do
record.mortgage = nil
record.mortgageused = 2
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
it "returns false if no deposit is given" do
record.mortgage = 1000
record.deposit = nil
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if no cashdis is given and cashdis is routed to" do
record.mortgage = 1000
record.deposit = 1000
record.type = 18
record.cashdis = nil
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if no cashdis is given and cashdis is not routed to" do
record.mortgage = 1000
record.deposit = 1000
record.type = 2
record.cashdis = nil
record.value = 3000
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
it "returns false if no value is given" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = nil
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if no equity is given" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = nil
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if MORTGAGE + DEPOSIT + CASHDIS are not equal VALUE * EQUITY/100" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 4323
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
end
end end
describe "hodate_more_than_3_years_before_saledate" do describe "hodate_more_than_3_years_before_saledate" do

Loading…
Cancel
Save