Browse Source

CLDC-3758: Sales - Add shared ownership staircasing transaction section (#2788)

* db migration, new sales log fields

* Add new staircasing transaction section

* Update tests

* Lint

* Add tests

* Use log methods

* Lint

* Update test

* Remove compact

* Change section display condition

* CLDC-3760: Sales - firststair and numstair staircasing questions validations (#2793)

* Add validation to new questions firststair and numstair

* Remove page headers on single question page

* Remove page

* More useful page header

* Show don't know option from 2025 onwards

* Add page header to monthly rent only for the version with two questions on the page

* Remove page header staircase initial date only page

* Update displayed answer options

* Fix lint

* Updates after merge

* Update test

* Update tests
pull/2844/head
Manny Dinssa 2 months ago committed by GitHub
parent
commit
128ac5d57a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      app/models/derived_variables/sales_log_variables.rb
  2. 2
      app/models/form/sales/pages/about_staircase.rb
  3. 2
      app/models/form/sales/pages/equity.rb
  4. 17
      app/models/form/sales/pages/monthly_rent_staircasing.rb
  5. 17
      app/models/form/sales/pages/monthly_rent_staircasing_owned.rb
  6. 15
      app/models/form/sales/pages/staircase_first_time.rb
  7. 16
      app/models/form/sales/pages/staircase_initial_date.rb
  8. 18
      app/models/form/sales/pages/staircase_previous.rb
  9. 17
      app/models/form/sales/pages/staircase_sale.rb
  10. 2
      app/models/form/sales/pages/value_shared_ownership.rb
  11. 1
      app/models/form/sales/questions/equity.rb
  12. 15
      app/models/form/sales/questions/monthly_rent_after_staircasing.rb
  13. 15
      app/models/form/sales/questions/monthly_rent_before_staircasing.rb
  14. 2
      app/models/form/sales/questions/mortgageused.rb
  15. 15
      app/models/form/sales/questions/staircase_count.rb
  16. 16
      app/models/form/sales/questions/staircase_first_time.rb
  17. 11
      app/models/form/sales/questions/staircase_initial_date.rb
  18. 11
      app/models/form/sales/questions/staircase_last_date.rb
  19. 2
      app/models/form/sales/questions/staircase_sale.rb
  20. 1
      app/models/form/sales/questions/value.rb
  21. 16
      app/models/form/sales/sections/sale_information.rb
  22. 5
      app/models/form/sales/subsections/shared_ownership_initial_purchase.rb
  23. 4
      app/models/form/sales/subsections/shared_ownership_scheme.rb
  24. 35
      app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb
  25. 4
      app/models/sales_log.rb
  26. 17
      app/models/validations/sales/sale_information_validations.rb
  27. 92
      config/locales/forms/2025/sales/sale_information.en.yml
  28. 6
      config/locales/validations/sales/sale_information.en.yml
  29. 11
      db/migrate/20241114173226_add_fields_to_sales_log.rb
  30. 5
      db/schema.rb
  31. 4
      spec/models/form/sales/pages/about_staircase_spec.rb
  32. 4
      spec/models/form/sales/pages/equity_spec.rb
  33. 31
      spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb
  34. 31
      spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb
  35. 31
      spec/models/form/sales/pages/staircase_first_time_spec.rb
  36. 31
      spec/models/form/sales/pages/staircase_initial_date_spec.rb
  37. 31
      spec/models/form/sales/pages/staircase_previous_spec.rb
  38. 38
      spec/models/form/sales/pages/staircase_sale_spec.rb
  39. 2
      spec/models/form/sales/pages/value_shared_ownership_spec.rb
  40. 2
      spec/models/form/sales/questions/equity_spec.rb
  41. 37
      spec/models/form/sales/questions/monthly_rent_after_staircasing_spec.rb
  42. 37
      spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb
  43. 98
      spec/models/form/sales/questions/mortgageused_spec.rb
  44. 33
      spec/models/form/sales/questions/staircase_count_spec.rb
  45. 40
      spec/models/form/sales/questions/staircase_first_time_spec.rb
  46. 33
      spec/models/form/sales/questions/staircase_initial_date_spec.rb
  47. 33
      spec/models/form/sales/questions/staircase_last_date_spec.rb
  48. 4
      spec/models/form/sales/questions/staircase_sale_spec.rb
  49. 6
      spec/models/form/sales/questions/value_spec.rb
  50. 11
      spec/models/form/sales/sections/sale_information_spec.rb
  51. 2
      spec/models/form/sales/subsections/shared_ownership_initial_purchase_spec.rb
  52. 40
      spec/models/validations/sales/sale_information_validations_spec.rb

3
app/models/derived_variables/sales_log_variables.rb

@ -80,6 +80,9 @@ module DerivedVariables::SalesLogVariables
self.is_la_inferred = false
end
self.numstair = is_firststair? ? 1 : nil if numstair == 1 && firststair_changed?
self.mrent = 0 if stairowned_100?
set_encoded_derived_values!(DEPENDENCIES)
end

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

@ -18,7 +18,7 @@ class Form::Sales::Pages::AboutStaircase < ::Form::Page
end
def staircase_sale_question
if form.start_date.year >= 2023
if [2023, 2024].include?(form.start_date.year)
Form::Sales::Questions::StaircaseSale.new(nil, nil, self)
end
end

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

@ -1,7 +1,7 @@
class Form::Sales::Pages::Equity < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "equity"
@copy_key = "sales.sale_information.equity"
end
def questions

17
app/models/form/sales/pages/monthly_rent_staircasing.rb

@ -0,0 +1,17 @@
class Form::Sales::Pages::MonthlyRentStaircasing < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "monthly_rent_staircasing"
@copy_key = "sales.sale_information.mrent_staircasing"
@depends_on = [{
"stairowned_100?" => false,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::MonthlyRentBeforeStaircasing.new(nil, nil, self),
Form::Sales::Questions::MonthlyRentAfterStaircasing.new(nil, nil, self),
]
end
end

17
app/models/form/sales/pages/monthly_rent_staircasing_owned.rb

@ -0,0 +1,17 @@
class Form::Sales::Pages::MonthlyRentStaircasingOwned < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "monthly_rent_staircasing_owned"
@copy_key = "sales.sale_information.mrent_staircasing"
@header = ""
@depends_on = [{
"stairowned_100?" => true,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::MonthlyRentBeforeStaircasing.new(nil, nil, self),
]
end
end

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

@ -0,0 +1,15 @@
class Form::Sales::Pages::StaircaseFirstTime < ::Form::Page
def initialize(id, hsh, subsection)
super(id, hsh, subsection)
@id = "staircase_first_time"
@depends_on = [{
"staircase" => 1,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::StaircaseFirstTime.new(nil, nil, self),
]
end
end

16
app/models/form/sales/pages/staircase_initial_date.rb

@ -0,0 +1,16 @@
class Form::Sales::Pages::StaircaseInitialDate < ::Form::Page
def initialize(id, hsh, subsection)
super(id, hsh, subsection)
@id = "staircase_initial_date"
@header = ""
@depends_on = [{
"is_firststair?" => true,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::StaircaseInitialDate.new(nil, nil, self),
]
end
end

18
app/models/form/sales/pages/staircase_previous.rb

@ -0,0 +1,18 @@
class Form::Sales::Pages::StaircasePrevious < ::Form::Page
def initialize(id, hsh, subsection)
super(id, hsh, subsection)
@id = "staircase_previous"
@copy_key = "sales.sale_information.stairprevious"
@depends_on = [{
"is_firststair?" => false,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::StaircaseCount.new(nil, nil, self),
Form::Sales::Questions::StaircaseLastDate.new(nil, nil, self),
Form::Sales::Questions::StaircaseInitialDate.new(nil, nil, self),
]
end
end

17
app/models/form/sales/pages/staircase_sale.rb

@ -0,0 +1,17 @@
class Form::Sales::Pages::StaircaseSale < ::Form::Page
def initialize(id, hsh, subsection)
super(id, hsh, subsection)
@id = "staircase_sale"
@copy_key = form.start_year_2025_or_later? ? "sales.sale_information.staircasesale" : "sales.sale_information.about_staircasing.staircasesale"
@depends_on = [{
"staircase" => 1,
"stairowned" => 100,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::StaircaseSale.new(nil, nil, self),
]
end
end

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

@ -1,7 +1,7 @@
class Form::Sales::Pages::ValueSharedOwnership < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "value_shared_ownership"
@copy_key = "sales.sale_information.value"
end
def questions

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

@ -2,6 +2,7 @@ class Form::Sales::Questions::Equity < ::Form::Question
def initialize(id, hsh, page)
super
@id = "equity"
@copy_key = "sales.sale_information.equity.#{page.id}"
@type = "numeric"
@min = 0
@max = 100

15
app/models/form/sales/questions/monthly_rent_after_staircasing.rb

@ -0,0 +1,15 @@
class Form::Sales::Questions::MonthlyRentAfterStaircasing < ::Form::Question
def initialize(id, hsh, page)
super
@id = "mrent"
@copy_key = "sales.sale_information.mrent_staircasing.poststaircasing"
@type = "numeric"
@min = 0
@step = 0.01
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 99 }.freeze
end

15
app/models/form/sales/questions/monthly_rent_before_staircasing.rb

@ -0,0 +1,15 @@
class Form::Sales::Questions::MonthlyRentBeforeStaircasing < ::Form::Question
def initialize(id, hsh, page)
super
@id = "mrentprestaircasing"
@copy_key = "sales.sale_information.mrent_staircasing.prestaircasing"
@type = "numeric"
@min = 0
@step = 0.01
@width = 5
@prefix = "£"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 98 }.freeze
end

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

@ -12,7 +12,7 @@ class Form::Sales::Questions::Mortgageused < ::Form::Question
def displayed_answer_options(log, _user = nil)
if log.outright_sale? && log.saledate && !form.start_year_2024_or_later?
answer_options_without_dont_know
elsif log.stairowned == 100 || log.outright_sale?
elsif log.stairowned_100? || log.outright_sale? || (log.is_staircase? && form.start_year_2025_or_later?)
ANSWER_OPTIONS
else
answer_options_without_dont_know

15
app/models/form/sales/questions/staircase_count.rb

@ -0,0 +1,15 @@
class Form::Sales::Questions::StaircaseCount < ::Form::Question
def initialize(id, hsh, page)
super
@id = "numstair"
@copy_key = "sales.sale_information.stairprevious.numstair"
@type = "numeric"
@width = 2
@min = 2
@max = 10
@step = 1
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 82 }.freeze
end

16
app/models/form/sales/questions/staircase_first_time.rb

@ -0,0 +1,16 @@
class Form::Sales::Questions::StaircaseFirstTime < ::Form::Question
def initialize(id, hsh, page)
super
@id = "firststair"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
ANSWER_OPTIONS = {
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}.freeze
QUESTION_NUMBER_FROM_YEAR = { 2025 => 81 }.freeze
end

11
app/models/form/sales/questions/staircase_initial_date.rb

@ -0,0 +1,11 @@
class Form::Sales::Questions::StaircaseInitialDate < ::Form::Question
def initialize(id, hsh, page)
super
@id = "initialpurchase"
@copy_key = "sales.sale_information.stairprevious.initialpurchase"
@type = "date"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 83 }.freeze
end

11
app/models/form/sales/questions/staircase_last_date.rb

@ -0,0 +1,11 @@
class Form::Sales::Questions::StaircaseLastDate < ::Form::Question
def initialize(id, hsh, page)
super
@id = "lasttransaction"
@copy_key = "sales.sale_information.stairprevious.lasttransaction"
@type = "date"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2025 => 83 }.freeze
end

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

@ -2,7 +2,7 @@ class Form::Sales::Questions::StaircaseSale < ::Form::Question
def initialize(id, hsh, page)
super
@id = "staircasesale"
@copy_key = "sales.sale_information.about_staircasing.staircasesale"
@copy_key = form.start_year_2025_or_later? ? "sales.sale_information.staircasesale" : "sales.sale_information.about_staircasing.staircasesale"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]

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

@ -2,6 +2,7 @@ class Form::Sales::Questions::Value < ::Form::Question
def initialize(id, hsh, page)
super
@id = "value"
@copy_key = "sales.sale_information.value.#{page.id}"
@type = "numeric"
@min = 0
@step = 1

16
app/models/form/sales/sections/sale_information.rb

@ -4,18 +4,20 @@ class Form::Sales::Sections::SaleInformation < ::Form::Section
@id = "sale_information"
@label = "Sale information"
@description = ""
@subsections = [
shared_ownership_scheme_subsection,
Form::Sales::Subsections::DiscountedOwnershipScheme.new(nil, nil, self),
Form::Sales::Subsections::OutrightSale.new(nil, nil, self),
] || []
@subsections = []
@subsections.concat(shared_ownership_scheme_subsection)
@subsections << Form::Sales::Subsections::DiscountedOwnershipScheme.new(nil, nil, self)
@subsections << Form::Sales::Subsections::OutrightSale.new(nil, nil, self)
end
def shared_ownership_scheme_subsection
if form.start_year_2025_or_later?
Form::Sales::Subsections::SharedOwnershipInitialPurchase.new(nil, nil, self)
[
Form::Sales::Subsections::SharedOwnershipInitialPurchase.new(nil, nil, self),
Form::Sales::Subsections::SharedOwnershipStaircasingTransaction.new(nil, nil, self),
]
else
Form::Sales::Subsections::SharedOwnershipScheme.new(nil, nil, self)
[Form::Sales::Subsections::SharedOwnershipScheme.new(nil, nil, self)]
end
end
end

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

@ -4,6 +4,7 @@ class Form::Sales::Subsections::SharedOwnershipInitialPurchase < ::Form::Subsect
@id = "shared_ownership_initial_purchase"
@label = "Shared ownership - initial purchase"
@depends_on = [{ "ownershipsch" => 1, "setup_completed?" => true, "staircase" => 2 }]
@copy_key = "sale_information"
end
def pages
@ -18,9 +19,9 @@ class Form::Sales::Subsections::SharedOwnershipInitialPurchase < ::Form::Subsect
Form::Sales::Pages::PreviousBedrooms.new(nil, nil, self),
Form::Sales::Pages::PreviousPropertyType.new(nil, nil, self),
Form::Sales::Pages::PreviousTenure.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new("value_shared_ownership", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_shared_ownership_value_check", nil, self),
Form::Sales::Pages::Equity.new(nil, nil, self),
Form::Sales::Pages::Equity.new("initial_equity", 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, ownershipsch: 1),
Form::Sales::Pages::MortgageValueCheck.new("mortgage_used_mortgage_value_check", nil, self),

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

@ -27,9 +27,9 @@ class Form::Sales::Subsections::SharedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::PreviousBedrooms.new(nil, nil, self),
Form::Sales::Pages::PreviousPropertyType.new(nil, nil, self),
Form::Sales::Pages::PreviousTenure.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new("value_shared_ownership", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_shared_ownership_value_check", nil, self),
Form::Sales::Pages::Equity.new(nil, nil, self),
Form::Sales::Pages::Equity.new("equity", 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, ownershipsch: 1),
Form::Sales::Pages::MortgageValueCheck.new("mortgage_used_mortgage_value_check", nil, self),

35
app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb

@ -0,0 +1,35 @@
class Form::Sales::Subsections::SharedOwnershipStaircasingTransaction < ::Form::Subsection
def initialize(id, hsh, section)
super
@id = "shared_ownership_staircasing_transaction"
@label = "Shared ownership - staircasing transaction"
@depends_on = [{ "ownershipsch" => 1, "setup_completed?" => true, "staircase" => 1 }]
@copy_key = "sale_information"
end
def pages
@pages ||= [
Form::Sales::Pages::AboutStaircase.new("about_staircasing_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::AboutStaircase.new("about_staircasing_not_joint_purchase", nil, self, joint_purchase: false),
Form::Sales::Pages::StaircaseSale.new(nil, nil, self),
Form::Sales::Pages::StaircaseBoughtValueCheck.new(nil, nil, self),
Form::Sales::Pages::StaircaseOwnedValueCheck.new("staircase_owned_value_check_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::StaircaseOwnedValueCheck.new("staircase_owned_value_check_not_joint_purchase", nil, self, joint_purchase: false),
Form::Sales::Pages::StaircaseFirstTime.new(nil, nil, self),
Form::Sales::Pages::StaircasePrevious.new(nil, nil, self),
Form::Sales::Pages::StaircaseInitialDate.new(nil, nil, self),
Form::Sales::Pages::ValueSharedOwnership.new("value_shared_ownership_staircase", nil, self),
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_shared_ownership_value_check", nil, self),
Form::Sales::Pages::Equity.new("staircase_equity", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_equity_value_check", nil, self),
Form::Sales::Pages::Mortgageused.new("staircase_mortgage_used_shared_ownership", nil, self, ownershipsch: 1),
Form::Sales::Pages::MonthlyRentStaircasingOwned.new(nil, nil, self),
Form::Sales::Pages::MonthlyRentStaircasing.new(nil, nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_shared_ownership_value_check", nil, self),
].compact
end
def displayed_in_tasklist?(log)
log.staircase == 1 && (log.ownershipsch.nil? || log.ownershipsch == 1)
end
end

4
app/models/sales_log.rb

@ -557,4 +557,8 @@ class SalesLog < Log
def is_resale?
resale == 1
end
def is_firststair?
firststair == 1
end
end

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

@ -35,6 +35,14 @@ module Validations::Sales::SaleInformationValidations
end
end
def validate_staircasing_initial_purchase_date(record)
return unless record.initialpurchase
if record.initialpurchase < Time.zone.local(1980, 1, 1)
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980")
end
end
def validate_previous_property_unit_type(record)
return unless record.fromprop && record.frombeds
@ -351,6 +359,15 @@ module Validations::Sales::SaleInformationValidations
end
end
def validate_number_of_staircase_transactions(record)
return unless record.numstair
if record.firststair == 2 && record.numstair < 2
record.errors.add :numstair, I18n.t("validations.sales.sale_information.numstair.must_be_greater_than_one")
record.errors.add :firststair, I18n.t("validations.sales.sale_information.firststair.cannot_be_no")
end
end
def over_tolerance?(expected, actual, tolerance, strict: false)
if strict
(expected - actual).abs > tolerance

92
config/locales/forms/2025/sales/sale_information.en.yml

@ -26,24 +26,47 @@ en:
question_text: "Did the buyer live in the property before purchasing it?"
about_staircasing:
page_header: "About the staircasing transaction"
stairbought:
check_answer_label: "Percentage bought in this staircasing transaction"
page_header: "About the staircasing transaction"
stairbought:
check_answer_label: "Percentage bought in this staircasing transaction"
hint_text: ""
question_text: "What percentage of the property has been bought in this staircasing transaction?"
stairowned:
joint_purchase:
check_answer_label: "Percentage the buyers now own in total"
hint_text: ""
question_text: "What percentage of the property has been bought in this staircasing transaction?"
stairowned:
joint_purchase:
check_answer_label: "Percentage the buyers now own in total"
hint_text: ""
question_text: "What percentage of the property do the buyers now own in total?"
not_joint_purchase:
check_answer_label: "Percentage the buyer now owns in total"
hint_text: ""
question_text: "What percentage of the property does the buyer now own in total?"
staircasesale:
check_answer_label: "Part of a back-to-back staircasing transaction"
question_text: "What percentage of the property do the buyers now own in total?"
not_joint_purchase:
check_answer_label: "Percentage the buyer now owns in total"
hint_text: ""
question_text: "Is this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
question_text: "What percentage of the property does the buyer now own in total?"
staircasesale:
page_header: ""
check_answer_label: "Part of a back-to-back staircasing transaction?"
hint_text: ""
question_text: "Is this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
firststair:
page_header: ""
check_answer_label: "First time staircasing?"
hint_text: ""
question_text: "Is this the first time the shared owner has engaged in staircasing in the home?"
stairprevious:
page_header: "About previous staircasing transactions"
numstair:
check_answer_label: "Number of staircasing transactions"
hint_text: ""
question_text: "Including this time, how many times has the shared owner engaged in staircasing in the home?"
initialpurchase:
check_answer_label: "Initial staircasing transaction"
hint_text: ""
question_text: "What was the date of the initial purchase of a share in the property?"
lasttransaction:
check_answer_label: "Last staircasing transaction"
hint_text: ""
question_text: "What was the date of the last staircasing transaction?"
resale:
page_header: ""
@ -101,19 +124,29 @@ en:
value:
page_header: "About the price of the property"
check_answer_label: "Full purchase price"
hint_text: "Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser)"
question_text: "What was the full purchase price?"
value_shared_ownership:
check_answer_label: "Full purchase price"
hint_text: "Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser)."
question_text: "What was the full purchase price?"
value_shared_ownership_staircase:
check_answer_label: "Full purchase price"
hint_text: "Enter the full purchase price paid for the equity bought in this staircasing transaction (this is equal to the value of the share bought by the purchaser)."
question_text: "What was the full purchase price for this staircasing transaction?"
equity:
page_header: "About the price of the property"
check_answer_label: "Initial percentage equity share"
hint_text: "Enter the amount of initial equity share held by the purchaser (for example, 25% or 50%)"
question_text: "What was the initial percentage share purchased?"
initial_equity:
check_answer_label: "Initial percentage equity share"
hint_text: "Enter the amount of initial equity share held by the purchaser (for example, 25% or 50%)"
question_text: "What was the initial percentage share purchased?"
staircase_equity:
check_answer_label: "Initial percentage equity share"
hint_text: "Enter the amount of initial equity share held by the purchaser (for example, 25% or 50%)"
question_text: "What was the percentage shared purchased in the initial transaction?"
mortgageused:
page_header: "Mortgage Amount"
check_answer_label: "Mortgage used"
check_answer_label: "Mortgage used?"
hint_text: ""
question_text: "Was a mortgage used for the purchase of this property?"
@ -165,6 +198,17 @@ en:
hint_text: "Amount paid before any charges"
question_text: "What is the basic monthly rent?"
mrent_staircasing:
page_header: "Monthly rent"
prestaircasing:
check_answer_label: "Monthly rent prior to staircasing"
hint_text: "Amount paid before any charges"
question_text: "What was the basic monthly rent prior to staircasing?"
poststaircasing:
check_answer_label: "Monthly rent after staircasing"
hint_text: "Amount paid before any charges"
question_text: "What is the basic monthly rent after staircasing?"
leaseholdcharges:
page_header: ""
has_mscharge:
@ -199,7 +243,7 @@ en:
check_answer_label: "Amount of any loan, grant or subsidy"
hint_text: "For all schemes except Right to Buy (RTB), Preserved Right to Buy (PRTB), Voluntary Right to Buy (VRTB) and Rent to Buy"
question_text: "What was the amount of any loan, grant, discount or subsidy given?"
management_fee:
page_header: ""
has_management_fee:

6
config/locales/validations/sales/sale_information.en.yml

@ -19,6 +19,8 @@ en:
exdate:
must_be_before_saledate: "Contract exchange date must be before sale completion date."
must_be_less_than_1_year_from_saledate: "Contract exchange date must be less than 1 year before sale completion date."
initialpurchase:
must_be_after_1980: "The initial purchase date must be after January 1, 1980."
fromprop:
previous_property_type_bedsit: "A bedsit cannot have more than 1 bedroom."
frombeds:
@ -125,3 +127,7 @@ en:
postcode_full:
value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London."
value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London."
numstair:
must_be_greater_than_one: "The number of staircasing transactions must be greater than 1 when this is not the first staircasing transaction."
firststair:
cannot_be_no: "The answer to 'Is this the first staircasing transaction?' cannot be 'no' if the number of staircasing transactions is 1."

11
db/migrate/20241114173226_add_fields_to_sales_log.rb

@ -0,0 +1,11 @@
class AddFieldsToSalesLog < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :firststair, :integer
t.column :numstair, :integer
t.column :mrentprestaircasing, :decimal, precision: 10, scale: 2
t.column :lasttransaction, :datetime
t.column :initialpurchase, :datetime
end
end
end

5
db/schema.rb

@ -761,6 +761,11 @@ ActiveRecord::Schema[7.0].define(version: 2024_11_22_154743) do
t.bigint "created_by_id"
t.integer "has_management_fee"
t.decimal "management_fee", precision: 10, scale: 2
t.integer "firststair"
t.integer "numstair"
t.decimal "mrentprestaircasing", precision: 10, scale: 2
t.datetime "lasttransaction"
t.datetime "initialpurchase"
t.index ["assigned_to_id"], name: "index_sales_logs_on_assigned_to_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"

4
spec/models/form/sales/pages/about_staircase_spec.rb

@ -15,6 +15,10 @@ RSpec.describe Form::Sales::Pages::AboutStaircase, type: :model do
describe "questions" do
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
before do
allow(subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
end
context "when 2022" do
let(:start_date) { Time.utc(2022, 2, 8) }

4
spec/models/form/sales/pages/equity_spec.rb

@ -15,10 +15,6 @@ RSpec.describe Form::Sales::Pages::Equity, type: :model do
expect(page.questions.map(&:id)).to eq(%w[equity])
end
it "has the correct id" do
expect(page.id).to eq("equity")
end
it "has the correct description" do
expect(page.description).to be_nil
end

31
spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MonthlyRentStaircasingOwned, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
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[mrentprestaircasing])
end
it "has the correct id" do
expect(page.id).to eq("monthly_rent_staircasing_owned")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "stairowned_100?" => true },
])
end
end

31
spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MonthlyRentStaircasing, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
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[mrentprestaircasing mrent])
end
it "has the correct id" do
expect(page.id).to eq("monthly_rent_staircasing")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "stairowned_100?" => false },
])
end
end

31
spec/models/form/sales/pages/staircase_first_time_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::StaircaseFirstTime, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
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[firststair])
end
it "has the correct id" do
expect(page.id).to eq("staircase_first_time")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "staircase" => 1 },
])
end
end

31
spec/models/form/sales/pages/staircase_initial_date_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::StaircaseInitialDate, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
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[initialpurchase])
end
it "has the correct id" do
expect(page.id).to eq("staircase_initial_date")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "is_firststair?" => true },
])
end
end

31
spec/models/form/sales/pages/staircase_previous_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::StaircasePrevious, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
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[numstair lasttransaction initialpurchase])
end
it "has the correct id" do
expect(page.id).to eq("staircase_previous")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{ "is_firststair?" => false },
])
end
end

38
spec/models/form/sales/pages/staircase_sale_spec.rb

@ -0,0 +1,38 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::StaircaseSale, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
before do
allow(subsection.form).to receive(:start_year_2025_or_later?).and_return(true)
end
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[staircasesale])
end
it "has the correct id" do
expect(page.id).to eq("staircase_sale")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"staircase" => 1,
"stairowned" => 100,
},
])
end
end

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

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::ValueSharedOwnership, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_id) { "value_shared_ownership" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }

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

@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::Equity, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
let(:page) { instance_double(Form::Page, id: "initial_equity", subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
it "has correct page" do
expect(question.page).to eq(page)

37
spec/models/form/sales/questions/monthly_rent_after_staircasing_spec.rb

@ -0,0 +1,37 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::MonthlyRentAfterStaircasing, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("mrent")
end
it "has the correct type" do
expect(question.type).to eq("numeric")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has correct width" do
expect(question.width).to eq(5)
end
it "has correct prefix" do
expect(question.prefix).to eq("£")
end
it "has correct min" do
expect(question.min).to eq(0)
end
end

37
spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb

@ -0,0 +1,37 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::MonthlyRentBeforeStaircasing, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("mrentprestaircasing")
end
it "has the correct type" do
expect(question.type).to eq("numeric")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has correct width" do
expect(question.width).to eq(5)
end
it "has correct prefix" do
expect(question.prefix).to eq("£")
end
it "has correct min" do
expect(question.min).to eq(0)
end
end

98
spec/models/form/sales/questions/mortgageused_spec.rb

@ -3,28 +3,39 @@ require "rails_helper"
RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch:) }
let(:ownershipsch) { 1 }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:)) }
let(:stairowned) { nil }
let(:staircase) { nil }
let(:saledate) { Time.zone.today }
let(:log) { build(:sales_log, :in_progress, ownershipsch:, stairowned:, staircase:) }
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
})
end
context "when the form start year is 2024" do
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:)) }
let(:saledate) { Time.zone.local(2024, 5, 1) }
let(:ownershipsch) { 1 }
before do
allow(form).to receive(:start_year_2024_or_later?).and_return true
allow(form).to receive(:start_year_2025_or_later?).and_return false
end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
})
end
describe "the displayed answer options" do
context "when it is a discounted ownership sale" do
let(:ownershipsch) { 2 }
it "shows the correct question number" do
expect(question.question_number).to eq 104
end
it "does not show the don't know option" do
expect_the_question_not_to_show_dont_know
end
@ -34,20 +45,14 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
let(:ownershipsch) { 3 }
context "and the saledate is before 24/25" do
before do
allow(form).to receive(:start_year_2024_or_later?).and_return false
end
let(:saledate) { Time.zone.local(2023, 5, 1) }\
it "does not show the don't know option" do
expect_the_question_not_to_show_dont_know
it "does show the don't know option" do
expect_the_question_to_show_dont_know
end
end
context "and the saledate is 24/25 or after" do
before do
allow(form).to receive(:start_year_2024_or_later?).and_return true
end
context "and the saledate is 24/25" do
it "shows the don't know option" do
expect_the_question_to_show_dont_know
end
@ -87,6 +92,57 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
end
end
context "when the form start year is 2025" do
let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 1)) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:)) }
let(:saledate) { Time.zone.local(2025, 5, 1) }
before do
allow(form).to receive(:start_year_2024_or_later?).and_return true
allow(form).to receive(:start_year_2025_or_later?).and_return true
end
context "when it is a discounted ownership sale" do
let(:ownershipsch) { 2 }
it "shows the correct question number" do
expect(question.question_number).to eq 104
end
it "does not show the don't know option" do
expect_the_question_not_to_show_dont_know
end
end
context "when it is a shared ownership scheme" do
let(:ownershipsch) { 1 }
context "and it is a staircasing transaction" do
let(:staircase) { 1 }
it "does show the don't know option" do
expect_the_question_to_show_dont_know
end
context "and stairowned is 100" do
let(:stairowned) { 100 }
it "shows the don't know option" do
expect_the_question_to_show_dont_know
end
end
end
context "and it is not a staircasing transaction" do
let(:staircase) { 2 }
it "does not show the don't know option" do
expect_the_question_not_to_show_dont_know
end
end
end
end
private
def expect_the_question_not_to_show_dont_know

33
spec/models/form/sales/questions/staircase_count_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::StaircaseCount, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("numstair")
end
it "has the correct type" do
expect(question.type).to eq("numeric")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has correct conditional for" do
expect(question.conditional_for).to eq(nil)
end
end

40
spec/models/form/sales/questions/staircase_first_time_spec.rb

@ -0,0 +1,40 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::StaircaseFirstTime, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("firststair")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
})
end
it "has correct conditional for" do
expect(question.conditional_for).to eq(nil)
end
end

33
spec/models/form/sales/questions/staircase_initial_date_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::StaircaseInitialDate, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("initialpurchase")
end
it "has the correct type" do
expect(question.type).to eq("date")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has correct conditional for" do
expect(question.conditional_for).to eq(nil)
end
end

33
spec/models/form/sales/questions/staircase_last_date_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::StaircaseLastDate, 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, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("lasttransaction")
end
it "has the correct type" do
expect(question.type).to eq("date")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
it "has correct conditional for" do
expect(question.conditional_for).to eq(nil)
end
end

4
spec/models/form/sales/questions/staircase_sale_spec.rb

@ -7,6 +7,10 @@ RSpec.describe Form::Sales::Questions::StaircaseSale, type: :model do
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
end
it "has correct page" do
expect(question.page).to eq(page)
end

6
spec/models/form/sales/questions/value_spec.rb

@ -5,7 +5,11 @@ RSpec.describe Form::Sales::Questions::Value, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
let(:page) { instance_double(Form::Page, id: "value_shared_ownership", subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
end
it "has correct page" do
expect(question.page).to eq(page)

11
spec/models/form/sales/sections/sale_information_spec.rb

@ -7,6 +7,10 @@ RSpec.describe Form::Sales::Sections::SaleInformation, type: :model do
let(:section_definition) { nil }
let(:form) { instance_double(Form, start_year_2025_or_later?: false) }
before do
allow(form).to receive(:start_year_2025_or_later?).and_return(false)
end
it "has correct form" do
expect(sale_information.form).to eq(form)
end
@ -22,11 +26,16 @@ RSpec.describe Form::Sales::Sections::SaleInformation, type: :model do
end
context "when form is 2025 or later" do
let(:form) { instance_double(Form, start_year_2025_or_later?: true) }
let(:form) { instance_double(Form) }
before do
allow(form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct subsections" do
expect(sale_information.subsections.map(&:id)).to eq(%w[
shared_ownership_initial_purchase
shared_ownership_staircasing_transaction
discounted_ownership_scheme
outright_sale
])

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

@ -30,7 +30,7 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipInitialPurchase, type: :
shared_ownership_previous_tenure
value_shared_ownership
about_price_shared_ownership_value_check
equity
initial_equity
shared_ownership_equity_value_check
mortgage_used_shared_ownership
mortgage_used_mortgage_value_check

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

@ -1407,4 +1407,44 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
end
end
describe "#validate_number_of_staircase_transactions" do
let(:record) { build(:sales_log, numstair:, firststair:) }
before do
sale_information_validator.validate_number_of_staircase_transactions(record)
end
context "when it is not the first staircasing transaction" do
context "and the number of staircasing transactions is between 2 and 10" do
let(:numstair) { 6 }
let(:firststair) { 2 }
it "does not add an error" do
expect(record.errors).to be_empty
end
end
context "and the number of staircasing transactions is less than 2" do
let(:numstair) { 1 }
let(:firststair) { 2 }
it "adds an error" do
expect(record.errors[:numstair]).to include(I18n.t("validations.sales.sale_information.numstair.must_be_greater_than_one"))
expect(record.errors[:firststair]).to include(I18n.t("validations.sales.sale_information.firststair.cannot_be_no"))
end
end
end
context "when it is the first staircasing transaction" do
context "and numstair is also 1" do
let(:numstair) { 1 }
let(:firststair) { 1 }
it "does not add an error" do
expect(record.errors).to be_empty
end
end
end
end
end

Loading…
Cancel
Save