Browse Source

Value validation (#1429)

* Add discounted_sale_value_check to sales

* Add DiscountedSaleValueCheck pages and questions

* Add value check to the form

* Only run validate_discounted_ownership_value as a hard validation on and after 24/25

* Rebase fix

* Fix form spec

* Update discounted_ownership_value_invalid?

* update validation

* Update soft validation content

* PR comments

* typo

* lint

* Default discounted_sale_value_check on import
pull/1449/head
kosiakkatrina 2 years ago committed by GitHub
parent
commit
f29e41bb2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      app/models/form/sales/pages/discounted_sale_value_check.rb
  2. 23
      app/models/form/sales/questions/discounted_sale_value_check.rb
  3. 4
      app/models/form/sales/subsections/discounted_ownership_scheme.rb
  4. 1
      app/models/form/sales/subsections/setup.rb
  5. 17
      app/models/sales_log.rb
  6. 11
      app/models/validations/sales/sale_information_validations.rb
  7. 9
      app/models/validations/sales/soft_validations.rb
  8. 4
      app/services/imports/sales_logs_import_service.rb
  9. 3
      config/locales/en.yml
  10. 5
      db/migrate/20230316162737_add_discounted_sale_value_check.rb
  11. 1
      db/schema.rb
  12. 52
      spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
  13. 57
      spec/models/form/sales/questions/discounted_sale_value_check_spec.rb
  14. 4
      spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
  15. 1
      spec/models/form/sales/subsections/setup_spec.rb
  16. 4
      spec/models/form_spec.rb
  17. 2
      spec/models/sales_log_spec.rb
  18. 200
      spec/models/validations/sales/sale_information_validations_spec.rb
  19. 115
      spec/models/validations/sales/soft_validations_spec.rb
  20. 15
      spec/services/imports/sales_logs_import_service_spec.rb

26
app/models/form/sales/pages/discounted_sale_value_check.rb

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

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

@ -0,0 +1,23 @@
class Form::Sales::Questions::DiscountedSaleValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "discounted_sale_value_check"
@check_answer_label = "Discounted sale value 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" => [
{
"discounted_sale_value_check" => 0,
},
{
"discounted_sale_value_check" => 1,
},
],
}
end
end

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

@ -14,12 +14,15 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self), Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self),
Form::Sales::Pages::GrantValueCheck.new(nil, nil, self), Form::Sales::Pages::GrantValueCheck.new(nil, nil, self),
Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_grant_value_check", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_discounted_ownership_value_check", nil, self), Form::Sales::Pages::AboutPriceValueCheck.new("about_price_discounted_ownership_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_used_mortgage_value_check", nil, self), Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_used_mortgage_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_used_value_check", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_amount_mortgage_value_check", nil, self), Form::Sales::Pages::MortgageValueCheck.new("discounted_ownership_mortgage_amount_mortgage_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_mortgage_value_check", nil, self),
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_mortgage_value_check", nil, self), Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_mortgage_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_mortgage", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_mortgage", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::MortgageLender.new("mortgage_lender_discounted_ownership", nil, self, ownershipsch: 2),
@ -31,6 +34,7 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_deposit_value_check", nil, self), Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_deposit_value_check", nil, self),
Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self),
Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_deposit", nil, self), Form::Sales::Pages::DepositAndMortgageValueCheck.new("discounted_ownership_deposit_and_mortgage_value_check_after_deposit", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_deposit_value_check", nil, self),
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_discounted_ownership", nil, self, ownershipsch: 2), Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_discounted_ownership_value_check", nil, self), Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_discounted_ownership_value_check", nil, self),
] ]

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

@ -18,6 +18,7 @@ class Form::Sales::Subsections::Setup < ::Form::Subsection
Form::Sales::Pages::OutrightOwnershipType.new(nil, nil, self), Form::Sales::Pages::OutrightOwnershipType.new(nil, nil, self),
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self), Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self), Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_type_value_check", nil, self),
Form::Sales::Pages::BuyerCompany.new(nil, nil, self), Form::Sales::Pages::BuyerCompany.new(nil, nil, self),
Form::Sales::Pages::BuyerLive.new(nil, nil, self), Form::Sales::Pages::BuyerLive.new(nil, nil, self),
Form::Sales::Pages::JointPurchase.new(nil, nil, self), Form::Sales::Pages::JointPurchase.new(nil, nil, self),

17
app/models/sales_log.rb

@ -42,7 +42,7 @@ class SalesLog < Log
} }
scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) } scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) }
OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check mortgagelender othtype].freeze OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check mortgagelender othtype discounted_sale_value_check].freeze
RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze
def lettings? def lettings?
@ -330,4 +330,19 @@ class SalesLog < Log
def should_process_uprn_change? def should_process_uprn_change?
uprn_changed? && saledate && saledate.year >= 2023 uprn_changed? && saledate && saledate.year >= 2023
end end
def value_with_discount
return if value.blank?
discount_amount = discount ? value * discount / 100 : 0
value - discount_amount
end
def mortgage_deposit_and_grant_total
return if deposit.blank?
grant_amount = grant || 0
mortgage_amount = mortgage || 0
mortgage_amount + deposit + grant_amount
end
end end

11
app/models/validations/sales/sale_information_validations.rb

@ -1,4 +1,6 @@
module Validations::Sales::SaleInformationValidations module Validations::Sales::SaleInformationValidations
include CollectionTimeHelper
def validate_practical_completion_date_before_saledate(record) def validate_practical_completion_date_before_saledate(record)
return if record.saledate.blank? || record.hodate.blank? return if record.saledate.blank? || record.hodate.blank?
@ -45,17 +47,14 @@ module Validations::Sales::SaleInformationValidations
end end
def validate_discounted_ownership_value(record) def validate_discounted_ownership_value(record)
return unless record.saledate && collection_start_year(record.saledate) >= 2024
return unless record.value && record.deposit && record.ownershipsch return unless record.value && record.deposit && record.ownershipsch
return unless record.mortgage || record.mortgageused == 2 return unless record.mortgage || record.mortgageused == 2
return unless record.discount || record.grant || record.type == 29 return unless record.discount || record.grant || record.type == 29
discount_amount = record.discount ? record.value * record.discount / 100 : 0 if record.mortgage_deposit_and_grant_total != record.value_with_discount && record.discounted_ownership_sale?
grant_amount = record.grant || 0
mortgage_amount = record.mortgage || 0
value_with_discount = (record.value - discount_amount)
if mortgage_amount + record.deposit + grant_amount != value_with_discount && record.discounted_ownership_sale?
%i[mortgage deposit grant value discount ownershipsch].each do |field| %i[mortgage deposit grant value discount ownershipsch].each do |field|
record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", value_with_discount)) record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: sprintf("%.2f", record.value_with_discount))
end end
end end
end end

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

@ -114,6 +114,15 @@ module Validations::Sales::SoftValidations
end end
end end
def discounted_ownership_value_invalid?
return unless saledate && collection_start_year <= 2023
return unless value && deposit && ownershipsch
return unless mortgage || mortgageused == 2
return unless discount || grant || type == 29
mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale?
end
private private
def sale_range def sale_range

4
app/services/imports/sales_logs_import_service.rb

@ -153,6 +153,7 @@ module Imports
attributes["income2_value_check"] = 0 attributes["income2_value_check"] = 0
attributes["monthly_charges_value_check"] = 0 attributes["monthly_charges_value_check"] = 0
attributes["student_not_child_value_check"] = 0 attributes["student_not_child_value_check"] = 0
attributes["discounted_sale_value_check"] = 0
# Sets the log creator # Sets the log creator
owner_id = meta_field_value(xml_doc, "owner-user-id").strip owner_id = meta_field_value(xml_doc, "owner-user-id").strip
@ -255,7 +256,8 @@ module Imports
monthly_charges_value_check monthly_charges_value_check
hodate_check hodate_check
saledate_check saledate_check
student_not_child_value_check] student_not_child_value_check
discounted_sale_value_check]
end end
def check_status_completed(sales_log, previous_status) def check_status_completed(sales_log, previous_status)

3
config/locales/en.yml

@ -525,6 +525,9 @@ en:
title_text: "The amount of monthly charges is high for this type of property and sale type" title_text: "The amount of monthly charges is high for this type of property and sale type"
student_not_child: student_not_child:
title_text: "You told us this person is a student aged beween 16 and 19" title_text: "You told us this person is a student aged beween 16 and 19"
discounted_sale_value:
title_text: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
informative_text: "Your given mortgage, deposit and grant total is £%{mortgage_deposit_and_grant_total}"
devise: devise:
two_factor_authentication: two_factor_authentication:

5
db/migrate/20230316162737_add_discounted_sale_value_check.rb

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

1
db/schema.rb

@ -569,6 +569,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_20_084057) do
t.string "county" t.string "county"
t.integer "nationalbuy2" t.integer "nationalbuy2"
t.integer "student_not_child_value_check" t.integer "student_not_child_value_check"
t.integer "discounted_sale_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.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 ["old_id"], name: "index_sales_logs_on_old_id", unique: true t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true

52
spec/models/form/sales/pages/discounted_sale_value_check_spec.rb

@ -0,0 +1,52 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::DiscountedSaleValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, index) }
let(:page_id) { "discounted_sale_value_check" }
let(:page_definition) { nil }
let(:index) { 1 }
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[discounted_sale_value_check])
end
it "has the correct id" do
expect(page.id).to eq("discounted_sale_value_check")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.discounted_sale_value.title_text",
"arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }],
})
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({
"translation" => "soft_validations.discounted_sale_value.informative_text",
"arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }],
})
end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"discounted_ownership_value_invalid?" => true,
},
])
end
end

57
spec/models/form/sales/questions/discounted_sale_value_check_spec.rb

@ -0,0 +1,57 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::DiscountedSaleValueCheck, 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("discounted_sale_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("Discounted sale value 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 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" => [
{
"discounted_sale_value_check" => 0,
},
{
"discounted_sale_value_check" => 1,
},
],
})
end
end

4
spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb

@ -20,12 +20,15 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model
about_price_not_rtb about_price_not_rtb
grant_value_check grant_value_check
purchase_price_discounted_ownership purchase_price_discounted_ownership
discounted_sale_grant_value_check
about_price_discounted_ownership_value_check about_price_discounted_ownership_value_check
discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount discounted_ownership_deposit_and_mortgage_value_check_after_value_and_discount
mortgage_used_discounted_ownership mortgage_used_discounted_ownership
discounted_ownership_mortgage_used_mortgage_value_check discounted_ownership_mortgage_used_mortgage_value_check
discounted_sale_mortgage_used_value_check
mortgage_amount_discounted_ownership mortgage_amount_discounted_ownership
discounted_ownership_mortgage_amount_mortgage_value_check discounted_ownership_mortgage_amount_mortgage_value_check
discounted_sale_mortgage_value_check
extra_borrowing_mortgage_value_check extra_borrowing_mortgage_value_check
discounted_ownership_deposit_and_mortgage_value_check_after_mortgage discounted_ownership_deposit_and_mortgage_value_check_after_mortgage
mortgage_lender_discounted_ownership mortgage_lender_discounted_ownership
@ -37,6 +40,7 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model
extra_borrowing_deposit_value_check extra_borrowing_deposit_value_check
discounted_ownership_deposit_value_check discounted_ownership_deposit_value_check
discounted_ownership_deposit_and_mortgage_value_check_after_deposit discounted_ownership_deposit_and_mortgage_value_check_after_deposit
discounted_sale_deposit_value_check
leasehold_charges_discounted_ownership leasehold_charges_discounted_ownership
monthly_charges_discounted_ownership_value_check monthly_charges_discounted_ownership_value_check
], ],

1
spec/models/form/sales/subsections/setup_spec.rb

@ -25,6 +25,7 @@ RSpec.describe Form::Sales::Subsections::Setup, type: :model do
outright_ownership_type outright_ownership_type
ownership_type_old_persons_shared_ownership_value_check ownership_type_old_persons_shared_ownership_value_check
monthly_charges_type_value_check monthly_charges_type_value_check
discounted_sale_type_value_check
buyer_company buyer_company
buyer_live buyer_live
joint_purchase joint_purchase

4
spec/models/form_spec.rb

@ -227,9 +227,9 @@ RSpec.describe Form, type: :model do
expect(form.sections[0].class).to eq(Form::Sales::Sections::Setup) expect(form.sections[0].class).to eq(Form::Sales::Sections::Setup)
expect(form.subsections.count).to eq(1) expect(form.subsections.count).to eq(1)
expect(form.subsections.first.id).to eq("setup") expect(form.subsections.first.id).to eq("setup")
expect(form.pages.count).to eq(15) expect(form.pages.count).to eq(16)
expect(form.pages.first.id).to eq("organisation") expect(form.pages.first.id).to eq("organisation")
expect(form.questions.count).to eq(16) expect(form.questions.count).to eq(17)
expect(form.questions.first.id).to eq("owning_organisation_id") expect(form.questions.first.id).to eq("owning_organisation_id")
expect(form.start_date).to eq(Time.zone.parse("2022-04-01")) expect(form.start_date).to eq(Time.zone.parse("2022-04-01"))
expect(form.end_date).to eq(Time.zone.parse("2023-07-07")) expect(form.end_date).to eq(Time.zone.parse("2023-07-07"))

2
spec/models/sales_log_spec.rb

@ -61,6 +61,7 @@ RSpec.describe SalesLog, type: :model do
old_persons_shared_ownership_value_check old_persons_shared_ownership_value_check
mortgagelender mortgagelender
othtype othtype
discounted_sale_value_check
proplen proplen
mortlen mortlen
frombeds frombeds
@ -79,6 +80,7 @@ RSpec.describe SalesLog, type: :model do
old_persons_shared_ownership_value_check old_persons_shared_ownership_value_check
mortgagelender mortgagelender
othtype othtype
discounted_sale_value_check
address_line2 address_line2
county county
postcode_full postcode_full

200
spec/models/validations/sales/sale_information_validations_spec.rb

@ -226,112 +226,133 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end end
describe "#validate_discounted_ownership_value" do describe "#validate_discounted_ownership_value" do
context "when grant is routed to" do context "when sale is on or after 24/25 collection window" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8) } context "when grant is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8, saledate: Time.zone.local(2024, 4, 3)) }
context "and not provided" do context "and not provided" do
before do before do
record.grant = nil record.grant = nil
end end
it "does not add an error" do it "does not add an error" do
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty expect(record.errors).to be_empty
end
end end
end
context "and is provided" do context "and is provided" do
it "adds an error if mortgage, deposit and grant total does not equal market value" do it "adds an error if mortgage, deposit and grant total does not equal market value" do
record.grant = 3_000 record.grant = 3_000
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
end end
it "does not add an error if mortgage, deposit and grant total equals market value" do it "does not add an error if mortgage, deposit and grant total equals market value" do
record.grant = 15_000 record.grant = 15_000
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty expect(record.errors).to be_empty
end
end end
end end
end
context "when discount is routed to" do context "when discount is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9) } let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9, saledate: Time.zone.local(2024, 4, 3)) }
context "and not provided" do context "and not provided" do
before do before do
record.discount = nil record.discount = nil
end end
it "does not add an error" do it "does not add an error" do
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty expect(record.errors).to be_empty
end
end
context "and is provided" do
it "adds an error if mortgage and deposit total does not equal market value - discount" do
record.discount = 10
sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00"))
end
it "does not add an error if mortgage and deposit total equals market value - discount" do
record.discount = 50
sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty
end
end end
end end
context "and is provided" do context "when neither discount nor grant is routed to" do
it "adds an error if mortgage and deposit total does not equal market value - discount" do let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29, saledate: Time.zone.local(2024, 4, 3)) }
record.discount = 10
it "adds an error if mortgage and deposit total does not equal market value" do
record.deposit = 2_000
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "27000.00")) expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
end end
it "does not add an error if mortgage and deposit total equals market value - discount" do it "does not add an error if mortgage and deposit total equals market value" do
record.discount = 50 record.deposit = 20_000
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty expect(record.errors).to be_empty
end end
end end
end
context "when neither discount nor grant is routed to" do context "when mortgage is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29) } let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2024, 4, 3)) }
it "adds an error if mortgage and deposit total does not equal market value" do context "and not provided" do
record.deposit = 2_000 before do
sale_information_validator.validate_discounted_ownership_value(record) record.mortgage = nil
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00")) end
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "30000.00"))
end
it "does not add an error if mortgage and deposit total equals market value" do it "does not add an error" do
record.deposit = 20_000 sale_information_validator.validate_discounted_ownership_value(record)
sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty
end
end
context "when mortgage is routed to" do expect(record.errors).to be_empty
let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2) } end
context "and not provided" do
before do
record.mortgage = nil
end end
it "does not add an error" do context "and is provided" do
sale_information_validator.validate_discounted_ownership_value(record) it "adds an error if mortgage, grant and deposit total does not equal market value - discount" do
record.mortgage = 10
expect(record.errors).to be_empty sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
end
it "does not add an error if mortgage, grant and deposit total equals market value - discount" do
record.mortgage = 10_000
sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty
end
end end
end end
context "and is provided" do context "when mortgage is not routed to" do
it "adds an error if mortgage, grant and deposit total does not equal market value - discount" do let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2024, 4, 3)) }
record.mortgage = 10
it "adds an error if grant and deposit total does not equal market value - discount" do
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00")) expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
@ -341,34 +362,25 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end end
it "does not add an error if mortgage, grant and deposit total equals market value - discount" do it "does not add an error if mortgage, grant and deposit total equals market value - discount" do
record.mortgage = 10_000 record.grant = 13_000
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty expect(record.errors).to be_empty
end end
end end
end
context "when mortgage is not routed to" do context "when ownership is not discounted" do
let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2) } let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1, saledate: Time.zone.local(2024, 4, 3)) }
it "adds an error if grant and deposit total does not equal market value - discount" do it "does not add an error" do
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors[:mortgage]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:deposit]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:grant]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:value]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
expect(record.errors[:discount]).to include(I18n.t("validations.sale_information.discounted_ownership_value", value_with_discount: "18000.00"))
end
it "does not add an error if mortgage, grant and deposit total equals market value - discount" do expect(record.errors).to be_empty
record.grant = 13_000 end
sale_information_validator.validate_discounted_ownership_value(record)
expect(record.errors).to be_empty
end end
end end
context "when ownership is not discounted" do context "when sale is before 24/25 collection" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1) } let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 4)) }
it "does not add an error" do it "does not add an error" do
sale_information_validator.validate_discounted_ownership_value(record) sale_information_validator.validate_discounted_ownership_value(record)

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

@ -798,4 +798,119 @@ RSpec.describe Validations::Sales::SoftValidations do
expect(record).to be_person_3_student_not_child expect(record).to be_person_3_student_not_child
end end
end end
describe "#discounted_ownership_value_invalid?" do
context "when grant is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 8, saledate: Time.zone.local(2023, 4, 3)) }
context "and not provided" do
before do
record.grant = nil
end
it "returns false" do
expect(record).not_to be_discounted_ownership_value_invalid
end
end
context "and is provided" do
it "returns true if mortgage, deposit and grant total does not equal market value" do
record.grant = 3_000
expect(record).to be_discounted_ownership_value_invalid
end
it "returns false if mortgage, deposit and grant total equals market value" do
record.grant = 15_000
expect(record).not_to be_discounted_ownership_value_invalid
end
end
end
context "when discount is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, value: 30_000, ownershipsch: 2, type: 9, saledate: Time.zone.local(2023, 4, 3)) }
context "and not provided" do
before do
record.discount = nil
end
it "returns false" do
expect(record).not_to be_discounted_ownership_value_invalid
end
end
context "and is provided" do
it "returns true if mortgage and deposit total does not equal market value - discount" do
record.discount = 10
expect(record).to be_discounted_ownership_value_invalid
end
it "returns false if mortgage and deposit total equals market value - discount" do
record.discount = 50
expect(record).not_to be_discounted_ownership_value_invalid
end
end
end
context "when neither discount nor grant is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, value: 30_000, ownershipsch: 2, type: 29, saledate: Time.zone.local(2023, 4, 3)) }
it "returns true if mortgage and deposit total does not equal market value" do
record.deposit = 2_000
expect(record).to be_discounted_ownership_value_invalid
end
it "returns false if mortgage and deposit total equals market value" do
record.deposit = 20_000
expect(record).not_to be_discounted_ownership_value_invalid
end
end
context "when mortgage is routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 3)) }
context "and not provided" do
before do
record.mortgage = nil
end
it "returns false" do
expect(record).not_to be_discounted_ownership_value_invalid
end
end
context "and is provided" do
it "returns true if mortgage, grant and deposit total does not equal market value - discount" do
record.mortgage = 10
expect(record).to be_discounted_ownership_value_invalid
end
it "returns false if mortgage, grant and deposit total equals market value - discount" do
record.mortgage = 10_000
expect(record).not_to be_discounted_ownership_value_invalid
end
end
end
context "when mortgage is not routed to" do
let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 2, saledate: Time.zone.local(2023, 4, 3)) }
it "returns true if grant and deposit total does not equal market value - discount" do
expect(record).to be_discounted_ownership_value_invalid
end
it "returns false if mortgage, grant and deposit total equals market value - discount" do
record.grant = 13_000
expect(record).not_to be_discounted_ownership_value_invalid
end
end
context "when ownership is not discounted" do
let(:record) { FactoryBot.build(:sales_log, mortgage: 10_000, deposit: 5_000, grant: 3_000, value: 20_000, discount: 10, ownershipsch: 1, saledate: Time.zone.local(2023, 4, 3)) }
it "returns false" do
expect(record).not_to be_discounted_ownership_value_invalid
end
end
end
end end

15
spec/services/imports/sales_logs_import_service_spec.rb

@ -379,6 +379,21 @@ RSpec.describe Imports::SalesLogsImportService do
end end
end end
context "and the value soft validation is triggered (discounted_sale_value_check)" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:Q31PurchasePrice").content = "500000"
end
it "completes the log" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log.status).to eq("completed")
expect(sales_log.discounted_sale_value_check).to eq(0)
end
end
context "and it has an invalid record with invalid child age" do context "and it has an invalid record with invalid child age" do
let(:sales_log_id) { "discounted_ownership_sales_log" } let(:sales_log_id) { "discounted_ownership_sales_log" }

Loading…
Cancel
Save