Browse Source

Merge branch 'main' into CLDC-3655-extract-property-information-errors

pull/2700/head
kosiakkatrina 2 years ago committed by GitHub
parent
commit
90597386f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 30
      app/components/bulk_upload_error_row_component.html.erb
  2. 13
      app/components/bulk_upload_error_row_component.rb
  3. 5
      app/frontend/styles/_bulk-uploads.scss
  4. 1
      app/models/form/sales/pages/buyer1_income.rb
  5. 3
      app/models/form/sales/pages/buyer1_income_max_value_check.rb
  6. 5
      app/models/form/sales/pages/buyer1_income_min_value_check.rb
  7. 1
      app/models/form/sales/pages/buyer2_income.rb
  8. 3
      app/models/form/sales/pages/buyer2_income_max_value_check.rb
  9. 5
      app/models/form/sales/pages/buyer2_income_min_value_check.rb
  10. 3
      app/models/form/sales/pages/combined_income_max_value_check.rb
  11. 5
      app/models/form/sales/pages/deposit_value_check.rb
  12. 1
      app/models/form/sales/pages/housing_benefits.rb
  13. 6
      app/models/form/sales/pages/mortgage_value_check.rb
  14. 1
      app/models/form/sales/pages/previous_ownership.rb
  15. 1
      app/models/form/sales/pages/savings.rb
  16. 5
      app/models/form/sales/pages/savings_value_check.rb
  17. 4
      app/models/form/sales/questions/buyer1_income.rb
  18. 3
      app/models/form/sales/questions/buyer1_income_known.rb
  19. 3
      app/models/form/sales/questions/buyer1_income_value_check.rb
  20. 2
      app/models/form/sales/questions/buyer1_mortgage.rb
  21. 4
      app/models/form/sales/questions/buyer2_income.rb
  22. 3
      app/models/form/sales/questions/buyer2_income_known.rb
  23. 3
      app/models/form/sales/questions/buyer2_income_value_check.rb
  24. 2
      app/models/form/sales/questions/buyer2_mortgage.rb
  25. 3
      app/models/form/sales/questions/combined_income_value_check.rb
  26. 3
      app/models/form/sales/questions/deposit_value_check.rb
  27. 3
      app/models/form/sales/questions/housing_benefits.rb
  28. 3
      app/models/form/sales/questions/mortgage_value_check.rb
  29. 3
      app/models/form/sales/questions/prevown.rb
  30. 3
      app/models/form/sales/questions/prevshared.rb
  31. 3
      app/models/form/sales/questions/savings.rb
  32. 3
      app/models/form/sales/questions/savings_nk.rb
  33. 3
      app/models/form/sales/questions/savings_value_check.rb
  34. 7
      app/models/forms/bulk_upload_lettings/guidance.rb
  35. 7
      app/models/forms/bulk_upload_sales/guidance.rb
  36. 48
      app/models/validations/sales/household_validations.rb
  37. 6
      app/models/validations/shared_validations.rb
  38. 4
      app/services/bulk_upload/lettings/year2024/row_parser.rb
  39. 16
      app/services/bulk_upload/sales/year2024/row_parser.rb
  40. 2
      config/credentials.yml.enc
  41. 37
      config/locales/en.yml
  42. 90
      config/locales/forms/2023/sales/income_benefits_and_savings.en.yml
  43. 60
      config/locales/forms/2023/sales/soft_validations.en.yml
  44. 90
      config/locales/forms/2024/sales/income_benefits_and_savings.en.yml
  45. 60
      config/locales/forms/2024/sales/soft_validations.en.yml
  46. 47
      config/locales/validations/sales/household.en.yml
  47. 3
      spec/models/form/sales/pages/buyer1_income_max_value_check_spec.rb
  48. 3
      spec/models/form/sales/pages/buyer1_income_min_value_check_spec.rb
  49. 3
      spec/models/form/sales/pages/buyer2_income_max_value_check_spec.rb
  50. 3
      spec/models/form/sales/pages/buyer2_income_min_value_check_spec.rb
  51. 3
      spec/models/form/sales/pages/combined_income_max_value_check_spec.rb
  52. 3
      spec/models/form/sales/pages/deposit_value_check_spec.rb
  53. 3
      spec/models/form/sales/pages/mortgage_value_check_spec.rb
  54. 3
      spec/models/form/sales/pages/savings_value_check_spec.rb
  55. 3
      spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
  56. 2
      spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
  57. 17
      spec/models/forms/bulk_upload_lettings/guidance_spec.rb
  58. 17
      spec/models/forms/bulk_upload_sales/guidance_spec.rb
  59. 50
      spec/models/validations/sales/household_validations_spec.rb
  60. 8
      spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

30
app/components/bulk_upload_error_row_component.html.erb

@ -13,7 +13,7 @@
<% if critical_errors.any? %>
<h2 class="govuk-heading-m">Critical errors</h2>
<p class="govuk-body">These errors must be fixed to complete your logs.</p>
<%= govuk_table do |table| %>
<%= govuk_table(html_attributes: { class: potential_errors.any? ? "" : "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
@ -39,7 +39,7 @@
<% if potential_errors.any? %>
<h2 class="govuk-heading-m">Potential errors</h2>
<p class="govuk-body">The following groups of cells might have conflicting data. Check the answers and fix any incorrect data.<br><br>If the answers are correct, fix the critical errors and reupload the file. You'll need to confirm that the following data is correct when the file only contains potential errors.</p>
<%= govuk_table do |table| %>
<%= govuk_table(html_attributes: { class: "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
@ -49,24 +49,24 @@
<% end %>
<% end %>
<%= table.with_body do |body| %>
<% potential_errors.group_by(&:error).each do |error_message, errors| %>
<% errors.each_with_index do |error, index| %>
<% row_class = "grouped-rows" %>
<% row_class += " first-row" if index.zero? %>
<% row_class += " last-row" if index == errors.size - 1 %>
<% body.with_row(html_attributes: { class: row_class }) do |row| %>
<% row.with_cell(text: error.cell) %>
<% row.with_cell(text: question_for_field(error.field), html_attributes: { class: "govuk-!-width-one-half" }) %>
<% if index == 0 %>
<% row.with_cell(text: error_message.html_safe, rowspan: errors.size, html_attributes: { class: "govuk-!-font-weight-bold govuk-!-width-one-half grouped-multirow-cell" }) %>
<% end %>
<% row.with_cell(text: error.field.humanize) %>
<%= table.with_body do |body| %>
<% potential_errors.group_by(&:error).each_with_index do |(error_message, errors), group_index| %>
<% total_groups = potential_errors.group_by(&:error).size %>
<% errors.each_with_index do |error, index| %>
<% row_class = row_classes(index, errors.size) %>
<% body.with_row(html_attributes: { class: row_class }) do |row| %>
<% row.with_cell(text: error.cell) %>
<% row.with_cell(text: question_for_field(error.field), html_attributes: { class: "govuk-!-width-one-half" }) %>
<% if index == 0 %>
<% cell_class = cell_classes(group_index, total_groups) %>
<% row.with_cell(text: error_message.html_safe, rowspan: errors.size, html_attributes: { class: cell_class }) %>
<% end %>
<% row.with_cell(text: error.field.humanize) %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
<% end %>
</div>
</div>

13
app/components/bulk_upload_error_row_component.rb

@ -62,4 +62,17 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def sales?
bulk_upload.log_type == "sales"
end
def row_classes(index, errors_size)
row_class = "grouped-rows"
row_class += " first-row" if index.zero?
row_class += " last-row" if index == errors_size - 1
row_class
end
def cell_classes(group_index, total_groups)
cell_class = "govuk-!-font-weight-bold govuk-!-width-one-half"
cell_class += " grouped-multirow-cell" unless group_index == total_groups - 1
cell_class
end
end

5
app/frontend/styles/_bulk-uploads.scss

@ -12,6 +12,11 @@
border-bottom: 1px solid #b1b4b6;
}
.no-bottom-border,
.no-bottom-border > tbody > tr:last-of-type td {
border-bottom: none;
}
.text-normal-break {
white-space: normal;
word-break: break-all;

1
app/models/form/sales/pages/buyer1_income.rb

@ -2,6 +2,7 @@ class Form::Sales::Pages::Buyer1Income < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "buyer_1_income"
@copy_key = "sales.income_benefits_and_savings.buyer_1_income"
end
def questions

3
app/models/form/sales/pages/buyer1_income_max_value_check.rb

@ -6,8 +6,9 @@ class Form::Sales::Pages::Buyer1IncomeMaxValueCheck < ::Form::Page
"income1_over_soft_max?" => true,
},
]
@copy_key = "sales.soft_validations.income1_value_check.max"
@title_text = {
"translation" => "soft_validations.income.over_soft_max_for_la_buyer_1",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",

5
app/models/form/sales/pages/buyer1_income_min_value_check.rb

@ -6,8 +6,9 @@ class Form::Sales::Pages::Buyer1IncomeMinValueCheck < ::Form::Page
"income1_under_soft_min?" => true,
},
]
@copy_key = "sales.soft_validations.income1_value_check.min"
@title_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status.title_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@ -22,7 +23,7 @@ class Form::Sales::Pages::Buyer1IncomeMinValueCheck < ::Form::Page
],
}
@informative_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status.hint_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
end

1
app/models/form/sales/pages/buyer2_income.rb

@ -2,6 +2,7 @@ class Form::Sales::Pages::Buyer2Income < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "buyer_2_income"
@copy_key = "sales.income_benefits_and_savings.buyer_2_income"
@depends_on = [{
"joint_purchase?" => true,
}]

3
app/models/form/sales/pages/buyer2_income_max_value_check.rb

@ -6,8 +6,9 @@ class Form::Sales::Pages::Buyer2IncomeMaxValueCheck < ::Form::Page
"income2_over_soft_max?" => true,
},
]
@copy_key = "sales.soft_validations.income2_value_check.max"
@title_text = {
"translation" => "soft_validations.income.over_soft_max_for_la_buyer_2",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",

5
app/models/form/sales/pages/buyer2_income_min_value_check.rb

@ -6,8 +6,9 @@ class Form::Sales::Pages::Buyer2IncomeMinValueCheck < ::Form::Page
"income2_under_soft_min?" => true,
},
]
@copy_key = "sales.soft_validations.income2_value_check.min"
@title_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status.title_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@ -22,7 +23,7 @@ class Form::Sales::Pages::Buyer2IncomeMinValueCheck < ::Form::Page
],
}
@informative_text = {
"translation" => "soft_validations.income.under_soft_min_for_economic_status.hint_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
end

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

@ -6,8 +6,9 @@ class Form::Sales::Pages::CombinedIncomeMaxValueCheck < ::Form::Page
"combined_income_over_soft_max?" => true,
},
]
@copy_key = "sales.soft_validations.combined_income_value_check"
@title_text = {
"translation" => "soft_validations.income.over_soft_max_for_la_combined",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",

5
app/models/form/sales/pages/deposit_value_check.rb

@ -1,12 +1,13 @@
class Form::Sales::Pages::DepositValueCheck < ::Form::Page
def initialize(id, hsh, subsection, joint_purchase:)
super(id, hsh, subsection)
@copy_key = "sales.soft_validations.deposit_value_check.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@informative_text = {
"translation" => "soft_validations.deposit.hint_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
@title_text = {
"translation" => "soft_validations.deposit.title_text.#{joint_purchase ? 'two' : 'one'}",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",

1
app/models/form/sales/pages/housing_benefits.rb

@ -2,6 +2,7 @@ class Form::Sales::Pages::HousingBenefits < ::Form::Page
def initialize(id, hsh, subsection, joint_purchase:)
super(id, hsh, subsection)
@joint_purchase = joint_purchase
@copy_key = "sales.income_benefits_and_savings.housing_benefits.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
end
def questions

6
app/models/form/sales/pages/mortgage_value_check.rb

@ -2,10 +2,10 @@ class Form::Sales::Pages::MortgageValueCheck < ::Form::Page
def initialize(id, hsh, subsection, person_index = nil)
super(id, hsh, subsection)
@depends_on = depends_on
@informative_text = {}
@person_index = person_index
@copy_key = "sales.soft_validations.mortgage_value_check"
@title_text = {
"translation" => "soft_validations.mortgage.title_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@ -15,7 +15,7 @@ class Form::Sales::Pages::MortgageValueCheck < ::Form::Page
],
}
@informative_text = {
"translation" => "soft_validations.mortgage.hint_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
end

1
app/models/form/sales/pages/previous_ownership.rb

@ -3,6 +3,7 @@ class Form::Sales::Pages::PreviousOwnership < ::Form::Page
super(id, hsh, subsection)
@joint_purchase = joint_purchase
@depends_on = [{ "joint_purchase?" => @joint_purchase }]
@copy_key = "sales.income_benefits_and_savings.prevown.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
end
def questions

1
app/models/form/sales/pages/savings.rb

@ -2,6 +2,7 @@ class Form::Sales::Pages::Savings < ::Form::Page
def initialize(id, hsh, subsection, joint_purchase:)
super(id, hsh, subsection)
@joint_purchase = joint_purchase
@copy_key = "sales.income_benefits_and_savings.savings.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
end
def questions

5
app/models/form/sales/pages/savings_value_check.rb

@ -1,8 +1,9 @@
class Form::Sales::Pages::SavingsValueCheck < ::Form::Page
def initialize(id, hsh, subsection, joint_purchase:)
super(id, hsh, subsection)
@copy_key = "sales.soft_validations.savings_value_check.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@title_text = {
"translation" => "soft_validations.savings.title_text.#{joint_purchase ? 'two' : 'one'}",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
{
"key" => "field_formatted_as_currency",
@ -12,7 +13,7 @@ class Form::Sales::Pages::SavingsValueCheck < ::Form::Page
],
}
@informative_text = {
"translation" => "soft_validations.savings.hint_text",
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
@joint_purchase = joint_purchase

4
app/models/form/sales/questions/buyer1_income.rb

@ -2,9 +2,7 @@ class Form::Sales::Questions::Buyer1Income < ::Form::Question
def initialize(id, hsh, page)
super
@id = "income1"
@check_answer_label = "Buyer 1’s gross annual income"
@header = "Buyer 1’s gross annual income"
@hint_text = "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
@copy_key = "sales.income_benefits_and_savings.buyer_1_income.income1"
@type = "numeric"
@min = 0
@max = 999_999

3
app/models/form/sales/questions/buyer1_income_known.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Buyer1IncomeKnown < ::Form::Question
def initialize(id, hsh, page)
super
@id = "income1nk"
@check_answer_label = "Buyer 1’s gross annual income known?"
@header = "Do you know buyer 1’s annual income?"
@copy_key = "sales.income_benefits_and_savings.buyer_1_income.income1nk"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@conditional_for = {

3
app/models/form/sales/questions/buyer1_income_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Buyer1IncomeValueCheck < ::Form::Question
def initialize(id, hsh, page, check_answers_card_number:)
super(id, hsh, page)
@id = "income1_value_check"
@check_answer_label = "Buyer 1 income confirmation"
@header = "Are you sure this is correct?"
@copy_key = "sales.soft_validations.income1_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

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

@ -2,8 +2,6 @@ class Form::Sales::Questions::Buyer1Mortgage < ::Form::Question
def initialize(id, hsh, page)
super
@id = "inc1mort"
@check_answer_label = "Buyer 1’s income used for mortgage application"
@header = "Was buyer 1’s income used for a mortgage application?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1

4
app/models/form/sales/questions/buyer2_income.rb

@ -2,10 +2,8 @@ class Form::Sales::Questions::Buyer2Income < ::Form::Question
def initialize(id, hsh, page)
super
@id = "income2"
@check_answer_label = "Buyer 2’s gross annual income"
@header = "Buyer 2’s gross annual income"
@copy_key = "sales.income_benefits_and_savings.buyer_2_income.income2"
@type = "numeric"
@hint_text = "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
@min = 0
@max = 999_999
@step = 1

3
app/models/form/sales/questions/buyer2_income_known.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Buyer2IncomeKnown < ::Form::Question
def initialize(id, hsh, page)
super
@id = "income2nk"
@check_answer_label = "Buyer 2’s gross annual income known?"
@header = "Do you know buyer 2’s annual income?"
@copy_key = "sales.income_benefits_and_savings.buyer_2_income.income2"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@conditional_for = {

3
app/models/form/sales/questions/buyer2_income_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Buyer2IncomeValueCheck < ::Form::Question
def initialize(id, hsh, page, check_answers_card_number:)
super(id, hsh, page)
@id = "income2_value_check"
@check_answer_label = "Buyer 2 income confirmation"
@header = "Are you sure this is correct?"
@copy_key = "sales.soft_validations.income2_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

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

@ -2,8 +2,6 @@ class Form::Sales::Questions::Buyer2Mortgage < ::Form::Question
def initialize(id, hsh, page)
super
@id = "inc2mort"
@check_answer_label = "Buyer 2’s income used for mortgage application"
@header = "Was buyer 2’s income used for a mortgage application?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2

3
app/models/form/sales/questions/combined_income_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::CombinedIncomeValueCheck < ::Form::Question
def initialize(id, hsh, page, check_answers_card_number:)
super(id, hsh, page)
@id = "combined_income_value_check"
@check_answer_label = "Combined income confirmation"
@header = "Are you sure this is correct?"
@copy_key = "sales.soft_validations.combined_income_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

3
app/models/form/sales/questions/deposit_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::DepositValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "deposit_value_check"
@check_answer_label = "Deposit confirmation"
@header = "Are you sure that the deposit is this much higher than the buyer's savings?"
@copy_key = "sales.soft_validations.deposit_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

3
app/models/form/sales/questions/housing_benefits.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::HousingBenefits < ::Form::Question
def initialize(id, hsh, page, joint_purchase:)
super(id, hsh, page)
@id = "hb"
@check_answer_label = "Housing-related benefits #{joint_purchase ? 'buyers' : 'buyer'} received before buying this property"
@header = "#{joint_purchase ? 'Were the buyers' : 'Was the buyer'} receiving any of these housing-related benefits immediately before buying this property?"
@copy_key = "sales.income_benefits_and_savings.housing_benefits.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@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]

3
app/models/form/sales/questions/mortgage_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::MortgageValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "mortgage_value_check"
@check_answer_label = "Mortgage confirmation"
@header = "Are you sure that the mortgage is more than 5 times the income used for the mortgage application?"
@copy_key = "sales.soft_validations.mortgage_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

3
app/models/form/sales/questions/prevown.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Prevown < ::Form::Question
def initialize(id, hsh, page, joint_purchase:)
super(id, hsh, page)
@id = "prevown"
@check_answer_label = I18n.t("check_answer_labels.prevown", count: joint_purchase ? 2 : 1)
@header = I18n.t("questions.prevown", count: joint_purchase ? 2 : 1)
@copy_key = "sales.income_benefits_and_savings.prevown.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@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]

3
app/models/form/sales/questions/prevshared.rb

@ -2,11 +2,8 @@ class Form::Sales::Questions::Prevshared < ::Form::Question
def initialize(id, hsh, page)
super
@id = "prevshared"
@check_answer_label = "Previous property shared ownership?"
@header = "Was the previous property under shared ownership?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@hint_text = "For any buyer"
@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/sales/questions/savings.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::Savings < ::Form::Question
def initialize(id, hsh, page, joint_purchase:)
super(id, hsh, page)
@id = "savings"
@check_answer_label = "#{joint_purchase ? 'Buyers’' : 'Buyer’s'} total savings before any deposit paid"
@header = "Enter their total savings to the nearest £10"
@copy_key = "sales.income_benefits_and_savings.savings.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}.savings"
@type = "numeric"
@width = 5
@prefix = "£"

3
app/models/form/sales/questions/savings_nk.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::SavingsNk < ::Form::Question
def initialize(id, hsh, page, joint_purchase:)
super(id, hsh, page)
@id = "savingsnk"
@check_answer_label = "#{joint_purchase ? 'Buyers’' : 'Buyer’s'} total savings known?"
@header = "Do you know how much the #{joint_purchase ? 'buyers' : 'buyer'} had in savings before they paid any deposit for the property?"
@copy_key = "sales.income_benefits_and_savings.savings.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}.savingsnk"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@conditional_for = {

3
app/models/form/sales/questions/savings_value_check.rb

@ -2,8 +2,7 @@ class Form::Sales::Questions::SavingsValueCheck < ::Form::Question
def initialize(id, hsh, page)
super
@id = "savings_value_check"
@check_answer_label = "Savings confirmation"
@header = "Are you sure the savings are higher than £100,000?"
@copy_key = "sales.soft_validations.savings_value_check"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },

7
app/models/forms/bulk_upload_lettings/guidance.rb

@ -4,11 +4,18 @@ module Forms
include ActiveModel::Model
include ActiveModel::Attributes
include Rails.application.routes.url_helpers
include CollectionTimeHelper
attribute :year, :integer
attribute :referrer
attribute :organisation_id, :integer
def initialize(params)
super(params)
self.year = current_collection_start_year if year.nil?
end
def view_path
"bulk_upload_shared/guidance"
end

7
app/models/forms/bulk_upload_sales/guidance.rb

@ -4,11 +4,18 @@ module Forms
include ActiveModel::Model
include ActiveModel::Attributes
include Rails.application.routes.url_helpers
include CollectionTimeHelper
attribute :year, :integer
attribute :referrer
attribute :organisation_id, :integer
def initialize(params)
super(params)
self.year = current_collection_start_year if year.nil?
end
def view_path
"bulk_upload_shared/guidance"
end

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

@ -9,9 +9,9 @@ module Validations::Sales::HouseholdValidations
return unless record.form.start_date.year >= 2023
if record.buyers_will_live_in? && record.buyer_one_will_not_live_in_property? && record.buyer_two_will_not_live_in_property?
record.errors.add :buylivein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent_setup")
record.errors.add :buy1livein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
record.errors.add :buy2livein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
record.errors.add :buylivein, I18n.t("validations.sales.household.buylivein.buyers_will_live_in_property_values_inconsistent")
record.errors.add :buy1livein, I18n.t("validations.sales.household.buy1livein.buyers_will_live_in_property_values_inconsistent")
record.errors.add :buy2livein, I18n.t("validations.sales.household.buy2livein.buyers_will_live_in_property_values_inconsistent")
end
end
@ -20,8 +20,8 @@ module Validations::Sales::HouseholdValidations
return unless record.discounted_ownership_sale? && record.prevten
if [3, 4, 5, 6, 7, 9, 0].include?(record.prevten)
record.errors.add :prevten, I18n.t("validations.household.prevten.invalid_for_discounted_sale")
record.errors.add :ownershipsch, I18n.t("validations.household.prevten.invalid_for_discounted_sale")
record.errors.add :prevten, I18n.t("validations.sales.household.prevten.prevten_invalid_for_discounted_sale")
record.errors.add :ownershipsch, I18n.t("validations.sales.household.ownershipsch.prevten_invalid_for_discounted_sale")
end
end
@ -34,11 +34,11 @@ module Validations::Sales::HouseholdValidations
next unless age && relationship
if age < 16 && !relationship_is_child_other_or_refused?(relationship)
record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_relat_sales", person_num:)
record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.child_under_16_sales", person_num:)
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.child_under_16", person_num:)
record.errors.add "relat#{person_num}", I18n.t("validations.sales.household.relat.child_under_16", person_num:)
elsif age >= 20 && person_is_child?(relationship)
record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_over_20")
record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.child_over_20")
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.child_over_20")
record.errors.add "relat#{person_num}", I18n.t("validations.sales.household.relat.child_over_20")
end
end
end
@ -58,16 +58,16 @@ module Validations::Sales::HouseholdValidations
child = person_is_child?(relationship)
if age_between_16_19 && !(student || economic_status_refused) && child
record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.must_be_student")
record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.cannot_be_16_19.child_not_student")
record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.16_19_not_student")
record.errors.add "ecstat#{person_num}", I18n.t("validations.sales.household.ecstat.student_16_19.must_be_student")
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.student_16_19.cannot_be_16_19.child_not_student")
record.errors.add "relat#{person_num}", I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.16_19_not_student")
end
next unless !age_between_16_19 && student && child
record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.must_be_16_19")
record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.cannot_be_student.child_not_16_19")
record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.student_not_16_19")
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.student_16_19.must_be_16_19")
record.errors.add "ecstat#{person_num}", I18n.t("validations.sales.household.ecstat.student_16_19.cannot_be_student.child_not_16_19")
record.errors.add "relat#{person_num}", I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.student_not_16_19")
end
end
@ -78,12 +78,12 @@ module Validations::Sales::HouseholdValidations
next unless age && economic_status
if age < 16 && !economic_status_is_child_other_or_refused?(economic_status) && !record.form.start_year_after_2024?
record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_under_16", person_num:)
record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_ecstat", person_num:)
record.errors.add "ecstat#{person_num}", I18n.t("validations.sales.household.ecstat.child_under_16", person_num:)
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.child_under_16_ecstat", person_num:)
end
if person_is_economic_child?(economic_status) && age > 16
record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_over_16", person_num:)
record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_over_16", person_num:)
record.errors.add "ecstat#{person_num}", I18n.t("validations.sales.household.ecstat.child_over_16", person_num:)
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.child_over_16", person_num:)
end
end
end
@ -99,17 +99,17 @@ module Validations::Sales::HouseholdValidations
next unless person_age > buyer_1_age - 12 && person_is_child?(relationship)
record.errors.add "age1", I18n.t("validations.household.age.child_12_years_younger")
record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_12_years_younger")
record.errors.add "relat#{person_num}", I18n.t("validations.household.age.child_12_years_younger")
record.errors.add "age1", I18n.t("validations.sales.household.age1.child_12_years_younger")
record.errors.add "age#{person_num}", I18n.t("validations.sales.household.age.child_12_years_younger")
record.errors.add "relat#{person_num}", I18n.t("validations.sales.household.relat.child_12_years_younger")
end
end
def validate_buyer_not_child(record)
return unless record.saledate && record.form.start_year_after_2024?
record.errors.add "ecstat1", I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "1") if person_is_economic_child?(record.ecstat1)
record.errors.add "ecstat2", I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "2") if person_is_economic_child?(record.ecstat2) && record.joint_purchase?
record.errors.add "ecstat1", I18n.t("validations.sales.household.ecstat1.buyer_cannot_be_child") if person_is_economic_child?(record.ecstat1)
record.errors.add "ecstat2", I18n.t("validations.sales.household.ecstat2.buyer_cannot_be_child") if person_is_economic_child?(record.ecstat2) && record.joint_purchase?
end
private

6
app/models/validations/shared_validations.rb

@ -131,7 +131,11 @@ module Validations::SharedValidations
partner_numbers = (2..max_people).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
record.errors.add "relat#{n}", I18n.t("validations.household.relat.one_partner")
if record.sales?
record.errors.add "relat#{n}", I18n.t("validations.sales.household.relat.one_partner")
else
record.errors.add "relat#{n}", I18n.t("validations.household.relat.one_partner")
end
end
end
end

4
app/services/bulk_upload/lettings/year2024/row_parser.rb

@ -618,7 +618,7 @@ private
end
def key_address_fields_provided?
field_17.present? && field_19.present? && field_21.present? && field_22.present?
field_17.present? && field_19.present? && postcode_full.present?
end
def validate_address_fields
@ -1355,7 +1355,7 @@ private
end
def postcode_full
"#{field_21} #{field_22}" if field_21 && field_22
[field_21, field_22].compact_blank.join(" ") if field_21 || field_22
end
def owning_organisation

16
app/services/bulk_upload/sales/year2024/row_parser.rb

@ -616,7 +616,7 @@ private
end
def key_address_fields_provided?
field_23.present? && field_25.present? && field_27.present? && field_28.present?
field_23.present? && field_25.present? && postcode_full.present?
end
def validate_address_fields
@ -1074,7 +1074,7 @@ private
end
def postcode_full
"#{field_27} #{field_28}" if field_27 && field_28
[field_27, field_28].compact_blank.join(" ") if field_27 || field_28
end
def ppostcode_full
@ -1469,10 +1469,10 @@ private
def validate_buyer1_economic_status
if field_35 == 9
if field_31.present? && field_31.to_i >= 16
errors.add(:field_35, I18n.t("validations.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1"))
errors.add(:field_31, I18n.t("validations.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1"))
errors.add(:field_35, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1"))
errors.add(:field_31, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1"))
else
errors.add(:field_35, I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "1"))
errors.add(:field_35, I18n.t("validations.sales.household.ecstat1.buyer_cannot_be_child"))
end
end
end
@ -1482,10 +1482,10 @@ private
if field_42 == 9
if field_38.present? && field_38.to_i >= 16
errors.add(:field_42, I18n.t("validations.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2"))
errors.add(:field_38, I18n.t("validations.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2"))
errors.add(:field_42, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2"))
errors.add(:field_38, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2"))
else
errors.add(:field_42, I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "2"))
errors.add(:field_42, I18n.t("validations.sales.household.ecstat2.buyer_cannot_be_child"))
end
end
end

2
config/credentials.yml.enc

@ -1 +1 @@
QGn9IiI91BaO4IGAtfy92FrNP46X9T2jJErRv+o/PRG9LrimEGeuOE+FwhArKZQ5cTipaDqo8u9Ajv45Kitv3c0GynOOvz0r3OjPRHO/p4hW8BFWQDv581cWWPsyZT2JO51zZ5LnwNFvWrjEB2q49YESgtfADPkJWmtx/By5Cg2/PVIRxvhGKOnheme5cih050wqg/43BdiF0PD9FDTZXJDLJg/QQ8nQYkvQe2jN4nM4mTVpkQkmzDKgGknmUWFfW3qWFzlsdMkdkPdeP9wLnJVbFTeyaaJT3wv6l19d2rKqo8iVvacdaQjRev+LVXqOsNAjVHwcPNQVq9s8pxG24HLk3aQ14Eyjf6tHAuZAV4jLnNqQtBQ0AIldWeOl6SKmlTom1P1tcLp9KpajEADplmWSwUktIGmaakFjk/ApYaUBiYTku2iLHMrT/xSc3jPj5W/ZggeJ0Ij6nuGYE1cmBxWGxda9PzOrDP8coEK9vPHiNeDDM1RoukVmf8gwDmshILi5EwIAsO2gJXM1wtPYMu41+H4/y3c0GIwgfv9QP11q+nqhG1MMcOrAUKGhypAS+M+uLwfGQudfQDKP9Zv3VCnOk3mkKlpIzMMD4UdJxQeE/8sfwIsEhWggEo3oa93ptbRdvJ7YYcVvmMmkVBxk0KWFprl4i/BkFHLWrKNl5LBOGA==--ziMOTnYBB5TDyXYU--3FJMs8e6R8lheqcqB8p8uQ==
M2+y4Ll2PwjN9IiCvliQ5Ytiy+/9bSepV2siwg6hvttLc63q0W4hbNobseAZAYqWLajrnJ7lm9AfT8CuBreHtwFsdQ/HV8NPrvzLB/P+X15MKLtb1Sg7bNjtW24uoE3zYrWILecpNygLc1ZXxgjka3yjc7XdV7MA3NR2/2zvkGREJvjbJlEn7036CWnNfN7PD0S57O1z+LqilrrhecWAmGeJRU2Ve2UZNoUExz865ovpk1enGReiU5+0jlNTIK3SCc75HH3grET6HkAbzsZvC763OkEkEQGVJeaytQ2cGkyk8t98nqGRq6fK9uAwKyGh6KwHH8BT++OOF3Re4Uf2A9boFdJ5AOwuV7ZK+OonPu7x/bThRmb+Sl057+L1pSrpILvFUzA3K8k34G9ZMHMLIX0/rHLEav+ToFFwBxARleiUdSgEv9txP0wU+7fPyuJlHJb7CIrC9dRQIeyM9RAIvxZYhP2KrTqm9eEyCJNttAWpYnXfnoxgbQEoQw94KOal/i26bK09TZNwv10oTYZqxB6PqfsQQ9wVIesO9v6uK3HQ2jVXeCb4caj1HWFOjFLhcDoAEFe6DUmjSdxf2tDQ90pwQKQ7IWi9jPOOQSVQ7VoCc1uD3cImDjsY/04sGbCdSpGt53E3Rn9UCGHdVhzzOXRhU4wQLBFEFin79KJ7q0m71jesGEpVNKI2s8aC+Ux8btSBu92JLS4b9zZHT13D729CW2T8--EZ5GxuRKaFfGdzCE--OZ1EwaObJ4ZF59N0JcJ7Dg==

37
config/locales/en.yml

@ -495,11 +495,8 @@ en:
retired_female: "A female tenant who is retired must be 60 or over."
retired_over_70: "Answer cannot be over 70 as person %{person_num} has economic status that is not ‘retired’."
child_under_16_relat_lettings: "Answer cannot be under 16 as person %{person_num}'s relationship to the lead tenant is ‘partner’."
child_under_16_relat_sales: "Answer cannot be under 16 as person %{person_num}'s relationship to buyer 1 is ‘partner’."
child_under_16_ecstat: "Answer cannot be under 16 as person %{person_num}’s working situation is not ‘child under 16’, ‘other’ or ‘prefers not to say’."
child_over_16: "Answer cannot be over 16 as person’s %{person_num} working situation is ‘child under 16‘."
child_over_20: "Answer cannot be 20 or over as the relationship is ‘child’."
child_12_years_younger: "A child must be at least 12 years younger than their parent."
not_student_16_19: "Answer cannot be between 16 and 19 as person %{person_num} is a child of the lead tenant but is not a full-time student."
student_16_19:
cannot_be_16_19:
@ -522,12 +519,8 @@ en:
retired_female: "Answer cannot be ‘retired’ as the female tenant is under 60."
not_child_16_19:
cannot_be_student: "Person cannot be a student if they are aged 16-19 but are not a child."
buyer_cannot_be_child: "Buyer %{buyer_index} cannot have a working situation of child under 16."
buyer_cannot_be_over_16_and_child: "Buyer %{buyer_index}'s age cannot be 16 or over if their working situation is child under 16."
relat:
child_under_16_sales: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16."
child_under_16_lettings: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16."
child_over_20: "Answer cannot be ‘child’ if the person's age is 20 or over."
one_partner: "Number of partners cannot be greater than 1."
not_student_16_19: "Answer cannot be ‘child’ as you told us the person %{person_num} is between 16 and 19 and is not a full-time student."
student_16_19:
@ -550,7 +543,6 @@ en:
internal_transfer: "Answer cannot be %{prevten} as this tenancy is an internal transfer."
la_general_needs:
internal_transfer: "Answer cannot be a fixed-term or lifetime local authority general needs tenancy as it’s an internal transfer and a private registered provider is on the tenancy agreement."
invalid_for_discounted_sale: "Buyer 1’s previous tenure should be “local authority tenant” or “private registered provider or housing association tenant” for discounted sales."
referral:
secure_tenancy: "Answer must be internal transfer as this is a secure tenancy."
rsnvac_non_temp: "Answer cannot be this source of referral as this is a re-let to tenant who occupied the same property as temporary accommodation."
@ -590,9 +582,6 @@ en:
no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more."
postcode:
discounted_ownership: "Last settled accommodation and discounted ownership property postcodes must match."
buylivein:
buyers_will_live_in_property_values_inconsistent_setup: "You have already told us that both buyer 1 and buyer 2 will not live in the property."
buyers_will_live_in_property_values_inconsistent: "You have already told us that the buyers will live in the property. Either buyer 1 or buyer 2 must live in the property."
nationality: "Select a valid nationality."
tenancy:
@ -697,13 +686,6 @@ en:
message: "Net income is lower than expected based on the household’s working situation. Are you sure this is correct?"
in_soft_max_range:
message: "Net income is higher than expected based on the household’s working situation. Are you sure this is correct?"
income:
under_soft_min_for_economic_status:
title_text: "You told us income was %{income}."
hint_text: "This is less than we would expect for someone in this working situation."
over_soft_max_for_la_buyer_1: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
over_soft_max_for_la_buyer_2: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"
over_soft_max_for_la_combined: "You told us the combined income of this household is %{combined_income}. This seems high. Are you sure this is correct?"
rent:
outside_range_title: "You told us the rent is %{brent}."
informative_text: "This is %{higher_or_lower} than we would expect."
@ -766,24 +748,11 @@ Make sure these answers are correct."
percentage_discount_value:
title_text: "You told us that the percentage discount is %{discount}."
hint_text: "This is higher than we would expect."
savings:
title_text:
one: "You told us the buyer’s savings were %{savings}."
two: "You told us the buyers’ savings were %{savings}."
hint_text: "This is higher than we would expect."
deposit:
title_text:
one: "You told us the buyer’s deposit was %{deposit} and their savings were %{savings}."
two: "You told us the buyers’ deposit was %{deposit} and their savings were %{savings}."
hint_text: "The deposit amount is higher than we would expect for the amount of savings they have."
grant:
title_text: "You told us that the grant amount is %{grant}."
hint_text: "Loans, grants and subsidies are usually between £9,000 and £16,000."
wheelchair:
title_text: "You told us that someone in the household uses a wheelchair."
mortgage:
title_text: "You told us that the mortgage amount is %{mortgage}."
hint_text: "This is more than 5 times the income, which is higher than we would expect."
referral:
title_text: "Are you sure?"
hint_text: "This is a general needs log, and this referral type is for supported housing."
@ -853,9 +822,6 @@ Make sure these answers are correct."
soctenant:
one: "Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?"
other: "Were any of the buyers private registered providers, housing association or local authority tenants immediately before this sale?"
prevown:
one: "Has the buyer previously owned a property?"
other: "Have any of the buyers previously owned a property?"
stairowned:
one: "What percentage of the property does the buyer now own in total?"
other: "What percentage of the property do the buyers now own in total?"
@ -878,9 +844,6 @@ Make sure these answers are correct."
soctenant:
one: "Buyer was a registered provider, housing association or local authority tenant immediately before this sale?"
other: "Any buyers were registered providers, housing association or local authority tenants immediately before this sale?"
prevown:
one: "Buyer previously owned a property."
other: "Buyers previously owned a property."
stairowned:
one: "Percentage the buyer now owns in total."
other: "Percentage the buyers now own in total."

90
config/locales/forms/2023/sales/income_benefits_and_savings.en.yml

@ -0,0 +1,90 @@
en:
forms:
2023:
sales:
income_benefits_and_savings:
buyer_1_income:
page_header: ""
income1nk:
check_answer_label: "Buyer 1’s gross annual income known?"
hint_text: ""
question_text: "Do you know buyer 1’s annual income?"
income1:
check_answer_label: "Buyer 1’s gross annual income"
hint_text: "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
question_text: "Buyer 1’s gross annual income"
inc1mort:
page_header: ""
check_answer_label: "Buyer 1’s income used for mortgage application"
hint_text: ""
question_text: "Was buyer 1’s income used for a mortgage application?"
buyer_2_income:
page_header: ""
income2nk:
check_answer_label: "Buyer 2’s gross annual income known?"
hint_text: ""
question_text: "Do you know buyer 2’s annual income?"
income2:
check_answer_label: "Buyer 2’s gross annual income"
hint_text: "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
question_text: "Buyer 2’s gross annual income"
inc2mort:
page_header: ""
check_answer_label: "Buyer 2’s income used for mortgage application"
hint_text: ""
question_text: "Was buyer 2’s income used for a mortgage application?"
housing_benefits:
joint_purchase:
page_header: ""
check_answer_label: "Housing-related benefits buyers received before buying this property"
hint_text: ""
question_text: "Were the buyers receiving any of these housing-related benefits immediately before buying this property?"
not_joint_purchase:
page_header: ""
check_answer_label: "Housing-related benefits buyer received before buying this property"
hint_text: ""
question_text: "Was the buyer receiving any of these housing-related benefits immediately before buying this property?"
savings:
joint_purchase:
page_header: ""
savingsnk:
check_answer_label: "Buyers’ total savings known?"
hint_text: ""
question_text: "Do you know how much the 'buyers' had in savings before they paid any deposit for the property?"
savings:
check_answer_label: "Buyers’ total savings before any deposit paid"
hint_text: "Include any savings, investments, ISAs, premium bonds, shares, or money held in a bank or building society account."
question_text: "Enter their total savings to the nearest £10"
not_joint_purchase:
page_header: ""
savingsnk:
check_answer_label: "Buyer’s total savings known?"
hint_text: ""
question_text: "Do you know how much the buyer had in savings before they paid any deposit for the property?"
savings:
check_answer_label: "Buyer’s total savings before any deposit paid"
hint_text: "Include any savings, investments, ISAs, premium bonds, shares, or money held in a bank or building society account."
question_text: "Enter their total savings to the nearest £10"
prevown:
joint_purchase:
page_header: ""
check_answer_label: "Buyers previously owned a property."
hint_text: ""
question_text: "Have any of the buyers previously owned a property?"
not_joint_purchase:
page_header: ""
check_answer_label: "Buyer previously owned a property."
hint_text: ""
question_text: "Has the buyer previously owned a property?"
prevshared:
page_header: ""
check_answer_label: "Previous property shared ownership?"
hint_text: "For any buyer"
question_text: "Was the previous property under shared ownership?"

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

@ -0,0 +1,60 @@
en:
forms:
2023:
sales:
soft_validations:
income1_value_check:
page_header: ""
check_answer_label: "Buyer 1 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
income2_value_check:
page_header: ""
check_answer_label: "Buyer 2 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"
combined_income_value_check:
page_header: ""
check_answer_label: "Combined income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
title_text: "You told us the combined income of this household is %{combined_income}. This seems high. Are you sure this is correct?"
mortgage_value_check:
page_header: ""
check_answer_label: "Mortgage confirmation"
hint_text: ""
question_text: "Are you sure that the mortgage is more than 5 times the income used for the mortgage application?"
title_text: "You told us that the mortgage amount is %{mortgage}."
informative_text: "This is more than 5 times the income, which is higher than we would expect."
savings_value_check:
page_header: ""
check_answer_label: "Savings confirmation"
hint_text: ""
question_text: "Are you sure the savings are higher than £100,000?"
joint_purchase:
title_text: You told us the buyers’ savings were %{savings}."
informative_text: "This is higher than we would expect."
not_joint_purchase:
title_text: "You told us the buyer’s savings were %{savings}."
informative_text: "This is higher than we would expect."
deposit_value_check::
page_header: ""
check_answer_label: "Deposit confirmation"
hint_text: ""
question_text: "Are you sure that the deposit is this much higher than the buyer's savings?"
joint_purchase:
title_text: "You told us the buyers’ deposit was %{deposit} and their savings were %{savings}."
informative_text: "The deposit amount is higher than we would expect for the amount of savings they have."
not_joint_purchase:
title_text: "You told us the buyer’s deposit was %{deposit} and their savings were %{savings}."
informative_text: "The deposit amount is higher than we would expect for the amount of savings they have."

90
config/locales/forms/2024/sales/income_benefits_and_savings.en.yml

@ -0,0 +1,90 @@
en:
forms:
2024:
sales:
income_benefits_and_savings:
buyer_1_income:
page_header: ""
income1nk:
check_answer_label: "Buyer 1’s gross annual income known?"
hint_text: ""
question_text: "Do you know buyer 1’s annual income?"
income1:
check_answer_label: "Buyer 1’s gross annual income"
hint_text: "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
question_text: "Buyer 1’s gross annual income"
inc1mort:
page_header: ""
check_answer_label: "Buyer 1’s income used for mortgage application"
hint_text: ""
question_text: "Was buyer 1’s income used for a mortgage application?"
buyer_2_income:
page_header: ""
income2nk:
check_answer_label: "Buyer 2’s gross annual income known?"
hint_text: ""
question_text: "Do you know buyer 2’s annual income?"
income2:
check_answer_label: "Buyer 2’s gross annual income"
hint_text: "Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments."
question_text: "Buyer 2’s gross annual income"
inc2mort:
page_header: ""
check_answer_label: "Buyer 2’s income used for mortgage application"
hint_text: ""
question_text: "Was buyer 2’s income used for a mortgage application?"
housing_benefits:
joint_purchase:
page_header: ""
check_answer_label: "Housing-related benefits buyers received before buying this property"
hint_text: ""
question_text: "Were the buyers receiving any of these housing-related benefits immediately before buying this property?"
not_joint_purchase:
page_header: ""
check_answer_label: "Housing-related benefits buyer received before buying this property"
hint_text: ""
question_text: "Was the buyer receiving any of these housing-related benefits immediately before buying this property?"
savings:
joint_purchase:
page_header: ""
savingsnk:
check_answer_label: "Buyers’ total savings known?"
hint_text: ""
question_text: "Do you know how much the 'buyers' had in savings before they paid any deposit for the property?"
savings:
check_answer_label: "Buyers’ total savings before any deposit paid"
hint_text: "Include any savings, investments, ISAs, premium bonds, shares, or money held in a bank or building society account."
question_text: "Enter their total savings to the nearest £10"
not_joint_purchase:
page_header: ""
savingsnk:
check_answer_label: "Buyer’s total savings known?"
hint_text: ""
question_text: "Do you know how much the buyer had in savings before they paid any deposit for the property?"
savings:
check_answer_label: "Buyer’s total savings before any deposit paid"
hint_text: "Include any savings, investments, ISAs, premium bonds, shares, or money held in a bank or building society account."
question_text: "Enter their total savings to the nearest £10"
prevown:
joint_purchase:
page_header: ""
check_answer_label: "Buyers previously owned a property."
hint_text: ""
question_text: "Have any of the buyers previously owned a property?"
not_joint_purchase:
page_header: ""
check_answer_label: "Buyer previously owned a property."
hint_text: ""
question_text: "Has the buyer previously owned a property?"
prevshared:
page_header: ""
check_answer_label: "Previous property shared ownership?"
hint_text: "For any buyer"
question_text: "Was the previous property under shared ownership?"

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

@ -0,0 +1,60 @@
en:
forms:
2024:
sales:
soft_validations:
income1_value_check:
page_header: ""
check_answer_label: "Buyer 1 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 1 is %{income}. This seems high. Are you sure this is correct?"
income2_value_check:
page_header: ""
check_answer_label: "Buyer 2 income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
min:
title_text: "You told us income was %{income}."
informative_text: "This is less than we would expect for someone in this working situation."
max:
title_text: "You told us the income of buyer 2 is %{income}. This seems high. Are you sure this is correct?"
combined_income_value_check:
page_header: ""
check_answer_label: "Combined income confirmation"
hint_text: ""
question_text: "Are you sure this is correct?"
title_text: "You told us the combined income of this household is %{combined_income}. This seems high. Are you sure this is correct?"
mortgage_value_check:
page_header: ""
check_answer_label: "Mortgage confirmation"
hint_text: ""
question_text: "Are you sure that the mortgage is more than 5 times the income used for the mortgage application?"
title_text: "You told us that the mortgage amount is %{mortgage}."
informative_text: "This is more than 5 times the income, which is higher than we would expect."
savings_value_check:
page_header: ""
check_answer_label: "Savings confirmation"
hint_text: ""
question_text: "Are you sure the savings are higher than £100,000?"
joint_purchase:
title_text: You told us the buyers’ savings were %{savings}."
informative_text: "This is higher than we would expect."
not_joint_purchase:
title_text: "You told us the buyer’s savings were %{savings}."
informative_text: "This is higher than we would expect."
deposit_value_check:
page_header: ""
check_answer_label: "Deposit confirmation"
hint_text: ""
question_text: "Are you sure that the deposit is this much higher than the buyer's savings?"
joint_purchase:
title_text: "You told us the buyers’ deposit was %{deposit} and their savings were %{savings}."
informative_text: "The deposit amount is higher than we would expect for the amount of savings they have."
not_joint_purchase:
title_text: "You told us the buyer’s deposit was %{deposit} and their savings were %{savings}."
informative_text: "The deposit amount is higher than we would expect for the amount of savings they have."

47
config/locales/validations/sales/household.en.yml

@ -0,0 +1,47 @@
en:
validations:
sales:
household:
buylivein:
buyers_will_live_in_property_values_inconsistent: "You have already told us that both buyer 1 and buyer 2 will not live in the property."
buy1livein:
buyers_will_live_in_property_values_inconsistent: "You have already told us that the buyers will live in the property. Either buyer 1 or buyer 2 must live in the property."
buy2livein:
buyers_will_live_in_property_values_inconsistent: "You have already told us that the buyers will live in the property. Either buyer 1 or buyer 2 must live in the property."
ownershipsch:
prevten_invalid_for_discounted_sale: "Buyer 1’s previous tenure should be “local authority tenant” or “private registered provider or housing association tenant” for discounted sales."
prevten:
prevten_invalid_for_discounted_sale: "Buyer 1’s previous tenure should be “local authority tenant” or “private registered provider or housing association tenant” for discounted sales."
age1:
child_12_years_younger: "A child must be at least 12 years younger than their parent."
ecstat1:
buyer_cannot_be_child: "Buyer 1 cannot have a working situation of child under 16."
ecstat2:
buyer_cannot_be_child: "Buyer 2 cannot have a working situation of child under 16."
age:
child_12_years_younger: "A child must be at least 12 years younger than their parent."
child_under_16: "Answer cannot be under 16 as person %{person_num}'s relationship to buyer 1 is ‘partner’."
child_under_16_ecstat: "Answer cannot be under 16 as person %{person_num}’s working situation is not ‘child under 16’, ‘other’ or ‘prefers not to say’."
child_over_16: "Answer cannot be over 16 as person’s %{person_num} working situation is ‘child under 16‘."
child_over_20: "Answer cannot be 20 or over as the relationship is ‘child’."
student_16_19:
cannot_be_16_19:
child_not_student: "Person cannot be aged 16-19 if they have relationship ‘child’ but are not a student."
must_be_16_19: "Person must be aged 16-19 if they are a student and have relationship ‘child’."
relat:
one_partner: "Number of partners cannot be greater than 1."
child_12_years_younger: "A child must be at least 12 years younger than their parent."
child_under_16: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16."
child_over_20: "Answer cannot be ‘child’ if the person's age is 20 or over."
student_16_19:
cannot_be_child:
student_not_16_19: "Answer cannot be ‘child’ if the person is a student but not aged 16-19."
16_19_not_student: "Answer cannot be ‘child’ if the person is aged 16-19 but not a student."
ecstat:
child_under_16: "Person %{person_num}’s working situation must be ‘child under 16’, ‘other’ or ‘prefers not to say’ as you told us they’re under 16."
child_over_16: "Answer cannot be ‘child under 16’ as you told us the person %{person_num} is older than 16."
student_16_19:
must_be_student: "Person must be a student if they are aged 16-19 and have relationship ‘child’."
cannot_be_student:
child_not_16_19: "Person cannot be a student if they are not aged 16-19 but have relationship ‘child’."
buyer_cannot_be_over_16_and_child: "Buyer %{buyer_index}'s age cannot be 16 or over if their working situation is child under 16."

3
spec/models/form/sales/pages/buyer1_income_max_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeMaxValueCheck, type: :model do
let(:page_id) { "prefix_buyer_1_income_max_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/buyer1_income_min_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeMinValueCheck, type: :model do
let(:page_id) { "prefix_buyer_1_income_min_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/buyer2_income_max_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::Buyer2IncomeMaxValueCheck, type: :model do
let(:page_id) { "prefix_buyer_2_income_max_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/buyer2_income_min_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::Buyer2IncomeMinValueCheck, type: :model do
let(:page_id) { "prefix_buyer_2_income_min_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

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

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::CombinedIncomeMaxValueCheck, type: :model do
let(:page_id) { "prefix_combined_income_max_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/deposit_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::DepositValueCheck, type: :model do
let(:page_id) { "deposit_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/mortgage_value_check_spec.rb

@ -6,7 +6,8 @@ RSpec.describe Form::Sales::Pages::MortgageValueCheck, type: :model do
let(:page_id) { "buyer_1_income_mortgage_value_check" }
let(:page_definition) { nil }
let(:index) { 1 }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

3
spec/models/form/sales/pages/savings_value_check_spec.rb

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Pages::SavingsValueCheck, type: :model do
let(:page_id) { "savings_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)

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

@ -5,7 +5,8 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model
let(:subsection_id) { nil }
let(:subsection_definition) { nil }
let(:section) { instance_double(Form::Sales::Sections::SaleInformation) }
let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
let(:section) { instance_double(Form::Sales::Sections::SaleInformation, form:) }
it "has correct section" do
expect(discounted_ownership_scheme.section).to eq(section)

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

@ -8,7 +8,7 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipScheme, type: :model do
let(:section) { instance_double(Form::Sales::Sections::SaleInformation) }
before do
allow(section).to receive(:form).and_return(instance_double(Form, start_year_after_2024?: false))
allow(section).to receive(:form).and_return(instance_double(Form, start_year_after_2024?: false, start_date: Time.zone.local(2023, 4, 1)))
end
it "has correct section" do

17
spec/models/forms/bulk_upload_lettings/guidance_spec.rb

@ -6,6 +6,7 @@ RSpec.describe Forms::BulkUploadLettings::Guidance do
subject(:bu_guidance) { described_class.new(year:, referrer:) }
let(:year) { 2024 }
let(:referrer) { nil }
describe "#back_path" do
context "when referrer is prepare-your-file" do
@ -40,4 +41,20 @@ RSpec.describe Forms::BulkUploadLettings::Guidance do
end
end
end
describe "year" do
context "when year is not provided" do
let(:year) { nil }
before do
# rubocop:disable RSpec/AnyInstance
allow_any_instance_of(CollectionTimeHelper).to receive(:current_collection_start_year).and_return(2030)
# rubocop:enable RSpec/AnyInstance
end
it "is set to the current collection start year" do
expect(bu_guidance.year).to eq(2030)
end
end
end
end

17
spec/models/forms/bulk_upload_sales/guidance_spec.rb

@ -6,6 +6,7 @@ RSpec.describe Forms::BulkUploadSales::Guidance do
subject(:bu_guidance) { described_class.new(year:, referrer:) }
let(:year) { 2024 }
let(:referrer) { nil }
describe "#back_path" do
context "when referrer is prepare-your-file" do
@ -40,4 +41,20 @@ RSpec.describe Forms::BulkUploadSales::Guidance do
end
end
end
describe "year" do
context "when year is not provided" do
let(:year) { nil }
before do
# rubocop:disable RSpec/AnyInstance
allow_any_instance_of(CollectionTimeHelper).to receive(:current_collection_start_year).and_return(2030)
# rubocop:enable RSpec/AnyInstance
end
it "is set to the current collection start year" do
expect(bu_guidance.year).to eq(2030)
end
end
end
end

50
spec/models/validations/sales/household_validations_spec.rb

@ -15,11 +15,11 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat3 = "P"
household_validator.validate_partner_count(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.one_partner"))
.to include(match I18n.t("validations.sales.household.relat.one_partner"))
expect(record.errors["relat3"])
.to include(match I18n.t("validations.household.relat.one_partner"))
.to include(match I18n.t("validations.sales.household.relat.one_partner"))
expect(record.errors["relat4"])
.not_to include(match I18n.t("validations.household.relat.one_partner"))
.not_to include(match I18n.t("validations.sales.household.relat.one_partner"))
end
it "expects that a tenant can have a partner" do
@ -47,9 +47,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat2 = "P"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.child_under_16_sales", person_num: 2))
.to include(match I18n.t("validations.sales.household.relat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.child_under_16_relat_sales", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_under_16", person_num: 2))
end
end
@ -58,9 +58,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat2 = "C"
household_validator.validate_person_age_matches_relationship(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.child_over_20"))
.to include(match I18n.t("validations.sales.household.relat.child_over_20"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.child_over_20"))
.to include(match I18n.t("validations.sales.household.age.child_over_20"))
end
end
@ -94,9 +94,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.ecstat2 = 1
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.household.ecstat.child_under_16", person_num: 2))
.to include(match I18n.t("validations.sales.household.ecstat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.child_under_16_ecstat", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_under_16_ecstat", person_num: 2))
end
it "expects that person's economic status is Child" do
@ -112,9 +112,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.ecstat2 = 9
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.household.ecstat.child_over_16", person_num: 2))
.to include(match I18n.t("validations.sales.household.ecstat.child_over_16", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.child_over_16", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_over_16", person_num: 2))
end
end
@ -126,9 +126,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.ecstat2 = 1
household_validator.validate_person_age_matches_economic_status(record)
expect(record.errors["ecstat2"])
.not_to include(match I18n.t("validations.household.ecstat.child_under_16", person_num: 2))
.not_to include(match I18n.t("validations.sales.household.ecstat.child_under_16", person_num: 2))
expect(record.errors["age2"])
.not_to include(match I18n.t("validations.household.age.child_under_16_ecstat", person_num: 2))
.not_to include(match I18n.t("validations.sales.household.age.child_under_16_ecstat", person_num: 2))
end
end
end
@ -143,11 +143,11 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat2 = "C"
household_validator.validate_child_12_years_younger(record)
expect(record.errors["age1"])
.to include(match I18n.t("validations.household.age.child_12_years_younger", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.child_12_years_younger", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.age.child_12_years_younger", person_num: 2))
.to include(match I18n.t("validations.sales.household.age.child_12_years_younger", person_num: 2))
end
it "expects the child is at least 12 years younger than buyer 1" do
@ -206,11 +206,11 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.student_16_19.cannot_be_child.16_19_not_student"))
.to include(match I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.16_19_not_student"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.student_16_19.cannot_be_16_19.child_not_student"))
.to include(match I18n.t("validations.sales.household.age.student_16_19.cannot_be_16_19.child_not_student"))
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.household.ecstat.student_16_19.must_be_student"))
.to include(match I18n.t("validations.sales.household.ecstat.student_16_19.must_be_student"))
end
it "adds errors for a person who is a child of the buyer and a student but not aged 16-19" do
@ -219,11 +219,11 @@ RSpec.describe Validations::Sales::HouseholdValidations do
record.relat2 = "C"
household_validator.validate_person_age_and_relationship_matches_economic_status(record)
expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.student_16_19.cannot_be_child.student_not_16_19"))
.to include(match I18n.t("validations.sales.household.relat.student_16_19.cannot_be_child.student_not_16_19"))
expect(record.errors["age2"])
.to include(match I18n.t("validations.household.age.student_16_19.must_be_16_19"))
.to include(match I18n.t("validations.sales.household.age.student_16_19.must_be_16_19"))
expect(record.errors["ecstat2"])
.to include(match I18n.t("validations.household.ecstat.student_16_19.cannot_be_student.child_not_16_19"))
.to include(match I18n.t("validations.sales.household.ecstat.student_16_19.cannot_be_student.child_not_16_19"))
end
end
@ -316,9 +316,9 @@ RSpec.describe Validations::Sales::HouseholdValidations do
it "triggers a validation if buyer two will also not live in the property" do
sales_log.buy2livein = 2
household_validator.validate_buyers_living_in_property(sales_log)
expect(sales_log.errors[:buylivein]).to include I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent_setup")
expect(sales_log.errors[:buy2livein]).to include I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy1livein]).to include I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buylivein]).to include I18n.t("validations.sales.household.buylivein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy2livein]).to include I18n.t("validations.sales.household.buy2livein.buyers_will_live_in_property_values_inconsistent")
expect(sales_log.errors[:buy1livein]).to include I18n.t("validations.sales.household.buy1livein.buyers_will_live_in_property_values_inconsistent")
end
end
end

8
spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

@ -2718,6 +2718,14 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "strips whitespace" do
expect(parser.log.postcode_full).to eql("EC1N 2TD")
end
context "when a partial postcode is provided" do
let(:attributes) { { bulk_upload:, field_4: 1, field_21: "EC1N", field_22: "" } }
it "is set to the partial value" do
expect(parser.log.postcode_full).to eql("EC1N")
end
end
end
describe "#la" do

Loading…
Cancel
Save