Browse Source

Merge branch 'SalesFinancialValidationsCopy' into EquityDecimalPlace

pull/2746/head
Rachael Booth 8 months ago
parent
commit
6681071074
  1. 1
      app/models/form/lettings/pages/previous_housing_situation.rb
  2. 1
      app/models/form/lettings/pages/previous_housing_situation_renewal.rb
  3. 1
      app/models/form/lettings/pages/previous_local_authority.rb
  4. 1
      app/models/form/lettings/pages/previous_postcode.rb
  5. 1
      app/models/form/lettings/pages/reason_for_leaving_last_settled_home.rb
  6. 1
      app/models/form/lettings/pages/reason_for_leaving_last_settled_home_renewal.rb
  7. 1
      app/models/form/lettings/pages/referral.rb
  8. 1
      app/models/form/lettings/pages/referral_prp.rb
  9. 1
      app/models/form/lettings/pages/referral_supported_housing.rb
  10. 1
      app/models/form/lettings/pages/referral_supported_housing_prp.rb
  11. 2
      app/models/form/lettings/questions/declaration.rb
  12. 3
      app/models/form/lettings/questions/homeless.rb
  13. 3
      app/models/form/lettings/questions/layear.rb
  14. 3
      app/models/form/lettings/questions/letting_allocation.rb
  15. 4
      app/models/form/lettings/questions/ppcodenk.rb
  16. 4
      app/models/form/lettings/questions/ppostcode_full.rb
  17. 4
      app/models/form/lettings/questions/previous_la_known.rb
  18. 4
      app/models/form/lettings/questions/previous_tenure.rb
  19. 5
      app/models/form/lettings/questions/previous_tenure_renewal.rb
  20. 4
      app/models/form/lettings/questions/prevloc.rb
  21. 4
      app/models/form/lettings/questions/reason.rb
  22. 4
      app/models/form/lettings/questions/reason_renewal.rb
  23. 3
      app/models/form/lettings/questions/reasonable_preference_reason.rb
  24. 4
      app/models/form/lettings/questions/reasonother.rb
  25. 3
      app/models/form/lettings/questions/reasonpref.rb
  26. 4
      app/models/form/lettings/questions/referral.rb
  27. 4
      app/models/form/lettings/questions/referral_prp.rb
  28. 4
      app/models/form/lettings/questions/referral_supported_housing.rb
  29. 4
      app/models/form/lettings/questions/referral_supported_housing_prp.rb
  30. 2
      app/models/form/lettings/questions/rent_type.rb
  31. 3
      app/models/form/lettings/questions/waityear.rb
  32. 6
      app/models/form/sales/questions/privacy_notice.rb
  33. 10
      app/models/form/sales/questions/shared_ownership_type.rb
  34. 11
      app/models/forms/bulk_upload_lettings/upload_your_file.rb
  35. 11
      app/models/forms/bulk_upload_sales/upload_your_file.rb
  36. 48
      app/models/validations/sales/financial_validations.rb
  37. 28
      app/views/form/guidance/_discounted_ownership_type_definitions.erb
  38. 10
      app/views/form/guidance/_finding_location.erb
  39. 13
      app/views/form/guidance/_finding_scheme.erb
  40. 8
      app/views/form/guidance/_mortgage_lender.html.erb
  41. 13
      app/views/form/guidance/_outright_sale_type_definitions.erb
  42. 4
      app/views/form/guidance/_privacy_notice_buyer.erb
  43. 1
      app/views/form/guidance/_privacy_notice_buyer_2024.erb
  44. 1
      app/views/form/guidance/_privacy_notice_buyer_2024_joint_purchase.erb
  45. 4
      app/views/form/guidance/_privacy_notice_buyer_joint_purchase.erb
  46. 4
      app/views/form/guidance/_privacy_notice_tenant.erb
  47. 1
      app/views/form/guidance/_privacy_notice_tenant_2024.erb
  48. 26
      app/views/form/guidance/_rent_type_definitions.erb
  49. 21
      app/views/form/guidance/_rent_type_definitions_2024.erb
  50. 4
      app/views/form/guidance/_scheme_selection.html.erb
  51. 31
      app/views/form/guidance/_shared_ownership_type_definitions.erb
  52. 26
      app/views/form/guidance/_shared_ownership_type_definitions_2024.erb
  53. 14
      app/views/form/guidance/_void_date.html.erb
  54. 21
      app/views/form/guidance/_what_counts_as_income.html.erb
  55. 24
      config/locales/en.yml
  56. 63
      config/locales/forms/2023/lettings/guidance.en.yml
  57. 120
      config/locales/forms/2023/lettings/household_situation.en.yml
  58. 47
      config/locales/forms/2023/sales/guidance.en.yml
  59. 63
      config/locales/forms/2024/lettings/guidance.en.yml
  60. 120
      config/locales/forms/2024/lettings/household_situation.en.yml
  61. 46
      config/locales/forms/2024/sales/guidance.en.yml
  62. 81
      config/locales/validations/sales/financial.en.yml
  63. 19
      spec/features/bulk_upload_lettings_logs_spec.rb
  64. 20
      spec/features/bulk_upload_sales_logs_spec.rb
  65. 2
      spec/models/form/lettings/questions/declaration_spec.rb
  66. 2
      spec/models/form/lettings/questions/homeless_spec.rb
  67. 2
      spec/models/form/lettings/questions/reason_renewal_spec.rb
  68. 2
      spec/models/form/lettings/questions/reason_spec.rb
  69. 2
      spec/models/form/lettings/questions/rent_type_spec.rb
  70. 4
      spec/models/form/sales/questions/privacy_notice_spec.rb
  71. 2
      spec/models/form/sales/questions/shared_ownership_type_spec.rb
  72. 134
      spec/models/validations/sales/financial_validations_spec.rb
  73. 2
      spec/requests/form_controller_spec.rb
  74. 2
      spec/views/form/page_view_spec.rb

1
app/models/form/lettings/pages/previous_housing_situation.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::PreviousHousingSituation < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "previous_housing_situation"
@copy_key = "lettings.household_situation.prevten.not_renewal"
@depends_on = [{ "is_renewal?" => false }]
end

1
app/models/form/lettings/pages/previous_housing_situation_renewal.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::PreviousHousingSituationRenewal < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "previous_housing_situation_renewal"
@copy_key = "lettings.household_situation.prevten.renewal"
@depends_on = [{ "is_renewal?" => true, "is_supported_housing?" => true }]
end

1
app/models/form/lettings/pages/previous_local_authority.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::PreviousLocalAuthority < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "previous_local_authority"
@copy_key = "lettings.household_situation.previous_local_authority"
@depends_on = [{ "is_previous_la_inferred" => false, "renewal" => 0 }]
end

1
app/models/form/lettings/pages/previous_postcode.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::PreviousPostcode < ::Form::Page
def initialize(id, hsh, page)
super
@depends_on = [{ "renewal" => 0 }]
@copy_key = "lettings.household_situation.previous_postcode"
end
def questions

1
app/models/form/lettings/pages/reason_for_leaving_last_settled_home.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::ReasonForLeavingLastSettledHome < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "reason_for_leaving_last_settled_home"
@copy_key = "lettings.household_situation.reason.reason_for_leaving_last_settled_home"
@depends_on = [{ "renewal" => 0 }]
end

1
app/models/form/lettings/pages/reason_for_leaving_last_settled_home_renewal.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::ReasonForLeavingLastSettledHomeRenewal < ::Form::Pa
def initialize(id, hsh, subsection)
super
@id = "reason_for_leaving_last_settled_home_renewal"
@copy_key = "lettings.household_situation.reason.reason_for_leaving_last_settled_home_renewal"
@depends_on = [{ "renewal" => 1 }]
end

1
app/models/form/lettings/pages/referral.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::Referral < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral"
@copy_key = "lettings.household_situation.referral.general_needs.la"
@depends_on = [{ "owning_organisation_provider_type" => "LA", "needstype" => 1, "renewal" => 0 }]
end

1
app/models/form/lettings/pages/referral_prp.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::ReferralPrp < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_prp"
@copy_key = "lettings.household_situation.referral.general_needs.prp"
@depends_on = [{ "owning_organisation_provider_type" => "PRP", "needstype" => 1, "renewal" => 0 }]
end

1
app/models/form/lettings/pages/referral_supported_housing.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::ReferralSupportedHousing < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_supported_housing"
@copy_key = "lettings.household_situation.referral.supported_housing.la"
@depends_on = [{ "owning_organisation_provider_type" => "LA", "needstype" => 2, "renewal" => 0 }]
end

1
app/models/form/lettings/pages/referral_supported_housing_prp.rb

@ -2,6 +2,7 @@ class Form::Lettings::Pages::ReferralSupportedHousingPrp < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_supported_housing_prp"
@copy_key = "lettings.household_situation.referral.supported_housing.prp"
@depends_on = [{ "owning_organisation_provider_type" => "PRP", "needstype" => 2, "renewal" => 0 }]
end

2
app/models/form/lettings/questions/declaration.rb

@ -4,7 +4,7 @@ class Form::Lettings::Questions::Declaration < ::Form::Question
@id = "declaration"
@type = "checkbox"
@check_answers_card_number = 0 unless form.start_year_after_2024?
@top_guidance_partial = form.start_year_after_2024? ? "privacy_notice_tenant_2024" : "privacy_notice_tenant"
@top_guidance_partial = "privacy_notice_tenant"
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

3
app/models/form/lettings/questions/homeless.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::Homeless < ::Form::Question
def initialize(id, hsh, page)
super
@id = "homeless"
@check_answer_label = "Household homeless immediately before letting"
@header = "Did the household experience homelessness immediately before this letting?"
@type = "radio"
@check_answers_card_number = 0
@hint_text = ""
@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

3
app/models/form/lettings/questions/layear.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::Layear < ::Form::Question
def initialize(id, hsh, page)
super
@id = "layear"
@check_answer_label = "Length of time in local authority area"
@header = "How long has the household continuously lived in the local authority area of the new letting?"
@type = "radio"
@check_answers_card_number = 0
@hint_text = ""
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

3
app/models/form/lettings/questions/letting_allocation.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::LettingAllocation < ::Form::Question
def initialize(id, hsh, page)
super
@id = "letting_allocation"
@check_answer_label = "Allocation system"
@header = "How was this letting allocated?"
@type = "checkbox"
@check_answers_card_number = 0
@hint_text = "Select all that apply."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

4
app/models/form/lettings/questions/ppcodenk.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::Ppcodenk < ::Form::Question
def initialize(id, hsh, page)
super
@id = "ppcodenk"
@check_answer_label = ""
@header = "Do you know the postcode of the household’s last settled accommodation?"
@copy_key = "lettings.household_situation.previous_postcode.ppcodenk"
@type = "radio"
@check_answers_card_number = 0
@hint_text = form.start_year_after_2024? ? "This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless." : "This is also known as the household’s ‘last settled home’."
@answer_options = ANSWER_OPTIONS
@conditional_for = { "ppostcode_full" => [0] }
@hidden_in_check_answers = { "depends_on" => [{ "ppcodenk" => 0 }, { "ppcodenk" => 1 }] }

4
app/models/form/lettings/questions/ppostcode_full.rb

@ -2,8 +2,7 @@ class Form::Lettings::Questions::PpostcodeFull < ::Form::Question
def initialize(id, hsh, page)
super
@id = "ppostcode_full"
@check_answer_label = "Postcode of household’s last settled accommodation"
@header = "Postcode for the previous accommodation"
@copy_key = "lettings.household_situation.previous_postcode.ppostcode_full"
@type = "text"
@width = 5
@inferred_check_answers_value = [{
@ -13,7 +12,6 @@ class Form::Lettings::Questions::PpostcodeFull < ::Form::Question
"value" => "Not known",
}]
@check_answers_card_number = 0
@hint_text = ""
@inferred_answers = { "prevloc" => { "is_previous_la_inferred" => true } }
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@disable_clearing_if_not_routed_or_dynamic_answer_options = true

4
app/models/form/lettings/questions/previous_la_known.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::PreviousLaKnown < ::Form::Question
def initialize(id, hsh, page)
super
@id = "previous_la_known"
@check_answer_label = "Do you know the local authority of the household’s last settled accommodation?"
@header = "Do you know the local authority of the household’s last settled accommodation?"
@copy_key = "lettings.household_situation.previous_local_authority.previous_la_known"
@type = "radio"
@check_answers_card_number = 0
@hint_text = form.start_year_after_2024? ? "This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless." : "This is also known as the household’s ‘last settled home’."
@answer_options = ANSWER_OPTIONS
@conditional_for = { "prevloc" => [1] }
@hidden_in_check_answers = { "depends_on" => [{ "previous_la_known" => 0 }, { "previous_la_known" => 1 }] }

4
app/models/form/lettings/questions/previous_tenure.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::PreviousTenure < ::Form::Question
def initialize(id, hsh, page)
super
@id = "prevten"
@check_answer_label = "Where was the household immediately before this letting?"
@header = "Where was the household immediately before this letting?"
@copy_key = "lettings.household_situation.prevten.not_renewal"
@type = "radio"
@check_answers_card_number = 0
@hint_text = "This is where the household was the night before they moved into this new let."
@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

5
app/models/form/lettings/questions/previous_tenure_renewal.rb

@ -2,12 +2,9 @@ class Form::Lettings::Questions::PreviousTenureRenewal < ::Form::Question
def initialize(id, hsh, page)
super
@id = "prevten"
@check_answer_label = "Where was the household immediately before this letting?"
@header = "Where was the household immediately before this letting?"
@copy_key = "lettings.household_situation.prevten.renewal"
@type = "radio"
@check_answers_card_number = 0
@hint_text = "You told us this letting is a renewal. We have removed some options because of this.<br><br>
This is where the household was the night before they moved into this new let."
@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

4
app/models/form/lettings/questions/prevloc.rb

@ -2,12 +2,10 @@ class Form::Lettings::Questions::Prevloc < ::Form::Question
def initialize(id, hsh, page)
super
@id = "prevloc"
@check_answer_label = "Location of household’s last settled accommodation"
@header = "Select a local authority"
@copy_key = "lettings.household_situation.previous_local_authority.prevloc"
@type = "select"
@inferred_check_answers_value = [{ "condition" => { "previous_la_known" => 0 }, "value" => "Not known" }]
@check_answers_card_number = 0
@hint_text = "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end

4
app/models/form/lettings/questions/reason.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::Reason < ::Form::Question
def initialize(id, hsh, page)
super
@id = "reason"
@check_answer_label = "Reason for leaving last settled home"
@header = "What is the tenant’s main reason for the household leaving their last settled home?"
@copy_key = "lettings.household_situation.reason.#{page.id}.reason"
@type = "radio"
@check_answers_card_number = 0
@hint_text = form.start_year_after_2024? ? "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously." : "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously."
@conditional_for = {
"reasonother" => [
20,

4
app/models/form/lettings/questions/reason_renewal.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::ReasonRenewal < ::Form::Question
def initialize(id, hsh, page)
super
@id = "reason"
@check_answer_label = "Reason for leaving last settled home"
@header = "What is the tenant’s main reason for the household leaving their last settled home?"
@type = "radio"
@copy_key = "lettings.household_situation.reason.#{page.id}.reason"
@check_answers_card_number = 0
@hint_text = "You told us this letting is a renewal. We have removed some options because of this."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
@conditional_for = {
"reasonother" => [

3
app/models/form/lettings/questions/reasonable_preference_reason.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::ReasonablePreferenceReason < ::Form::Question
def initialize(id, hsh, page)
super
@id = "reasonable_preference_reason"
@check_answer_label = "Reason for reasonable preference"
@header = "Why was the household given ‘reasonable preference’?"
@type = "checkbox"
@check_answers_card_number = 0
@hint_text = "Select all that apply."
@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

4
app/models/form/lettings/questions/reasonother.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::Reasonother < ::Form::Question
def initialize(id, hsh, page)
super
@id = "reasonother"
@check_answer_label = ""
@header = "What is the reason?"
@copy_key = "lettings.household_situation.reason.#{@page.id}.reasonother"
@type = "text"
@check_answers_card_number = 0
@hint_text = ""
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

3
app/models/form/lettings/questions/reasonpref.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::Reasonpref < ::Form::Question
def initialize(id, hsh, page)
super
@id = "reasonpref"
@check_answer_label = "Household given reasonable preference"
@header = "Was the household given ‘reasonable preference’ by the local authority?"
@type = "radio"
@check_answers_card_number = 0
@hint_text = form.start_year_after_2024? ? "Households may be given ‘reasonable preference’ for social housing under one or more specific categories by the local authority. This is also known as ‘priority need’." : "Households may be given ‘reasonable preference’ for social housing, also known as ‘priority need’, by the local authority."
@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

4
app/models/form/lettings/questions/referral.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::Referral < ::Form::Question
def initialize(id, hsh, page)
super
@id = "referral"
@check_answer_label = "Source of referral for letting"
@header = "What was the source of referral for this letting?"
@copy_key = "lettings.household_situation.referral.general_needs.la"
@type = "radio"
@check_answers_card_number = 0
@hint_text = "You told us that you are a local authority and that the needs type is general needs. We have removed some options because of this."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

4
app/models/form/lettings/questions/referral_prp.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::ReferralPrp < ::Form::Question
def initialize(id, hsh, page)
super
@id = "referral"
@check_answer_label = "Source of referral for letting"
@header = "What was the source of referral for this letting?"
@copy_key = "lettings.household_situation.referral.general_needs.prp"
@type = "radio"
@check_answers_card_number = 0
@hint_text = "You told us that the needs type is general needs. We have removed some options because of this."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

4
app/models/form/lettings/questions/referral_supported_housing.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::ReferralSupportedHousing < ::Form::Question
def initialize(id, hsh, page)
super
@id = "referral"
@check_answer_label = "Source of referral for letting"
@header = "What was the source of referral for this letting?"
@copy_key = "lettings.household_situation.referral.supported_housing.la"
@type = "radio"
@check_answers_card_number = 0
@hint_text = "You told us that you are a local authority. We have removed some options because of this."
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

4
app/models/form/lettings/questions/referral_supported_housing_prp.rb

@ -2,11 +2,9 @@ class Form::Lettings::Questions::ReferralSupportedHousingPrp < ::Form::Question
def initialize(id, hsh, page)
super
@id = "referral"
@check_answer_label = "Source of referral for letting"
@header = "What was the source of referral for this letting?"
@copy_key = "lettings.household_situation.referral.supported_housing.prp"
@type = "radio"
@check_answers_card_number = 0
@hint_text = ""
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

2
app/models/form/lettings/questions/rent_type.rb

@ -4,7 +4,7 @@ class Form::Lettings::Questions::RentType < ::Form::Question
@id = "rent_type"
@copy_key = "lettings.setup.rent_type.rent_type"
@type = "radio"
@top_guidance_partial = form.start_year_after_2024? ? "rent_type_definitions_2024" : "rent_type_definitions"
@top_guidance_partial = "rent_type_definitions"
@answer_options = form.start_year_after_2024? ? ANSWER_OPTIONS_2024 : ANSWER_OPTIONS
@conditional_for = { "irproduct_other" => [5] }
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max] if form.start_date.present?

3
app/models/form/lettings/questions/waityear.rb

@ -2,11 +2,8 @@ class Form::Lettings::Questions::Waityear < ::Form::Question
def initialize(id, hsh, page)
super
@id = "waityear"
@check_answer_label = "Length of time on local authority waiting list"
@header = form.start_year_after_2024? ? "How long has the household been on the local authority waiting list for the area of the new letting?" : "How long has the household been on the local authority waiting list for the new letting?"
@type = "radio"
@check_answers_card_number = 0
@hint_text = ""
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end

6
app/models/form/sales/questions/privacy_notice.rb

@ -29,11 +29,7 @@ class Form::Sales::Questions::PrivacyNotice < ::Form::Question
end
def guidance
if form.start_year_after_2024?
@joint_purchase ? "privacy_notice_buyer_2024_joint_purchase" : "privacy_notice_buyer_2024"
else
@joint_purchase ? "privacy_notice_buyer_joint_purchase" : "privacy_notice_buyer"
end
@joint_purchase ? "privacy_notice_buyer_joint_purchase" : "privacy_notice_buyer"
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 19, 2024 => 14 }.freeze

10
app/models/form/sales/questions/shared_ownership_type.rb

@ -3,7 +3,7 @@ class Form::Sales::Questions::SharedOwnershipType < ::Form::Question
super
@id = "type"
@copy_key = "sales.setup.type.shared_ownership"
@top_guidance_partial = guidance_partial
@top_guidance_partial = "shared_ownership_type_definitions"
@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]
@ -34,13 +34,5 @@ class Form::Sales::Questions::SharedOwnershipType < ::Form::Question
end
end
def guidance_partial
if form.start_year_after_2024?
"shared_ownership_type_definitions_2024"
elsif form.start_date.year >= 2023
"shared_ownership_type_definitions"
end
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 4, 2024 => 6 }.freeze
end

11
app/models/forms/bulk_upload_lettings/upload_your_file.rb

@ -15,6 +15,7 @@ module Forms
validates :file, presence: true
validate :validate_file_is_csv
validate :validate_file_size
def view_path
"bulk_upload_lettings_logs/forms/upload_your_file"
@ -73,6 +74,16 @@ module Forms
errors.add(:file, :not_csv)
end
end
MAX_FILE_SIZE = 10.megabytes
def validate_file_size
return unless file
if file.size > MAX_FILE_SIZE
errors.add(:file, :file_too_large)
end
end
end
end
end

11
app/models/forms/bulk_upload_sales/upload_your_file.rb

@ -14,6 +14,7 @@ module Forms
validates :file, presence: true
validate :validate_file_is_csv
validate :validate_file_size
def view_path
"bulk_upload_sales_logs/forms/upload_your_file"
@ -67,6 +68,16 @@ module Forms
errors.add(:file, :not_csv)
end
end
MAX_FILE_SIZE = 10.megabytes
def validate_file_size
return unless file
if file.size > MAX_FILE_SIZE
errors.add(:file, :file_too_large)
end
end
end
end
end

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

@ -7,9 +7,9 @@ module Validations::Sales::FinancialValidations
relevant_fields = %i[income1 ownershipsch uprn la postcode_full]
if record.london_property? && !record.income1.between?(0, 90_000)
relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") }
relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_london_income_range") }
elsif record.property_not_in_london? && !record.income1.between?(0, 80_000)
relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") }
relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_non_london_income_range") }
end
end
@ -18,9 +18,9 @@ module Validations::Sales::FinancialValidations
relevant_fields = %i[income2 ownershipsch uprn la postcode_full]
if record.london_property? && !record.income2.between?(0, 90_000)
relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") }
relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_london_income_range") }
elsif record.property_not_in_london? && !record.income2.between?(0, 80_000)
relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") }
relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_non_london_income_range") }
end
end
@ -30,25 +30,26 @@ module Validations::Sales::FinancialValidations
combined_income = record.income1 + record.income2
relevant_fields = %i[income1 income2 ownershipsch uprn la postcode_full]
if record.london_property? && combined_income > 90_000
relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_london") }
relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_london, message: I18n.t("validations.sales.financial.#{field}.combined_over_hard_max_for_london") }
elsif record.property_not_in_london? && combined_income > 80_000
relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_outside_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london") }
relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_outside_london, message: I18n.t("validations.sales.financial.#{field}.combined_over_hard_max_for_outside_london") }
end
end
def validate_mortgage(record)
record.errors.add :mortgage, :cannot_be_0, message: I18n.t("validations.financial.mortgage") if record.mortgage_used? && record.mortgage&.zero?
record.errors.add :mortgage, :cannot_be_0, message: I18n.t("validations.sales.financial.mortgage.mortgage_zero") if record.mortgage_used? && record.mortgage&.zero?
end
def validate_monthly_leasehold_charges(record)
record.errors.add :mscharge, I18n.t("validations.financial.monthly_leasehold_charges.not_zero") if record.mscharge&.zero?
record.errors.add :mscharge, I18n.t("validations.sales.financial.mscharge.monthly_leasehold_charges.not_zero") if record.mscharge&.zero?
end
def validate_percentage_bought_not_greater_than_percentage_owned(record)
return unless record.stairbought && record.stairowned
if record.stairbought > record.stairowned
record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_must_be_greater_than_percentage_owned", buyer_now_owns: record.joint_purchase? ? "buyers now own" : "buyer now owns")
joint_purchase_id = record.joint_purchase? ? "joint_purchase" : "not_joint_purchase"
record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.#{joint_purchase_id}")
end
end
@ -57,8 +58,8 @@ module Validations::Sales::FinancialValidations
return unless record.saledate && record.form.start_year_after_2024?
if record.stairbought == record.stairowned
record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
end
end
@ -72,8 +73,8 @@ module Validations::Sales::FinancialValidations
end
if threshold && record.stairbought < threshold
record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_must_be_at_least_threshold", threshold:)
record.errors.add :type, I18n.t("validations.setup.type.percentage_bought_must_be_at_least_threshold", threshold:)
record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold:)
record.errors.add :type, I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold:)
end
end
@ -81,8 +82,8 @@ module Validations::Sales::FinancialValidations
return unless record.income2 && record.ecstat2
if record.income2.positive? && is_economic_status_child?(record.ecstat2) && record.form.start_date.year >= 2023
record.errors.add :ecstat2, I18n.t("validations.financial.income.child_has_income")
record.errors.add :income2, I18n.t("validations.financial.income.child_has_income")
record.errors.add :ecstat2, I18n.t("validations.sales.financial.ecstat2.child_has_income")
record.errors.add :income2, I18n.t("validations.sales.financial.income2.child_has_income")
end
end
@ -94,12 +95,12 @@ module Validations::Sales::FinancialValidations
return unless (range = ranges[record.type])
if record.equity < range.min
record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min)
record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min)
record.errors.add :type, I18n.t("validations.sales.financial.type.equity_under_min", min_equity: range.min)
record.errors.add :equity, :under_min, message: I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: range.min)
elsif !record.is_resale? && record.equity > range.max
record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :resale, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
record.errors.add :type, I18n.t("validations.sales.financial.type.equity_over_max", max_equity: range.max)
record.errors.add :equity, :over_max, message: I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: range.max)
record.errors.add :resale, I18n.t("validations.sales.financial.resale.equity_over_max", max_equity: range.max)
end
end
@ -109,9 +110,10 @@ module Validations::Sales::FinancialValidations
if record.equity > record.stairowned - record.stairbought
formatted_equity = sprintf("%g", record.equity)
record.errors.add :equity, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
record.errors.add :stairowned, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
record.errors.add :stairbought, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
joint_purchase_id = record.joint_purchase? ? "joint_purchase" : "not_joint_purchase"
record.errors.add :equity, I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought)
end
end

28
app/views/form/guidance/_discounted_ownership_type_definitions.erb

@ -1,23 +1,5 @@
<%= govuk_details(summary_text: "Discounted ownership type definitions") do %>
<p class="govuk-body">
<b>Right to Acquire (RTA):</b> a discounted sale of a property built or purchased after 31 March 1997 to tenants of a private registered provider.
</p>
<p class="govuk-body">
<b>Preserved Right to Buy (PRTB):</b> a discounted sale of a property that used to be owned by a council to tenants of a private registered provider.
</p>
<p class="govuk-body">
<b>Voluntary Right to Buy (VRTB):</b> a discounted sale to tenants in this PRP owned property, as part of a pilot scheme.
</p>
<p class="govuk-body">
<b>Right to Buy (RTB):</b> a discounted sale to tenants in this council owned property.
</p>
<p class="govuk-body">
<b>Rent to Buy full ownership:</b> a sale on full ownership terms following a period of discounted rent.
</p>
<p class="govuk-body">
<b>Social HomeBuy for outright purchase:</b> a discounted sale to tenants of a private registered provider on full ownership terms.
</p>
<p class="govuk-body">
<b>Any other equity loan scheme:</b> any scheme, not covered elsewhere, in which a loan is used to purchase equity.
</p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.discounted_ownership_type_definitions.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.discounted_ownership_type_definitions.content").html_safe %>
<% end %>
</div>

10
app/views/form/guidance/_finding_location.erb

@ -1,4 +1,6 @@
<%= govuk_details(summary_text: "What is a location?") do %>
<p class="govuk-body">A location is a postcode area where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode.</p>
<p class="govuk-body"><%= govuk_link_to("Read more about schemes and locations", scheme_changes_path) %></p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_location.title")) do %>
<p><%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_location.content").html_safe %></p>
<p><%= govuk_link_to(I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_location.scheme_changes_link_text"), scheme_changes_path) %></p>
<% end %>
</div>

13
app/views/form/guidance/_finding_scheme.erb

@ -1,6 +1,7 @@
<%= govuk_details(summary_text: "Can’t find your scheme?") do %>
<p class="govuk-body">Schemes are attached to the organisation that owns the property. Check you have correctly answered question 1 "Which organisation owns this property?"</p>
<p class="govuk-body">If your organisation’s schemes were migrated from old CORE, they may have new names and codes. Search by postcode to find your scheme.</p>
<p class="govuk-body"><%= govuk_link_to("View your organisation’s schemes", clear_filters_url(filter_type: "schemes")) %></p>
<p class="govuk-body"><%= govuk_link_to("Read more about how schemes have changed", scheme_changes_path) %></p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_scheme.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_scheme.content").html_safe %>
<p><%= govuk_link_to(I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_scheme.view_schemes_link_text"), clear_filters_url(filter_type: "schemes")) %></p>
<p><%= govuk_link_to(I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.finding_scheme.scheme_changes_link_text"), scheme_changes_path) %></p>
<% end %>
</div>

8
app/views/form/guidance/_mortgage_lender.html.erb

@ -1,7 +1,3 @@
<%= govuk_details(summary_text: "Can’t find the mortgage lender you’re looking for?") do %>
<ul class="govuk-list govuk-list--bullet">
<li>Double check the spelling and try again</li>
<li>Type the first few letters to see the suggestions</li>
<li>Type Other and continue - we’ll ask you to type in your answer in the next question</li>
</ul>
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.mortgage_lender.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.mortgage_lender.content").html_safe %>
<% end %>

13
app/views/form/guidance/_outright_sale_type_definitions.erb

@ -1,8 +1,5 @@
<%= govuk_details(summary_text: "Outright sale type definitions") do %>
<p class="govuk-body">
<b>Outright sale:</b> the full purchase of a property, usually with a mortgage or cash.
</p>
<p class="govuk-body">
<b>Other sale:</b> any sale which does not fit the criteria of any of the remaining options.
</p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.outright_sale_type_definitions.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.outright_sale_type_definitions.content").html_safe %>
<% end %>
</div>

4
app/views/form/guidance/_privacy_notice_buyer.erb

@ -1 +1,3 @@
<p class="govuk-body">Make sure the buyer has seen <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log.</p>
<p class="govuk-body">
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.privacy_notice_buyer.content", privacy_notice_link: "#{govuk_link_to I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.privacy_notice_buyer.privacy_notice_link_text"), privacy_notice_path, target: :_blank}").html_safe %>
</p>

1
app/views/form/guidance/_privacy_notice_buyer_2024.erb

@ -1 +0,0 @@
<p class="govuk-body">Make sure the buyer has seen or been given access to <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log. This is a legal requirement under data protection legislation.</p>

1
app/views/form/guidance/_privacy_notice_buyer_2024_joint_purchase.erb

@ -1 +0,0 @@
<p class="govuk-body">Make sure the buyers have seen or been given access to <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log. This is a legal requirement under data protection legislation.</p>

4
app/views/form/guidance/_privacy_notice_buyer_joint_purchase.erb

@ -1 +1,3 @@
<p class="govuk-body">Make sure the buyers have seen <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log.</p>
<p class="govuk-body">
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.privacy_notice_buyer_joint_purchase.content", privacy_notice_link: "#{govuk_link_to I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.privacy_notice_buyer_joint_purchase.privacy_notice_link_text"), privacy_notice_path, target: :_blank}").html_safe %>
</p>

4
app/views/form/guidance/_privacy_notice_tenant.erb

@ -1 +1,3 @@
<p class="govuk-body">Make sure the tenant has seen <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log.</p>
<p class="govuk-body">
<%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.privacy_notice_tenant.content", privacy_notice_link: "#{govuk_link_to I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.privacy_notice_tenant.privacy_notice_link_text"), privacy_notice_path, target: :_blank}").html_safe %>
</p>

1
app/views/form/guidance/_privacy_notice_tenant_2024.erb

@ -1 +0,0 @@
<p class="govuk-body">Make sure the lead tenant has seen or been given access to <%= govuk_link_to "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice", privacy_notice_path, target: :_blank %> before completing this log. This is a legal requirement under data protection legislation.</p>

26
app/views/form/guidance/_rent_type_definitions.erb

@ -1,21 +1,5 @@
<%= govuk_details(summary_text: "Rent type definitions") do %>
<p class="govuk-body">
<b>Affordable Rent:</b> where up to 80% of market rent can be charged. A new supply agreement is signed with Homes England or the Greater London Authority (GLA).
</p>
<p class="govuk-body">
<b>London Affordable Rent:</b> a tenure of affordable housing available in London by the GLA. It is an affordable rent which must be set in accordance with the Regulator of Social Housing’s Affordable Rent guidance. The landlord of these homes must be registered with the Regulator of Social Housing. These are a type of Affordable Rent lettings.
</p>
<p class="govuk-body">
<b>London Living Rent:</b> a tenure of affordable housing available in London by the GLA. It was introduced in Affordable Homes Programme 2016 to 2021. These are a type of Intermediate Rent lettings.
</p>
<p class="govuk-body">
<b>Rent to Buy: </b> a discount of up to 20% market rent is charged for a single rental period for a minimum of 5 years. After that period, the tenant is offered first chance to purchase the property (either shared ownership or outright) at full market value. These are a type of Intermediate Rent lettings.
</p>
<p class="govuk-body">
<b>Social Rent:</b> where target rents are determined through the national rent regime. This is sometimes also known as 'formula rent'.
</p>
<p class="govuk-body">
<b>Other intermediate rent:</b> any other specific scheme where up to 80% of market rent can be charged. This includes schemes with reduced rent so tenants can save towards a house purchasing deposit and schemes with an in-built future opportunity to buy the property being rented.
</p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.rent_type_definitions.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.rent_type_definitions.content").html_safe %>
<% end %>
</div>

21
app/views/form/guidance/_rent_type_definitions_2024.erb

@ -1,21 +0,0 @@
<%= govuk_details(summary_text: "Rent type definitions") do %>
<p class="govuk-body">
<b>Social Rent:</b> where target rents are determined through the national rent regime. This is sometimes also known as 'formula rent'.
</p>
<p class="govuk-body">
<b>Affordable Rent:</b> where up to 80% of market rent can be charged. A new supply agreement is signed with Homes England or the Greater London Authority (GLA).
</p>
<p class="govuk-body">
<b>London Affordable Rent:</b> a tenure of affordable housing available in London by the GLA. It is an affordable rent which must be set in accordance with the Regulator of Social Housing’s Affordable Rent guidance. The landlord of these homes must be registered with the Regulator of Social Housing. These are a type of Affordable Rent lettings.
</p>
<p class="govuk-body">
<b>Rent to Buy: </b> a discount of up to 20% market rent is charged for a single rental period for a minimum of 5 years. After that period, the tenant is offered first chance to purchase the property (either shared ownership or outright) at full market value. These are a type of Intermediate Rent lettings.
</p>
<p class="govuk-body">
<b>London Living Rent:</b> a tenure of affordable housing available in London by the GLA. It was introduced in Affordable Homes Programme 2016 to 2021. These are a type of Intermediate Rent lettings.
</p>
<p class="govuk-body">
<b>Other intermediate rent:</b> any other specific scheme where up to 80% of market rent can be charged. This includes schemes with reduced rent so tenants can save towards a house purchasing deposit and schemes with an in-built future opportunity to buy the property being rented.
</p>
<% end %>

4
app/views/form/guidance/_scheme_selection.html.erb

@ -1,5 +1,5 @@
<% if current_user.data_provider? %>
<p class="govuk-body">If you’re not sure which scheme to choose, ask a data coordinator. Find your data coordinators on the <%= govuk_link_to("users page", users_path) %>.</p>
<p class="govuk-body"><%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.scheme_selection.data_provider.content", users_page_link: govuk_link_to(I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.scheme_selection.data_provider.users_page_link_text"), users_path).to_s).html_safe %></p>
<% elsif current_user.data_coordinator? %>
<p class="govuk-body"><%= govuk_link_to "Create a new supported housing scheme", new_scheme_path %></p>
<p class="govuk-body"><%= govuk_link_to I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.scheme_selection.data_coordinator.create_scheme_link_text"), new_scheme_path %></p>
<% end %>

31
app/views/form/guidance/_shared_ownership_type_definitions.erb

@ -1,26 +1,5 @@
<%= govuk_details(summary_text: "Shared ownership type definitions") do %>
<p class="govuk-body">
<b>Shared ownership:</b> Cannot be used for homes funded through the Affordable Homes Programme 2021 to 2026. Use the 2021 model lease for these properties.
</p>
<p class="govuk-body">
<b>Shared ownership 2021 model lease:</b> Homes bought using the Affordable Homes Programme 2021 to 2026.
</p>
<p class="govuk-body">
<b>Older Persons Shared Ownership:</b> A type of shared ownership for those 55 years and over.
</p>
<p class="govuk-body">
<b>Social HomeBuy shared ownership purchase:</b> Tenants of private registered providers purchase their home at discount on Shared Ownership terms.
</p>
<p class="govuk-body">
<b>Home Ownership for people with Long-Term Disabilities (HOLD):</b> A shared ownership sale for those with long term disabilities.
</p>
<p class="govuk-body">
<b>Rent to Buy shared ownership:</b> A sale following a period of discounted rent.
</p>
<p class="govuk-body">
<b>Right to Shared Ownership:</b> A sale of a share of a rented home to a tenant using this scheme.
</p>
<p class="govuk-body">
<b>London Living Rent shared ownership:</b> A shared ownership sale following a period of discounted rent as part of the London Living Rent scheme.
</p>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.shared_ownership_type_definitions.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.shared_ownership_type_definitions.content").html_safe %>
<% end %>
</div>

26
app/views/form/guidance/_shared_ownership_type_definitions_2024.erb

@ -1,26 +0,0 @@
<%= govuk_details(summary_text: "Shared ownership type definitions") do %>
<p class="govuk-body">
<b>Shared Ownership (old model lease):</b> Cannot be used for homes funded through the Affordable Homes Programme 2021 to 2026. Use the new model lease for these properties.
</p>
<p class="govuk-body">
<b>Shared Ownership (new model lease):</b> Homes bought using the Affordable Homes Programme 2021 to 2026.
</p>
<p class="govuk-body">
<b>Social HomeBuy — shared ownership purchase:</b> Tenants of private registered providers purchase their home at discount on Shared Ownership terms.
</p>
<p class="govuk-body">
<b>Home Ownership for people with Long-Term Disabilities (HOLD):</b> A shared ownership sale for those with long term disabilities.
</p>
<p class="govuk-body">
<b>Older Persons Shared Ownership:</b> A type of shared ownership for those 55 years and over.
</p>
<p class="govuk-body">
<b>Rent to Buy — Shared Ownership:</b> A sale following a period of discounted rent.
</p>
<p class="govuk-body">
<b>Right to Shared Ownership (RtSO):</b> A sale of a share of a rented home to a tenant using this scheme.
</p>
<p class="govuk-body">
<b>London Living Rent — Shared Ownership:</b> A shared ownership sale following a period of discounted rent as part of the London Living Rent scheme.
</p>
<% end %>

14
app/views/form/guidance/_void_date.html.erb

@ -1,9 +1,5 @@
<%= govuk_details(summary_text: "What is a void date?") do %>
<p class="govuk-body">Date the property was (legally or contractually) available to let, or for:</p>
<ul class="govuk-list govuk-list--bullet">
<li>re-lets: the day after the previous tenant's contract ended</li>
<li>new builds: the day the landlord legally first owned the property (‘completion date’)</li>
<li>new conversions or acquisitions: completion date, or the day after rehabilitation work ended</li>
<li>new leases: the day the landlord got contractual property rights and could let it out to tenants</li>
</ul>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.void_date.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.void_date.content").html_safe %>
<% end %>
</div>

21
app/views/form/guidance/_what_counts_as_income.html.erb

@ -1,16 +1,5 @@
<%= govuk_details(summary_text: "What counts as income?") do %>
<p class="govuk-body">You should include any income after tax from:</p>
<ul class="govuk-list govuk-list--bullet">
<li>employment</li>
<li>pensions</li>
<li>Universal Credit</li>
</ul>
<p class="govuk-body">Don’t include:</p>
<ul class="govuk-list govuk-list--bullet">
<li>National Insurance (NI) contributions and tax</li>
<li>housing benefit</li>
<li>child benefit</li>
<li>council tax support</li>
</ul>
<% end %>
<div class="govuk-body">
<%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.what_counts_as_income.title")) do %>
<%= I18n.t("forms.#{@log.form.start_date.year}.lettings.guidance.what_counts_as_income.content").html_safe %>
<% end %>
</div>

24
config/locales/en.yml

@ -90,11 +90,13 @@ en:
file:
blank: "Select which file to upload."
not_csv: "Your file must be in CSV format."
file_too_large: "File must be 10MB or less. Check your file and delete data that does not need to be uploaded."
forms/bulk_upload_sales/upload_your_file:
attributes:
file:
blank: "Select which file to upload."
not_csv: "Your file must be in CSV format."
file_too_large: "File must be 10MB or less. Check your file and delete data that does not need to be uploaded."
forms/bulk_upload_lettings/needstype:
attributes:
needstype:
@ -283,8 +285,6 @@ en:
setup:
saledate:
year_not_two_or_four_digits: "Sale completion year must be 2 or 4 digits."
type:
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type."
startdate:
before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme."
@ -356,12 +356,6 @@ en:
under_hard_min: "The household’s income cannot be less than %{hard_min} per week given the household’s working situation."
freq_missing: "Select how often the household receives income."
earnings_missing: "Enter how much income the household has in total."
income:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
child_has_income: "Child's income must be £0."
negative_currency: "Enter an amount above 0."
rent:
out_of_range: "Enter a value for the %{charge_name} between £0 and %{maximum_per_period} paid %{frequency}. %{maximum_per_period} is the max limit for rent and charges paid %{frequency} for %{letting_type} lettings owned by a %{provider_type}."
@ -419,17 +413,9 @@ en:
not_provided: "Enter how much rent and other charges the household pays %{period}."
less_than_shortfall: "The care home charge must be more than the outstanding amount."
cash_discount_invalid: "Cash discount must be £0 - £999,999."
staircasing:
percentage_bought_must_be_greater_than_percentage_owned: "Total percentage %{buyer_now_owns} must be more than percentage bought in this transaction."
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}%."
percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same."
monthly_leasehold_charges:
not_zero: "Monthly leasehold charges cannot be £0 if the property has monthly charges."
equity:
under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%."
over_max: "The maximum initial equity stake is %{max_equity}%."
over_stairowned_minus_stairbought: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the %{buyer_owns} minus the percentage bought."
mortgage: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property."
mortgage_used:
year: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for the selected year."
staircasing: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions."
shared_ownership_deposit: "The %{mortgage_deposit_and_discount_error_fields} added together is %{mortgage_deposit_and_discount_total}. The value times the equity percentage is %{value_times_equity}. These figures should be the same."
household:

63
config/locales/forms/2023/lettings/guidance.en.yml

@ -0,0 +1,63 @@
en:
forms:
2023:
lettings:
guidance:
finding_location:
title: "What is a location?"
content: "A location is a postcode area where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode."
scheme_changes_link_text: "Read more about schemes and locations"
finding_scheme:
title: "Can’t find your scheme?"
content: "<p>Schemes are attached to the organisation that owns the property. Check you have correctly answered question 1 \"Which organisation owns this property?\"</p>
<p>If your organisation’s schemes were migrated from old CORE, they may have new names and codes. Search by postcode to find your scheme.</p>"
scheme_changes_link_text: "Read more about how schemes have changed"
view_schemes_link_text: "View your organisation’s schemes"
privacy_notice_tenant:
content: "Make sure the tenant has seen %{privacy_notice_link} before completing this log."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
rent_type_definitions:
title: "Rent type definitions"
content: "<p><b>Affordable Rent:</b> where up to 80% of market rent can be charged. A new supply agreement is signed with Homes England or the Greater London Authority (GLA).</p>
<p><b>London Affordable Rent:</b> a tenure of affordable housing available in London by the GLA. It is an affordable rent which must be set in accordance with the Regulator of Social Housing’s Affordable Rent guidance. The landlord of these homes must be registered with the Regulator of Social Housing. These are a type of Affordable Rent lettings.</p>
<p><b>London Living Rent:</b> a tenure of affordable housing available in London by the GLA. It was introduced in Affordable Homes Programme 2016 to 2021. These are a type of Intermediate Rent lettings.</p>
<p><b>Rent to Buy: </b> a discount of up to 20% market rent is charged for a single rental period for a minimum of 5 years. After that period, the tenant is offered first chance to purchase the property (either shared ownership or outright) at full market value. These are a type of Intermediate Rent lettings.</p>
<p><b>Social Rent:</b> where target rents are determined through the national rent regime. This is sometimes also known as 'formula rent'.</p>
<p><b>Other intermediate rent:</b> any other specific scheme where up to 80% of market rent can be charged. This includes schemes with reduced rent so tenants can save towards a house purchasing deposit and schemes with an in-built future opportunity to buy the property being rented.</p>"
scheme_selection:
data_provider:
content: "If you’re not sure which scheme to choose, ask a data coordinator. Find your data coordinators on the %{users_page_link}."
users_page_link_text: "users page"
data_coordinator:
create_scheme_link_text: "Create a new supported housing scheme"
void_date:
title: "What is a void date?"
content: "<p>Date the property was (legally or contractually) available to let, or for:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>re-lets: the day after the previous tenant's contract ended</li>
<li>new builds: the day the landlord legally first owned the property (‘completion date’)</li>
<li>new conversions or acquisitions: completion date, or the day after rehabilitation work ended</li>
<li>new leases: the day the landlord got contractual property rights and could let it out to tenants</li>
</ul>"
what_counts_as_income:
title: "What counts as income?"
content: "<p>You should include any income after tax from:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>employment</li>
<li>pensions</li>
<li>Universal Credit</li>
</ul>
<p>Don’t include:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>National Insurance (NI) contributions and tax</li>
<li>housing benefit</li>
<li>child benefit</li>
<li>council tax support</li>
</ul>"

120
config/locales/forms/2023/lettings/household_situation.en.yml

@ -0,0 +1,120 @@
en:
forms:
2023:
lettings:
household_situation:
layear:
page_header: ""
check_answer_label: "Length of time in local authority area"
hint_text: ""
question_text: "How long has the household continuously lived in the local authority area of the new letting?"
waityear:
page_header: ""
check_answer_label: "Length of time on local authority waiting list"
hint_text: ""
question_text: "How long has the household been on the local authority waiting list for the new letting?"
reason:
reason_for_leaving_last_settled_home_renewal:
page_header: ""
reason:
check_answer_label: "Reason for leaving last settled home"
hint_text: "You told us this letting is a renewal. We have removed some options because of this."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: "Length of time on local authority waiting list"
hint_text: ""
question_text: "How long has the household been on the local authority waiting list for the new letting?"
reason_for_leaving_last_settled_home:
page_header: ""
reason:
check_answer_label: "Reason for leaving last settled home"
hint_text: "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: ""
hint_text: ""
question_text: "What is the reason?"
prevten:
renewal:
page_header: ""
check_answer_label: "Where was the household immediately before this letting?"
hint_text: "You told us this letting is a renewal. We have removed some options because of this.<br><br>This is where the household was the night before they moved into this new let."
question_text: "Where was the household immediately before this letting?"
not_renewal:
page_header: ""
check_answer_label: "Where was the household immediately before this letting?"
hint_text: "This is where the household was the night before they moved into this new let."
question_text: "Where was the household immediately before this letting?"
homeless:
page_header: ""
check_answer_label: "Household homeless immediately before letting"
hint_text: ""
question_text: "Did the household experience homelessness immediately before this letting?"
previous_postcode:
page_header: ""
ppcodenk:
check_answer_label: ""
hint_text: "This is also known as the household’s ‘last settled home’."
question_text: "Do you know the postcode of the household’s last settled accommodation?"
ppostcode_full:
check_answer_label: "Postcode of household’s last settled accommodation"
hint_text: ""
question_text: "Postcode for the previous accommodation"
previous_local_authority:
page_header: ""
previous_la_known:
check_answer_label: ""
hint_text: "This is also known as the household’s ‘last settled home’."
question_text: "Do you know the local authority of the household’s last settled accommodation?"
prevloc:
check_answer_label: "Location of household’s last settled accommodation"
hint_text: "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England."
question_text: "Select a local authority"
reasonpref:
page_header: ""
check_answer_label: "Household given reasonable preference"
hint_text: "Households may be given ‘reasonable preference’ for social housing, also known as ‘priority need’, by the local authority."
question_text: "Was the household given ‘reasonable preference’ by the local authority?"
reasonable_preference_reason:
page_header: ""
check_answer_label: "Reason for reasonable preference"
hint_text: "Select all that apply."
question_text: "Why was the household given ‘reasonable preference’?"
letting_allocation:
page_header: ""
check_answer_label: "Allocation system"
hint_text: "Select all that apply."
question_text: "How was this letting allocated?"
referral:
supported_housing:
prp:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: ""
question_text: "What was the source of referral for this letting?"
la:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that you are a local authority. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"
general_needs:
prp:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that the needs type is general needs. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"
la:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that you are a local authority and that the needs type is general needs. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"

47
config/locales/forms/2023/sales/guidance.en.yml

@ -0,0 +1,47 @@
en:
forms:
2023:
sales:
guidance:
shared_ownership_type_definitions:
title: "Shared Ownership Type Definitions"
content: "<p><b>Shared ownership:</b> Cannot be used for homes funded through the Affordable Homes Programme 2021 to 2026. Use the 2021 model lease for these properties.</p>
<p><b>Shared ownership 2021 model lease:</b> Homes bought using the Affordable Homes Programme 2021 to 2026.</p>
<p><b>Older Persons Shared Ownership:</b> A type of shared ownership for those 55 years and over.</p>
<p><b>Social HomeBuy shared ownership purchase:</b> Tenants of private registered providers purchase their home at discount on Shared Ownership terms.</p>
<p>>Home Ownership for people with Long-Term Disabilities (HOLD):</b> A shared ownership sale for those with long term disabilities.</p>
<p><b>Rent to Buy shared ownership:</b> A sale following a period of discounted rent.</p>
<p><b>Right to Shared Ownership:</b> A sale of a share of a rented home to a tenant using this scheme.</p>
<p><b>London Living Rent shared ownership:</b> A shared ownership sale following a period of discounted rent as part of the London Living Rent scheme.</p>"
discounted_ownership_type_definitions:
title: "Discounted Ownership Type Definitions"
content: "<p><b>Right to Acquire (RTA):</b> a discounted sale of a property built or purchased after 31 March 1997 to tenants of a private registered provider.</p>
<p><b>Preserved Right to Buy (PRTB):</b> a discounted sale of a property that used to be owned by a council to tenants of a private registered provider.</p>
<p><b>Voluntary Right to Buy (VRTB):</b> a discounted sale to tenants in this PRP owned property, as part of a pilot scheme.</p>
<p><b>Right to Buy (RTB):</b> a discounted sale to tenants in this council owned property.</p>
<p><b>Rent to Buy full ownership:</b> a sale on full ownership terms following a period of discounted rent.</p>
<p><b>Social HomeBuy for outright purchase:</b> a discounted sale to tenants of a private registered provider on full ownership terms.</p>
<p><b>Any other equity loan scheme:</b> any scheme, not covered elsewhere, in which a loan is used to purchase equity.</p>"
mortgage_lender:
title: "Can’t find the mortgage lender you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Double check the spelling and try again</li>
<li>Type the first few letters to see the suggestions</li>
<li>Type Other and continue - we’ll ask you to type in your answer in the next question</li>
</ul>"
outright_sale_type_definitions:
title: "Outright sale type definitions"
content: "<p><b>Outright sale:</b> the full purchase of a property, usually with a mortgage or cash.</p>
<p><b>Other sale:</b> any sale which does not fit the criteria of any of the remaining options.</p>"
privacy_notice_buyer_joint_purchase:
content: "Make sure the buyers have seen %{privacy_notice_link} before completing this log."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
privacy_notice_buyer:
content: "Make sure the buyer has seen %{privacy_notice_link} before completing this log."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"

63
config/locales/forms/2024/lettings/guidance.en.yml

@ -0,0 +1,63 @@
en:
forms:
2024:
lettings:
guidance:
finding_location:
title: "What is a location?"
content: "A location is a postcode area where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode."
scheme_changes_link_text: "Read more about schemes and locations"
finding_scheme:
title: "Can’t find your scheme?"
content: "<p>Schemes are attached to the organisation that owns the property. Check you have correctly answered question 1 \"Which organisation owns this property?\"</p>
<p>If your organisation’s schemes were migrated from old CORE, they may have new names and codes. Search by postcode to find your scheme.</p>"
scheme_changes_link_text: "Read more about how schemes have changed"
view_schemes_link_text: "View your organisation’s schemes"
privacy_notice_tenant:
content: "Make sure the lead tenant has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
rent_type_definitions:
title: "Rent type definitions"
content: "<p><b>Social Rent:</b> where target rents are determined through the national rent regime. This is sometimes also known as 'formula rent'.</p>
<p><b>Affordable Rent:</b> where up to 80% of market rent can be charged. A new supply agreement is signed with Homes England or the Greater London Authority (GLA).</p>
<p><b>London Affordable Rent:</b> a tenure of affordable housing available in London by the GLA. It is an affordable rent which must be set in accordance with the Regulator of Social Housing’s Affordable Rent guidance. The landlord of these homes must be registered with the Regulator of Social Housing. These are a type of Affordable Rent lettings.</p>
<p><b>Rent to Buy: </b> a discount of up to 20% market rent is charged for a single rental period for a minimum of 5 years. After that period, the tenant is offered first chance to purchase the property (either shared ownership or outright) at full market value. These are a type of Intermediate Rent lettings.</p>
<p><b>London Living Rent:</b> a tenure of affordable housing available in London by the GLA. It was introduced in Affordable Homes Programme 2016 to 2021. These are a type of Intermediate Rent lettings.</p>
<p><b>Other intermediate rent:</b> any other specific scheme where up to 80% of market rent can be charged. This includes schemes with reduced rent so tenants can save towards a house purchasing deposit and schemes with an in-built future opportunity to buy the property being rented.</p>"
scheme_selection:
data_provider:
content: "If you’re not sure which scheme to choose, ask a data coordinator. Find your data coordinators on the %{users_page_link}."
users_page_link_text: "users page"
data_coordinator:
create_scheme_link_text: "Create a new supported housing scheme"
void_date:
title: "What is a void date?"
content: "<p>Date the property was (legally or contractually) available to let, or for:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>re-lets: the day after the previous tenant's contract ended</li>
<li>new builds: the day the landlord legally first owned the property (‘completion date’)</li>
<li>new conversions or acquisitions: completion date, or the day after rehabilitation work ended</li>
<li>new leases: the day the landlord got contractual property rights and could let it out to tenants</li>
</ul>"
what_counts_as_income:
title: "What counts as income?"
content: "<p>You should include any income after tax from:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>employment</li>
<li>pensions</li>
<li>Universal Credit</li>
</ul>
<p>Don’t include:</p>
<ul class=\"govuk-list govuk-list--bullet\">
<li>National Insurance (NI) contributions and tax</li>
<li>housing benefit</li>
<li>child benefit</li>
<li>council tax support</li>
</ul>"

120
config/locales/forms/2024/lettings/household_situation.en.yml

@ -0,0 +1,120 @@
en:
forms:
2024:
lettings:
household_situation:
layear:
page_header: ""
check_answer_label: "Length of time in local authority area"
hint_text: ""
question_text: "How long has the household continuously lived in the local authority area of the new letting?"
waityear:
page_header: ""
check_answer_label: "Length of time on local authority waiting list"
hint_text: ""
question_text: "How long has the household been on the local authority waiting list for the area of the new letting?"
reason:
reason_for_leaving_last_settled_home_renewal:
page_header: ""
reason:
check_answer_label: "Reason for leaving last settled home"
hint_text: "You told us this letting is a renewal. We have removed some options because of this."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: "Length of time on local authority waiting list"
hint_text: ""
question_text: "How long has the household been on the local authority waiting list for the area of the new letting?"
reason_for_leaving_last_settled_home:
page_header: ""
reason:
check_answer_label: "Reason for leaving last settled home"
hint_text: "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: ""
hint_text: ""
question_text: "What is the reason?"
prevten:
renewal:
page_header: ""
check_answer_label: "Where was the household immediately before this letting?"
hint_text: "You told us this letting is a renewal. We have removed some options because of this.<br><br>This is where the household was the night before they moved into this new let."
question_text: "Where was the household immediately before this letting?"
not_renewal:
page_header: ""
check_answer_label: "Where was the household immediately before this letting?"
hint_text: "This is where the household was the night before they moved into this new let."
question_text: "Where was the household immediately before this letting?"
homeless:
page_header: ""
check_answer_label: "Household homeless immediately before letting"
hint_text: ""
question_text: "Did the household experience homelessness immediately before this letting?"
previous_postcode:
page_header: ""
ppcodenk:
check_answer_label: ""
hint_text: "This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless."
question_text: "Do you know the postcode of the household’s last settled accommodation?"
ppostcode_full:
check_answer_label: "Postcode of household’s last settled accommodation"
hint_text: ""
question_text: "Postcode for the previous accommodation"
previous_local_authority:
page_header: ""
previous_la_known:
check_answer_label: ""
hint_text: "This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless."
question_text: "Do you know the local authority of the household’s last settled accommodation?"
prevloc:
check_answer_label: "Location of household’s last settled accommodation"
hint_text: "Select ‘Northern Ireland’, ‘Scotland’, ‘Wales’ or ‘Outside the UK’ if the household’s last settled home was outside England."
question_text: "Select a local authority"
reasonpref:
page_header: ""
check_answer_label: "Household given reasonable preference"
hint_text: "Households may be given ‘reasonable preference’ for social housing under one or more specific categories by the local authority. This is also known as ‘priority need’."
question_text: "Was the household given ‘reasonable preference’ by the local authority?"
reasonable_preference_reason:
page_header: ""
check_answer_label: "Reason for reasonable preference"
hint_text: "Select all that apply."
question_text: "Why was the household given ‘reasonable preference’?"
letting_allocation:
page_header: ""
check_answer_label: "Allocation system"
hint_text: "Select all that apply."
question_text: "How was this letting allocated?"
referral:
supported_housing:
prp:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: ""
question_text: "What was the source of referral for this letting?"
la:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that you are a local authority. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"
general_needs:
prp:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that the needs type is general needs. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"
la:
page_header: ""
check_answer_label: "Source of referral for letting"
hint_text: "You told us that you are a local authority and that the needs type is general needs. We have removed some options because of this."
question_text: "What was the source of referral for this letting?"

46
config/locales/forms/2024/sales/guidance.en.yml

@ -0,0 +1,46 @@
en:
forms:
2024:
sales:
guidance:
shared_ownership_type_definitions:
title: "Shared Ownership Type Definitions"
content: "<p><b>Shared Ownership (old model lease):</b> Cannot be used for homes funded through the Affordable Homes Programme 2021 to 2026. Use the new model lease for these properties.</p>
<p><b>Shared Ownership (new model lease):</b> Homes bought using the Affordable Homes Programme 2021 to 2026.</p>
<p><b>Social HomeBuy — shared ownership purchase:</b> Tenants of private registered providers purchase their home at discount on Shared Ownership terms.</p>
<p><b>Home Ownership for people with Long-Term Disabilities (HOLD):</b> A shared ownership sale for those with long term disabilities.</p>
<p><b>Older Persons Shared Ownership:</b> A type of shared ownership for those 55 years and over.</p>
<p><b>Rent to Buy — Shared Ownership:</b> A sale following a period of discounted rent.</p>
<p><b>Right to Shared Ownership (RtSO):</b> A sale of a share of a rented home to a tenant using this scheme.</p>
<p><b>London Living Rent — Shared Ownership:</b> A shared ownership sale following a period of discounted rent as part of the London Living Rent scheme.</p>"
discounted_ownership_type_definitions:
title: "Discounted Ownership Type Definitions"
content: "<p><b>Right to Acquire (RTA):</b> a discounted sale of a property built or purchased after 31 March 1997 to tenants of a private registered provider.</p>
<p><b>Preserved Right to Buy (PRTB):</b> a discounted sale of a property that used to be owned by a council to tenants of a private registered provider.</p>
<p><b>Voluntary Right to Buy (VRTB):</b> a discounted sale to tenants in this PRP owned property, as part of a pilot scheme.</p>
<p><b>Right to Buy (RTB):</b> a discounted sale to tenants in this council owned property.</p>
<p><b>Rent to Buy full ownership:</b> a sale on full ownership terms following a period of discounted rent.</p>
<p><b>Social HomeBuy for outright purchase:</b> a discounted sale to tenants of a private registered provider on full ownership terms.</p>
<p><b>Any other equity loan scheme:</b> any scheme, not covered elsewhere, in which a loan is used to purchase equity.</p>"
mortgage_lender:
title: "Can’t find the mortgage lender you’re looking for?"
content: "<ul class=\"govuk-list govuk-list--bullet\">
<li>Double check the spelling and try again</li>
<li>Type the first few letters to see the suggestions</li>
<li>Type Other and continue - we’ll ask you to type in your answer in the next question</li>
</ul>"
outright_sale_type_definitions:
title: "Outright sale type definitions"
content: "<p><b>Outright sale:</b> the full purchase of a property, usually with a mortgage or cash.</p>
<p><b>Other sale:</b> any sale which does not fit the criteria of any of the remaining options.</p>"
privacy_notice_buyer_joint_purchase:
content: "Make sure the buyers have seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"
privacy_notice_buyer:
content: "Make sure the buyer has seen or been given access to %{privacy_notice_link} before completing this log. This is a legal requirement under data protection legislation."
privacy_notice_link_text: "the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice"

81
config/locales/validations/sales/financial.en.yml

@ -0,0 +1,81 @@
en:
validations:
sales:
financial:
ownershipsch:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
uprn:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
la:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
postcode_full:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
income1:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
income2:
outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority."
outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority."
combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority."
combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities."
child_has_income: "Child's income must be £0."
ecstat2:
child_has_income: "Child's income must be £0."
mortgage:
mortgage_zero: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property."
mscharge:
monthly_leasehold_charges:
not_zero: "Monthly leasehold charges cannot be £0 if the property has monthly charges."
resale:
equity_over_max: "The maximum initial equity stake is %{max_equity}%."
type:
equity_under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%."
equity_over_max: "The maximum initial equity stake is %{max_equity}%."
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type."
equity:
equity_under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%."
equity_over_max: "The maximum initial equity stake is %{max_equity}%."
equity_over_stairowned_minus_stairbought:
joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought."
not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought."
stairowned:
equity_over_stairowned_minus_stairbought:
joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought."
not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought."
percentage_bought_must_be_greater_than_percentage_owned:
joint_purchase: "Total percentage buyers now own must be more than percentage bought in this transaction."
not_joint_purchase: "Total percentage buyer now owns must be more than percentage bought in this transaction."
percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same."
stairbought:
equity_over_stairowned_minus_stairbought:
joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought."
not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought."
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}%."
percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same."

19
spec/features/bulk_upload_lettings_logs_spec.rb

@ -74,6 +74,25 @@ RSpec.describe "Bulk upload lettings log" do
expect(page).to have_content("Upload lettings logs in bulk")
end
it "shows file to large error" do
stub_const("Forms::BulkUploadLettings::UploadYourFile::MAX_FILE_SIZE", 1.bytes)
visit("/lettings-logs")
click_link("Upload lettings logs in bulk")
expect(page).to have_content("Which year")
click_button("Continue")
choose(current_formatted_year)
click_button("Continue")
click_button("Continue")
allow_any_instance_of(Forms::BulkUploadLettings::UploadYourFile).to receive(:`).and_return("text/csv")
attach_file "file", file_fixture("2023_24_lettings_bulk_upload.xlsx")
click_button("Upload")
expect(page).to have_content("File must be 10MB or less. Check your file and delete data that does not need to be uploaded.")
end
end
# rubocop:enable RSpec/AnyInstance

20
spec/features/bulk_upload_sales_logs_spec.rb

@ -71,6 +71,26 @@ RSpec.describe "Bulk upload sales log" do
expect(page).to have_content("Upload sales logs in bulk")
end
it "shows file to large error" do
stub_const("Forms::BulkUploadSales::UploadYourFile::MAX_FILE_SIZE", 1.bytes)
visit("/sales-logs")
click_link("Upload sales logs in bulk")
expect(page).to have_content("Which year")
click_button("Continue")
click_button("Continue")
choose("2023 to 2024")
click_button("Continue")
click_button("Continue")
allow_any_instance_of(Forms::BulkUploadSales::UploadYourFile).to receive(:`).and_return("text/csv")
attach_file "file", file_fixture("2023_24_lettings_bulk_upload.xlsx")
click_button("Upload")
expect(page).to have_content("File must be 10MB or less. Check your file and delete data that does not need to be uploaded.")
end
end
# rubocop:enable RSpec/AnyInstance

2
spec/models/form/lettings/questions/declaration_spec.rb

@ -67,7 +67,7 @@ RSpec.describe Form::Lettings::Questions::Declaration, type: :model do
end
it "uses the expected top guidance partial" do
expect(question.top_guidance_partial).to eq("privacy_notice_tenant_2024")
expect(question.top_guidance_partial).to eq("privacy_notice_tenant")
end
it "has check_answers_card_number nil" do

2
spec/models/form/lettings/questions/homeless_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Form::Lettings::Questions::Homeless, type: :model do
subject(:question) { described_class.new(nil, nil, page) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 4)))) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 4), type: "lettings"), id: "household_situation")) }
it "has correct page" do
expect(question.page).to eq(page)

2
spec/models/form/lettings/questions/reason_renewal_spec.rb

@ -5,7 +5,7 @@ RSpec.describe Form::Lettings::Questions::ReasonRenewal, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:page) { instance_double(Form::Page, id: "reason_renewal") }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }

2
spec/models/form/lettings/questions/reason_spec.rb

@ -5,7 +5,7 @@ RSpec.describe Form::Lettings::Questions::Reason, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:page) { instance_double(Form::Page, id: "reason") }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }

2
spec/models/form/lettings/questions/rent_type_spec.rb

@ -73,7 +73,7 @@ RSpec.describe Form::Lettings::Questions::RentType, type: :model do
end
it "has the correct guidance partial" do
expect(question.top_guidance_partial).to eq("rent_type_definitions_2024")
expect(question.top_guidance_partial).to eq("rent_type_definitions")
end
end
end

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

@ -94,7 +94,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do
end
it "uses the expected top guidance partial" do
expect(question.top_guidance_partial).to eq("privacy_notice_buyer_2024")
expect(question.top_guidance_partial).to eq("privacy_notice_buyer")
end
it "returns correct unanswered_error_message" do
@ -116,7 +116,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do
end
it "uses the expected top guidance partial" do
expect(question.top_guidance_partial).to eq("privacy_notice_buyer_2024_joint_purchase")
expect(question.top_guidance_partial).to eq("privacy_notice_buyer_joint_purchase")
end
it "returns correct unanswered_error_message" do

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

@ -63,7 +63,7 @@ RSpec.describe Form::Sales::Questions::SharedOwnershipType, type: :model do
end
it "shows shows correct top_guidance_partial" do
expect(question.top_guidance_partial).to eq("shared_ownership_type_definitions_2024")
expect(question.top_guidance_partial).to eq("shared_ownership_type_definitions")
end
end
end

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

@ -16,19 +16,19 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds errors if buyer 1 has income over 80,000" do
record.income1 = 85_000
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range"))
end
it "adds errors if buyer 2 has income over 80,000" do
record.income2 = 85_000
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range"))
end
it "does not add errors if buyer 1 has income above 0 and below 80_000" do
@ -46,27 +46,27 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds errors if buyer 1 has income below 0" do
record.income1 = -500
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range"))
end
it "adds errors if buyer 2 has income below 0" do
record.income2 = -5
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_non_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range"))
end
it "adds errors when combined income is over 80_000" do
record.income1 = 45_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.combined_over_hard_max_for_outside_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.combined_over_hard_max_for_outside_london"))
end
it "does not add errors when combined income is under 80_000" do
@ -85,19 +85,19 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds errors if buyer 1 has income over 90,000" do
record.income1 = 95_000
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range"))
end
it "adds errors if buyer 2 has income over 90,000" do
record.income2 = 95_000
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range"))
end
it "does not add errors if buyer 1 has income above 0 and below 90_000" do
@ -115,27 +115,27 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds errors if buyer 1 has income below 0" do
record.income1 = -500
financial_validator.validate_income1(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range"))
end
it "adds errors if buyer 2 has income below 0" do
record.income2 = -2
financial_validator.validate_income2(record)
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_london_income_range"))
expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range"))
expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range"))
expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range"))
end
it "adds errors when combined income is over 90_000" do
record.income1 = 55_000
record.income2 = 40_000
financial_validator.validate_combined_income(record)
expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london"))
expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.combined_over_hard_max_for_london"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.combined_over_hard_max_for_london"))
end
it "does not add errors when combined income is under 90_000" do
@ -154,7 +154,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.mortgageused = 1
record.mortgage = 0
financial_validator.validate_mortgage(record)
expect(record.errors[:mortgage]).to include I18n.t("validations.financial.mortgage")
expect(record.errors[:mortgage]).to include I18n.t("validations.sales.financial.mortgage.mortgage_zero")
end
it "does not add an error is the mortgage is positive" do
@ -187,7 +187,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairowned = 40
record.jointpur = 1
financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record)
expect(record.errors["stairowned"]).to include("Total percentage buyers now own must be more than percentage bought in this transaction.")
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.joint_purchase"))
end
it "adds an error to stairowned and not stairbought if the percentage bought is more than the percentage owned for non joint purchase" do
@ -195,7 +195,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairowned = 40
record.jointpur = 2
financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record)
expect(record.errors["stairowned"]).to include("Total percentage buyer now owns must be more than percentage bought in this transaction.")
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.not_joint_purchase"))
end
end
@ -205,7 +205,6 @@ RSpec.describe Validations::Sales::FinancialValidations do
context "with 24/25 logs" do
before do
record.saledate = Time.zone.local(2024, 4, 3)
record.save!(validate: false)
end
it "does not add an error if the percentage bought is less than the percentage owned" do
@ -219,8 +218,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.stairbought = 30
record.stairowned = 30
financial_validator.validate_percentage_bought_not_equal_percentage_owned(record)
expect(record.errors["stairowned"]).to include("The percentage bought is 30% and the percentage owned in total is 30%. These figures cannot be the same.")
expect(record.errors["stairbought"]).to include("The percentage bought is 30% and the percentage owned in total is 30%. These figures cannot be the same.")
expect(record.errors["stairowned"]).to eq([I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)])
end
it "does not add an error to stairowned and not stairbought if the percentage bought is more than the percentage owned" do
@ -234,7 +233,6 @@ RSpec.describe Validations::Sales::FinancialValidations do
context "with 23/24 logs" do
before do
record.saledate = Time.zone.local(2023, 4, 3)
record.save!(validate: false)
end
it "does not add an error if the percentage bought is equal to the percentage owned" do
@ -258,7 +256,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds an error if monthly leasehold charges are zero" do
record.mscharge = 0
financial_validator.validate_monthly_leasehold_charges(record)
expect(record.errors[:mscharge]).to include I18n.t("validations.financial.monthly_leasehold_charges.not_zero")
expect(record.errors[:mscharge]).to include I18n.t("validations.sales.financial.mscharge.monthly_leasehold_charges.not_zero")
end
end
@ -270,8 +268,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
[2, 16, 18, 24].each do |type|
record.type = type
financial_validator.validate_percentage_bought_at_least_threshold(record)
expect(record.errors["stairbought"]).to eq(["The minimum increase in equity while staircasing is 10%."])
expect(record.errors["type"]).to eq(["The minimum increase in equity while staircasing is 10% for this shared ownership type."])
expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold: 10)])
expect(record.errors["type"]).to eq([I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold: 10)])
record.errors.clear
end
@ -279,8 +277,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
[28, 30, 31, 32].each do |type|
record.type = type
financial_validator.validate_percentage_bought_at_least_threshold(record)
expect(record.errors["stairbought"]).to eq(["The minimum increase in equity while staircasing is 1%."])
expect(record.errors["type"]).to eq(["The minimum increase in equity while staircasing is 1% for this shared ownership type."])
expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold: 1)])
expect(record.errors["type"]).to eq([I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold: 1)])
record.errors.clear
end
end
@ -331,8 +329,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
it "adds errors if buyer 2 has an income" do
record.income2 = 40_000
financial_validator.validate_child_income(record)
expect(record.errors["ecstat2"]).to include(match I18n.t("validations.financial.income.child_has_income"))
expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.child_has_income"))
expect(record.errors["ecstat2"]).to include(match I18n.t("validations.sales.financial.ecstat2.child_has_income"))
expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.child_has_income"))
end
end
end
@ -347,16 +345,16 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 2
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
it "adds an error for type 30, equity below min with the correct percentage" do
record.type = 30
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10))
end
it "does not add an error for equity in range with the correct percentage" do
@ -370,8 +368,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 2
record.equity = 90
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75))
end
it "does not add an error if it's a resale" do
@ -390,16 +388,16 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 2
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25))
end
it "adds an error for type 30, equity below min with the correct percentage" do
record.type = 30
record.equity = 1
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10))
end
it "does not add an error for equity in range with the correct percentage" do
@ -413,8 +411,8 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.type = 2
record.equity = 90
financial_validator.validate_equity_in_range_for_year_and_type(record)
expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75))
expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75))
expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75))
end
end
end
@ -443,9 +441,9 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.equity = 2
record.jointpur = 1
financial_validator.validate_equity_less_than_staircase_difference(record)
expect(record.errors["equity"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.")
expect(record.errors["stairowned"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.")
expect(record.errors["stairbought"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.")
expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1))
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1))
expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1))
end
it "adds errors if equity is more than stairowned - stairbought for non joint purchase" do
@ -454,9 +452,9 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.equity = 2
record.jointpur = 2
financial_validator.validate_equity_less_than_staircase_difference(record)
expect(record.errors["equity"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.")
expect(record.errors["stairowned"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.")
expect(record.errors["stairbought"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.")
expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1))
expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1))
expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1))
end
it "does not add errors if equity is less than stairowned - stairbought" do

2
spec/requests/form_controller_spec.rb

@ -412,7 +412,7 @@ RSpec.describe FormController, type: :request do
context "with a form page that has custom guidance" do
it "displays the correct partial" do
get "/lettings-logs/#{lettings_log.id}/net-income", headers: headers, params: {}
expect(response.body).to match("What counts as income?")
expect(response.body).to match(I18n.t("forms.2021.lettings.guidance.what_counts_as_income.title"))
end
end

2
spec/views/form/page_view_spec.rb

@ -100,7 +100,7 @@ RSpec.describe "form/page" do
end
context "with a question containing extra guidance" do
let(:expected_guidance) { /What counts as income?/ }
let(:expected_guidance) { /#{I18n.t("forms.2021.lettings.guidance.what_counts_as_income.content")}/ }
context "with radio type" do
let(:question_attributes) { { type: "radio", answer_options: { "1": "A", "2": "B" } } }

Loading…
Cancel
Save