Browse Source

Merge branch 'main' into CLDC-2199-uprn-soft-validation-bugs

pull/1538/head
natdeanlewissoftwire 2 years ago
parent
commit
88b190eea9
  1. 2
      Gemfile
  2. 8
      app/components/bulk_upload_error_row_component.rb
  3. 4
      app/components/bulk_upload_error_summary_table_component.rb
  4. 6
      app/controllers/form_controller.rb
  5. 2
      app/controllers/locations_controller.rb
  6. 8
      app/helpers/collection_time_helper.rb
  7. 6
      app/helpers/locations_helper.rb
  8. 2
      app/helpers/navigation_items_helper.rb
  9. 20
      app/helpers/question_view_helper.rb
  10. 2
      app/helpers/tasklist_helper.rb
  11. 3
      app/models/bulk_upload_error.rb
  12. 49
      app/models/form.rb
  13. 14
      app/models/form/lettings/pages/care_home_weekly.rb
  14. 12
      app/models/form/lettings/pages/max_rent_value_check.rb
  15. 10
      app/models/form/lettings/pages/min_rent_value_check.rb
  16. 12
      app/models/form/lettings/pages/net_income_value_check.rb
  17. 2
      app/models/form/lettings/pages/outstanding_amount.rb
  18. 6
      app/models/form/lettings/pages/rent_4_weekly.rb
  19. 6
      app/models/form/lettings/pages/rent_bi_weekly.rb
  20. 6
      app/models/form/lettings/pages/rent_monthly.rb
  21. 26
      app/models/form/lettings/pages/rent_weekly.rb
  22. 5
      app/models/form/lettings/pages/uprn.rb
  23. 16
      app/models/form/lettings/pages/uprn_known.rb
  24. 2
      app/models/form/lettings/questions/location_id.rb
  25. 9
      app/models/form/lettings/questions/period.rb
  26. 9
      app/models/form/lettings/questions/scheme_id.rb
  27. 1
      app/models/form/lettings/questions/tshortfall.rb
  28. 13
      app/models/form/lettings/questions/uprn.rb
  29. 2
      app/models/form/lettings/questions/uprn_known.rb
  30. 1
      app/models/form/lettings/subsections/property_information.rb
  31. 24
      app/models/form/question.rb
  32. 21
      app/models/form/sales/pages/buyer_live_in_value_check.rb
  33. 16
      app/models/form/sales/pages/discounted_sale_value_check.rb
  34. 15
      app/models/form/sales/pages/percentage_discount_value_check.rb
  35. 4
      app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
  36. 1
      app/models/form/sales/pages/uprn.rb
  37. 12
      app/models/form/sales/pages/uprn_known.rb
  38. 24
      app/models/form/sales/questions/buyer_live_in_value_check.rb
  39. 23
      app/models/form/sales/questions/percentage_discount_value_check.rb
  40. 13
      app/models/form/sales/questions/uprn.rb
  41. 8
      app/models/form/sales/questions/uprn_known.rb
  42. 1
      app/models/form/sales/subsections/discounted_ownership_scheme.rb
  43. 2
      app/models/form/sales/subsections/household_characteristics.rb
  44. 2
      app/models/form/sales/subsections/property_information.rb
  45. 2
      app/models/form/sales/subsections/setup.rb
  46. 26
      app/models/lettings_log.rb
  47. 1
      app/models/location.rb
  48. 17
      app/models/log.rb
  49. 20
      app/models/sales_log.rb
  50. 12
      app/models/scheme.rb
  51. 8
      app/models/validations/financial_validations.rb
  52. 2
      app/models/validations/sales/sale_information_validations.rb
  53. 24
      app/models/validations/sales/soft_validations.rb
  54. 8
      app/models/validations/setup_validations.rb
  55. 1
      app/models/validations/shared_validations.rb
  56. 68
      app/services/bulk_upload/lettings/year2022/row_parser.rb
  57. 9
      app/services/bulk_upload/lettings/year2023/row_parser.rb
  58. 46
      app/services/bulk_upload/sales/year2022/row_parser.rb
  59. 9
      app/services/exports/lettings_log_export_service.rb
  60. 10
      app/services/feature_toggle.rb
  61. 2
      app/services/imports/lettings_logs_import_service.rb
  62. 6
      app/services/imports/sales_logs_import_service.rb
  63. 6
      app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb
  64. 1
      app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb
  65. 2
      app/views/bulk_upload_lettings_results/show.html.erb
  66. 6
      app/views/bulk_upload_sales_logs/forms/checking_file.html.erb
  67. 1
      app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb
  68. 16
      app/views/form/_select_question.html.erb
  69. 2
      app/views/form/page.html.erb
  70. 1
      app/views/locations/availability.erb
  71. 1
      app/views/locations/check_answers.html.erb
  72. 1
      app/views/locations/index.html.erb
  73. 1
      app/views/locations/local_authority.html.erb
  74. 1
      app/views/locations/mobility_standards.html.erb
  75. 1
      app/views/locations/name.html.erb
  76. 1
      app/views/locations/postcode.html.erb
  77. 1
      app/views/locations/show.html.erb
  78. 1
      app/views/locations/toggle_active.html.erb
  79. 1
      app/views/locations/type_of_unit.html.erb
  80. 1
      app/views/locations/units.html.erb
  81. 8
      app/views/logs/index.html.erb
  82. 48
      app/views/organisations/merge.html.erb
  83. 3
      app/views/organisations/show.html.erb
  84. 1
      app/views/schemes/confirm_secondary.html.erb
  85. 5
      app/views/schemes/details.html.erb
  86. 5
      app/views/schemes/edit_name.html.erb
  87. 5
      app/views/schemes/new.html.erb
  88. 5
      app/views/schemes/primary_client_group.html.erb
  89. 1
      app/views/schemes/secondary_client_group.html.erb
  90. 1
      app/views/schemes/show.html.erb
  91. 1
      app/views/schemes/support.html.erb
  92. 1
      app/views/schemes/toggle_active.html.erb
  93. 201
      config/forms/2022_2023.json
  94. 2
      config/initializers/filter_parameter_logging.rb
  95. 35
      config/locales/en.yml
  96. 1
      config/routes.rb
  97. 5
      db/migrate/20230405074138_add_percentage_discount_value_check.rb
  98. 5
      db/migrate/20230405140343_add_buyer_livin_value_check.rb
  99. 2
      db/schema.rb
  100. BIN
      public/files/bulk-upload-lettings-specification-2023-24.xlsx
  101. Some files were not shown because too many files have changed in this diff Show More

2
Gemfile

@ -70,6 +70,7 @@ group :development, :test do
gem "byebug", platforms: %i[mri mingw x64_mingw]
gem "dotenv-rails"
gem "factory_bot_rails"
gem "faker"
gem "pry-byebug"
gem "parallel_tests"
@ -93,7 +94,6 @@ group :test do
gem "capybara", require: false
gem "capybara-lockstep"
gem "capybara-screenshot"
gem "faker"
gem "rspec-rails", require: false
gem "selenium-webdriver", require: false
gem "simplecov", require: false

8
app/components/bulk_upload_error_row_component.rb

@ -2,7 +2,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
attr_reader :bulk_upload_errors
def initialize(bulk_upload_errors:)
@bulk_upload_errors = sorted_errors(bulk_upload_errors)
@bulk_upload_errors = bulk_upload_errors
super
end
@ -62,10 +62,4 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def sales?
bulk_upload.log_type == "sales"
end
private
def sorted_errors(errors)
errors.sort_by { |e| e.cell.rjust(3, "0") }
end
end

4
app/components/bulk_upload_error_summary_table_component.rb

@ -16,8 +16,8 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
.bulk_upload_errors
.group(:col, :field, :error)
.having("count(*) >= ?", display_threshold)
.order_by_col
.count
.sort_by { |el| el[0][0].rjust(3, "0") }
end
def errors?
@ -39,8 +39,8 @@ private
.bulk_upload_errors
.where(category: "setup")
.group(:col, :field, :error)
.order_by_col
.count
.sort_by { |el| el[0][0].rjust(3, "0") }
end
def display_threshold

6
app/controllers/form_controller.rb

@ -122,11 +122,9 @@ private
def successful_redirect_path
if is_referrer_check_answers?
page_ids = form.subsection_for_page(@page).pages.map(&:id)
page_index = page_ids.index(@page.id)
next_page_id = form.next_page(@page, @log, current_user)
next_page_id = form.next_page_id(@page, @log, current_user)
next_page = form.get_page(next_page_id)
previous_page = form.previous_page(page_ids, page_index, @log, current_user)
previous_page = form.previous_page_id(@page, @log, current_user)
if next_page&.interruption_screen? || next_page_id == previous_page || CONFIRMATION_PAGE_IDS.include?(next_page_id)
return send("#{@log.class.name.underscore}_#{next_page_id}_path", @log, { referrer: "check_answers" })

2
app/controllers/locations_controller.rb

@ -134,7 +134,7 @@ class LocationsController < ApplicationController
def check_answers; end
def confirm
flash[:notice] = "#{@location.postcode} #{@location.startdate.blank? || @location.startdate < Time.zone.now ? 'has been' : 'will be'} added to this scheme"
flash[:notice] = helpers.location_creation_success_notice(@location)
redirect_to scheme_locations_path(@scheme)
end

8
app/helpers/collection_time_helper.rb

@ -1,15 +1,15 @@
module CollectionTimeHelper
def collection_start_year(date)
def collection_start_year_for_date(date)
window_end_date = Time.zone.local(date.year, 4, 1)
date < window_end_date ? date.year - 1 : date.year
end
def current_collection_start_year
collection_start_year(Time.zone.now)
collection_start_year_for_date(Time.zone.now)
end
def collection_start_date(date)
Time.zone.local(collection_start_year(date), 4, 1)
Time.zone.local(collection_start_year_for_date(date), 4, 1)
end
def date_mid_collection_year_formatted(date)
@ -22,7 +22,7 @@ module CollectionTimeHelper
end
def collection_end_date(date)
Time.zone.local(collection_start_year(date) + 1, 3, 31).end_of_day
Time.zone.local(collection_start_year_for_date(date) + 1, 3, 31).end_of_day
end
def current_collection_end_date

6
app/helpers/locations_helper.rb

@ -78,6 +78,12 @@ module LocationsHelper
return govuk_button_link_to "Reactivate this location", scheme_location_new_reactivation_path(location.scheme, location) if location.deactivated?
end
def location_creation_success_notice(location)
if location.confirmed
"#{location.postcode} #{location.startdate.blank? || location.startdate.before?(Time.zone.now) ? 'has been' : 'will be'} added to this scheme"
end
end
private
ActivePeriod = Struct.new(:from, :to)

2
app/helpers/navigation_items_helper.rb

@ -101,7 +101,7 @@ private
end
def subnav_details_path?(path)
path.include?("/organisations") && path.include?("/details")
path.include?("/organisations") && (path.include?("/details") || path.include?("/merge"))
end
def stock_owners_path?(path)

20
app/helpers/question_view_helper.rb

@ -13,6 +13,26 @@ module QuestionViewHelper
}
end
def answer_option_synonyms(resource)
return unless resource.instance_of?(Scheme)
resource.locations.map(&:postcode).join(",")
end
def answer_option_append(resource)
return unless resource.instance_of?(Scheme)
confirmed_locations_count = resource.locations.confirmed.size
unconfirmed_locations_count = resource.locations.unconfirmed.size
"#{confirmed_locations_count} completed #{'location'.pluralize(confirmed_locations_count)}, #{unconfirmed_locations_count} incomplete #{'location'.pluralize(unconfirmed_locations_count)}"
end
def answer_option_hint(resource)
return unless resource.instance_of?(Scheme)
[resource.primary_client_group, resource.secondary_client_group].compact.join(", ")
end
private
def label_size(page_header, conditional, question)

2
app/helpers/tasklist_helper.rb

@ -15,7 +15,7 @@ module TasklistHelper
if subsection.pages.first.routed_to?(log, current_user)
subsection.pages.first.id
else
log.form.next_page(subsection.pages.first, log, current_user)
log.form.next_page_id(subsection.pages.first, log, current_user)
end
end

3
app/models/bulk_upload_error.rb

@ -1,3 +1,6 @@
class BulkUploadError < ApplicationRecord
belongs_to :bulk_upload
scope :order_by_cell, -> { order(Arel.sql("LPAD(cell, 10, '0')")) }
scope :order_by_col, -> { order(Arel.sql("LPAD(col, 10, '0')")) }
end

49
app/models/form.rb

@ -61,30 +61,54 @@ class Form
subsections.find { |s| s.pages.find { |p| p.id == page.id } }
end
def next_page(page, log, current_user)
def next_page_id(page, log, current_user)
return page.next_unresolved_page_id || :check_answers if log.unresolved
page_ids = subsection_for_page(page).pages.map(&:id)
page_index = page_ids.index(page.id)
page_id = if page.interruption_screen? && log[page.questions[0].id] == 1 && page.routed_to?(log, current_user)
previous_page(page_ids, page_index, log, current_user)
previous_page_id(page, log, current_user)
else
page_ids[page_index + 1]
end
nxt_page = get_page(page_id)
next_page = get_page(page_id)
return :check_answers if nxt_page.nil?
return nxt_page.id if nxt_page.routed_to?(log, current_user)
return :check_answers if next_page.nil?
return next_page.id if next_page.routed_to?(log, current_user)
next_page(nxt_page, log, current_user)
next_page_id(next_page, log, current_user)
end
def next_page_redirect_path(page, log, current_user)
nxt_page = next_page(page, log, current_user)
if nxt_page == :check_answers
next_page_id = next_page_id(page, log, current_user)
if next_page_id == :check_answers
"#{type}_log_#{subsection_for_page(page).id}_check_answers_path"
else
"#{type}_log_#{nxt_page}_path"
"#{type}_log_#{next_page_id}_path"
end
end
def previous_page_id(page, log, current_user)
page_ids = subsection_for_page(page).pages.map(&:id)
page_index = page_ids.index(page.id)
return :tasklist if page_index.zero?
page_id = page_ids[page_index - 1]
previous_page = get_page(page_id)
return previous_page.id if previous_page.routed_to?(log, current_user)
previous_page_id(previous_page, log, current_user)
end
def previous_page_redirect_path(page, log, current_user, referrer)
previous_page_id = previous_page_id(page, log, current_user)
if referrer == "check_answers"
"#{type}_log_#{subsection_for_page(page).id}_check_answers_path"
elsif previous_page_id == :tasklist
"#{type}_log_path"
else
"#{type}_log_#{previous_page_id}_path"
end
end
@ -206,13 +230,6 @@ class Form
questions.select { |q| q.type == "numeric" }
end
def previous_page(page_ids, page_index, log, current_user)
prev_page = get_page(page_ids[page_index - 1])
return prev_page.id if prev_page.routed_to?(log, current_user)
previous_page(page_ids, page_index - 1, log, current_user)
end
def send_chain(arr, log)
Array(arr).inject(log) { |o, a| o.public_send(*a) }
end

14
app/models/form/lettings/pages/care_home_weekly.rb

@ -3,18 +3,8 @@ class Form::Lettings::Pages::CareHomeWeekly < ::Form::Page
super
@id = "care_home_weekly"
@depends_on = [
{ "period" => 1, "needstype" => 2, "household_charge" => 0 },
{ "period" => 1, "needstype" => 2, "household_charge" => nil },
{ "period" => 5, "needstype" => 2, "household_charge" => 0 },
{ "period" => 5, "needstype" => 2, "household_charge" => nil },
{ "period" => 6, "needstype" => 2, "household_charge" => 0 },
{ "period" => 6, "needstype" => 2, "household_charge" => nil },
{ "period" => 7, "needstype" => 2, "household_charge" => 0 },
{ "period" => 7, "needstype" => 2, "household_charge" => nil },
{ "period" => 8, "needstype" => 2, "household_charge" => 0 },
{ "period" => 8, "needstype" => 2, "household_charge" => nil },
{ "period" => 9, "needstype" => 2, "household_charge" => 0 },
{ "period" => 9, "needstype" => 2, "household_charge" => nil },
{ "rent_and_charges_paid_weekly?" => true, "is_supported_housing?" => true, "household_charge" => 0 },
{ "rent_and_charges_paid_weekly?" => true, "is_supported_housing?" => true, "household_charge" => nil },
]
end

12
app/models/form/lettings/pages/max_rent_value_check.rb

@ -4,14 +4,20 @@ class Form::Lettings::Pages::MaxRentValueCheck < ::Form::Page
@depends_on = [{ "rent_in_soft_max_range?" => true }]
@title_text = {
"translation" => "soft_validations.rent.outside_range_title",
"arguments" => [{ "key" => "brent", "label" => true, "i18n_template" => "brent" }],
"arguments" => [
{
"key" => "brent",
"label" => true,
"i18n_template" => "brent",
},
],
}
@informative_text = {
"translation" => "soft_validations.rent.max_hint_text",
"arguments" => [
{
"key" => "soft_max_for_period",
"label" => false,
"key" => "field_formatted_as_currency",
"arguments_for_key" => "soft_max_for_period",
"i18n_template" => "soft_max_for_period",
},
],

10
app/models/form/lettings/pages/min_rent_value_check.rb

@ -4,14 +4,18 @@ class Form::Lettings::Pages::MinRentValueCheck < ::Form::Page
@depends_on = [{ "rent_in_soft_min_range?" => true }]
@title_text = {
"translation" => "soft_validations.rent.outside_range_title",
"arguments" => [{ "key" => "brent", "label" => true, "i18n_template" => "brent" }],
"arguments" => [{
"key" => "brent",
"label" => true,
"i18n_template" => "brent",
}],
}
@informative_text = {
"translation" => "soft_validations.rent.min_hint_text",
"arguments" => [
{
"key" => "soft_min_for_period",
"label" => false,
"key" => "field_formatted_as_currency",
"arguments_for_key" => "soft_min_for_period",
"i18n_template" => "soft_min_for_period",
},
],

12
app/models/form/lettings/pages/net_income_value_check.rb

@ -7,8 +7,16 @@ class Form::Lettings::Pages::NetIncomeValueCheck < ::Form::Page
@informative_text = {
"translation" => "soft_validations.net_income.hint_text",
"arguments" => [
{ "key" => "ecstat1", "label" => true, "i18n_template" => "ecstat1" },
{ "key" => "earnings", "label" => true, "i18n_template" => "earnings" },
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "ecstat1",
"i18n_template" => "ecstat1",
},
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "earnings",
"i18n_template" => "earnings",
},
],
}
end

2
app/models/form/lettings/pages/outstanding_amount.rb

@ -2,7 +2,7 @@ class Form::Lettings::Pages::OutstandingAmount < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "outstanding_amount"
@depends_on = [{ "hb" => 1, "hbrentshortfall" => 1 }, { "hb" => 6, "hbrentshortfall" => 1 }]
@depends_on = [{ "receives_housing_related_benefits?" => true, "has_housing_benefit_rent_shortfall?" => true }]
end
def questions

6
app/models/form/lettings/pages/rent_4_weekly.rb

@ -4,10 +4,8 @@ class Form::Lettings::Pages::Rent4Weekly < ::Form::Page
@id = "rent_4_weekly"
@header = "Household rent and charges"
@depends_on = [
{ "household_charge" => 0, "period" => 3, "is_carehome" => 0 },
{ "household_charge" => nil, "period" => 3, "is_carehome" => 0 },
{ "household_charge" => 0, "period" => 3, "is_carehome" => nil },
{ "household_charge" => nil, "period" => 3, "is_carehome" => nil },
{ "household_charge" => 0, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false },
{ "household_charge" => nil, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false },
]
end

6
app/models/form/lettings/pages/rent_bi_weekly.rb

@ -4,10 +4,8 @@ class Form::Lettings::Pages::RentBiWeekly < ::Form::Page
@id = "rent_bi_weekly"
@header = "Household rent and charges"
@depends_on = [
{ "household_charge" => 0, "period" => 2, "is_carehome" => 0 },
{ "household_charge" => nil, "period" => 2, "is_carehome" => 0 },
{ "household_charge" => 0, "period" => 2, "is_carehome" => nil },
{ "household_charge" => nil, "period" => 2, "is_carehome" => nil },
{ "household_charge" => nil, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false },
{ "household_charge" => 0, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false },
]
end

6
app/models/form/lettings/pages/rent_monthly.rb

@ -4,10 +4,8 @@ class Form::Lettings::Pages::RentMonthly < ::Form::Page
@id = "rent_monthly"
@header = "Household rent and charges"
@depends_on = [
{ "household_charge" => 0, "period" => 4, "is_carehome" => 0 },
{ "household_charge" => nil, "period" => 4, "is_carehome" => 0 },
{ "household_charge" => 0, "period" => 4, "is_carehome" => nil },
{ "household_charge" => nil, "period" => 4, "is_carehome" => nil },
{ "household_charge" => nil, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false },
{ "household_charge" => 0, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false },
]
end

26
app/models/form/lettings/pages/rent_weekly.rb

@ -4,30 +4,8 @@ class Form::Lettings::Pages::RentWeekly < ::Form::Page
@id = "rent_weekly"
@header = "Household rent and charges"
@depends_on = [
{ "period" => 1, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 1, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 5, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 5, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 6, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 6, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 7, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 7, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 8, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 8, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 9, "household_charge" => 0, "is_carehome" => 0 },
{ "period" => 9, "household_charge" => nil, "is_carehome" => 0 },
{ "period" => 1, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 1, "household_charge" => nil, "is_carehome" => nil },
{ "period" => 5, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 5, "household_charge" => nil, "is_carehome" => nil },
{ "period" => 6, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 6, "household_charge" => nil, "is_carehome" => nil },
{ "period" => 7, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 7, "household_charge" => nil, "is_carehome" => nil },
{ "period" => 8, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 8, "household_charge" => nil, "is_carehome" => nil },
{ "period" => 9, "household_charge" => 0, "is_carehome" => nil },
{ "period" => 9, "household_charge" => nil, "is_carehome" => nil },
{ "rent_and_charges_paid_weekly?" => true, "household_charge" => 0, "is_carehome?" => false },
{ "rent_and_charges_paid_weekly?" => true, "household_charge" => nil, "is_carehome?" => false },
]
end

5
app/models/form/lettings/pages/uprn.rb

@ -6,14 +6,13 @@ class Form::Lettings::Pages::Uprn < ::Form::Page
def questions
@questions ||= [
Form::Lettings::Questions::UprnKnown.new(nil, nil, self),
Form::Lettings::Questions::Uprn.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
return false if log.is_supported_housing?
log.uprn_known == 1
!log.is_supported_housing?
end
def skip_text

16
app/models/form/lettings/pages/uprn_known.rb

@ -1,16 +0,0 @@
class Form::Lettings::Pages::UprnKnown < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_known"
end
def questions
@questions ||= [
Form::Lettings::Questions::UprnKnown.new(nil, nil, self),
]
end
def routed_to?(log, _current_user = nil)
!log.is_supported_housing?
end
end

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

@ -27,7 +27,7 @@ class Form::Lettings::Questions::LocationId < ::Form::Question
def displayed_answer_options(lettings_log, _user = nil)
return {} unless lettings_log.scheme
scheme_location_ids = lettings_log.scheme.locations.pluck(:id)
scheme_location_ids = lettings_log.scheme.locations.confirmed.pluck(:id)
answer_options.select { |k, _v| scheme_location_ids.include?(k.to_i) }
end

9
app/models/form/lettings/questions/period.rb

@ -15,11 +15,12 @@ class Form::Lettings::Questions::Period < ::Form::Question
"2" => { "value" => "Every 2 weeks" },
"3" => { "value" => "Every 4 weeks" },
"4" => { "value" => "Every calendar month" },
"5" => { "value" => "Weekly for 50 weeks" },
"6" => { "value" => "Weekly for 49 weeks" },
"7" => { "value" => "Weekly for 48 weeks" },
"8" => { "value" => "Weekly for 47 weeks" },
"9" => { "value" => "Weekly for 46 weeks" },
"8" => { "value" => "Weekly for 47 weeks" },
"7" => { "value" => "Weekly for 48 weeks" },
"6" => { "value" => "Weekly for 49 weeks" },
"5" => { "value" => "Weekly for 50 weeks" },
"1" => { "value" => "Weekly for 52 weeks" },
"10" => { "value" => "Weekly for 53 weeks" },
}.freeze
end

9
app/models/form/lettings/questions/scheme_id.rb

@ -9,6 +9,11 @@ class Form::Lettings::Questions::SchemeId < ::Form::Question
@guidance_position = GuidancePosition::BOTTOM
@guidance_partial = "scheme_selection"
@question_number = 9
@inferred_answers = {
"location.name": {
"scheme_has_multiple_locations?": false,
},
}
end
def answer_options
@ -41,6 +46,10 @@ class Form::Lettings::Questions::SchemeId < ::Form::Question
!supported_housing_selected?(lettings_log)
end
def get_extra_check_answer_value(lettings_log)
lettings_log.form.get_question("postcode_full", nil).label_from_value(lettings_log.postcode_full) unless lettings_log.scheme_has_multiple_locations?
end
private
def supported_housing_selected?(lettings_log)

1
app/models/form/lettings/questions/tshortfall.rb

@ -20,6 +20,7 @@ class Form::Lettings::Questions::Tshortfall < ::Form::Question
{ "label" => " every week for 47 weeks", "depends_on" => { "period" => 8 } },
{ "label" => " every week for 46 weeks", "depends_on" => { "period" => 9 } },
{ "label" => " every week for 52 weeks", "depends_on" => { "period" => 1 } },
{ "label" => " every week for 53 weeks", "depends_on" => { "period" => 10 } },
]
@question_number = 100
end

13
app/models/form/lettings/questions/uprn.rb

@ -5,9 +5,14 @@ class Form::Lettings::Questions::Uprn < ::Form::Question
@check_answer_label = "UPRN"
@header = "What is the property's UPRN"
@type = "text"
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
@width = 10
@question_number = 11
@inferred_check_answers_value = [
{
"condition" => { "uprn_known" => 0 },
"value" => "Not known",
},
]
end
def unanswered_error_message
@ -15,6 +20,8 @@ class Form::Lettings::Questions::Uprn < ::Form::Question
end
def get_extra_check_answer_value(log)
return unless log.uprn_known == 1
value = [
log.address_line1,
log.address_line2,
@ -28,8 +35,4 @@ class Form::Lettings::Questions::Uprn < ::Form::Question
"\n\n#{value.join("\n")}"
end
def hidden_in_check_answers?(log, _current_user = nil)
log.uprn_known != 1
end
end

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

@ -8,6 +8,8 @@ class Form::Lettings::Questions::UprnKnown < ::Form::Question
@answer_options = ANSWER_OPTIONS
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.<br><br>
You can continue without the UPRN, but it means we will need you to enter the address of the property."
@conditional_for = { "uprn" => [1] }
@hidden_in_check_answers = true
end
ANSWER_OPTIONS = {

1
app/models/form/lettings/subsections/property_information.rb

@ -34,7 +34,6 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions
if form.start_date.year >= 2023
[
Form::Lettings::Pages::UprnKnown.new(nil, nil, self),
Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),
Form::Lettings::Pages::Address.new(nil, nil, self),

24
app/models/form/question.rb

@ -226,24 +226,6 @@ class Form::Question
label
end
def answer_option_synonyms(resource)
return unless resource.respond_to?(:synonyms)
resource.synonyms
end
def answer_option_append(resource)
return unless resource.respond_to?(:appended_text)
resource.appended_text
end
def answer_option_hint(resource)
return unless resource.respond_to?(:hint)
resource.hint
end
def answer_selected?(log, answer)
return false unless type == "select"
@ -317,7 +299,11 @@ private
end
def enabled_inferred_answers(inferred_answers, log)
inferred_answers.filter { |_key, value| value.all? { |condition_key, condition_value| log[condition_key] == condition_value } }
inferred_answers.filter do |_attribute, condition|
condition.all? do |condition_key, condition_value|
log.public_send(condition_key) == condition_value
end
end
end
def inferred_answer_value(log)

21
app/models/form/sales/pages/buyer_live_in_value_check.rb

@ -0,0 +1,21 @@
class Form::Sales::Pages::BuyerLiveInValueCheck < Form::Sales::Pages::Person
def initialize(id, hsh, subsection, person_index:)
super
@depends_on = [
{
"buyer#{person_index}_livein_wrong_for_ownership_type?" => true,
},
]
@title_text = {
"translation" => "soft_validations.buyer#{person_index}_livein_wrong_for_ownership_type.title_text",
"arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
}
@informative_text = {}
end
def questions
@questions ||= [
Form::Sales::Questions::BuyerLiveInValueCheck.new(nil, nil, self, person_index: @person_index),
]
end
end

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

@ -4,11 +4,23 @@ class Form::Sales::Pages::DiscountedSaleValueCheck < ::Form::Page
@depends_on = depends_on
@title_text = {
"translation" => "soft_validations.discounted_sale_value.title_text",
"arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }],
"arguments" => [
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "value_with_discount",
"i18n_template" => "value_with_discount",
},
],
}
@informative_text = {
"translation" => "soft_validations.discounted_sale_value.informative_text",
"arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }],
"arguments" => [
{
"key" => "field_formatted_as_currency",
"arguments_for_key" => "mortgage_deposit_and_grant_total",
"i18n_template" => "mortgage_deposit_and_grant_total",
},
],
}
@person_index = person_index
@depends_on = [

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

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

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

@ -11,8 +11,8 @@ class Form::Sales::Pages::SharedOwnershipDepositValueCheck < ::Form::Page
"translation" => "soft_validations.shared_ownership_deposit.title_text",
"arguments" => [
{
"key" => "expected_shared_ownership_deposit_value",
"label" => false,
"key" => "field_formatted_as_currency",
"arguments_for_key" => "expected_shared_ownership_deposit_value",
"i18n_template" => "expected_shared_ownership_deposit_value",
},
],

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

@ -6,6 +6,7 @@ class Form::Sales::Pages::Uprn < ::Form::Page
def questions
@questions ||= [
Form::Sales::Questions::UprnKnown.new(nil, nil, self),
Form::Sales::Questions::Uprn.new(nil, nil, self),
]
end

12
app/models/form/sales/pages/uprn_known.rb

@ -1,12 +0,0 @@
class Form::Sales::Pages::UprnKnown < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "uprn_known"
end
def questions
@questions ||= [
Form::Sales::Questions::UprnKnown.new(nil, nil, self),
]
end
end

24
app/models/form/sales/questions/buyer_live_in_value_check.rb

@ -0,0 +1,24 @@
class Form::Sales::Questions::BuyerLiveInValueCheck < ::Form::Question
def initialize(id, hsh, page, person_index:)
super(id, hsh, page)
@id = "buyer_livein_value_check"
@check_answer_label = "Buyer live in confirmation"
@type = "interruption_screen"
@answer_options = {
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
}
@hidden_in_check_answers = {
"depends_on" => [
{
"buyer_livein_value_check" => 0,
},
{
"buyer_livein_value_check" => 1,
},
],
}
@check_answers_card_number = person_index
@header = "Are you sure this is correct?"
end
end

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

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

13
app/models/form/sales/questions/uprn.rb

@ -5,9 +5,14 @@ class Form::Sales::Questions::Uprn < ::Form::Question
@check_answer_label = "UPRN"
@header = "What is the property's UPRN"
@type = "text"
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
@width = 10
@question_number = 14
@inferred_check_answers_value = [
{
"condition" => { "uprn_known" => 0 },
"value" => "Not known",
},
]
end
def unanswered_error_message
@ -15,6 +20,8 @@ class Form::Sales::Questions::Uprn < ::Form::Question
end
def get_extra_check_answer_value(log)
return unless log.uprn_known == 1
value = [
log.address_line1,
log.address_line2,
@ -28,8 +35,4 @@ class Form::Sales::Questions::Uprn < ::Form::Question
"\n\n#{value.join("\n")}"
end
def hidden_in_check_answers?(log, _current_user = nil)
log.uprn_known != 1
end
end

8
app/models/form/sales/questions/uprn_known.rb

@ -8,6 +8,14 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question
@answer_options = ANSWER_OPTIONS
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.<br><br>
You can continue without the UPRN, but it means we will need you to enter the address of the property."
@conditional_for = { "uprn" => [1] }
@inferred_check_answers_value = [
{
"condition" => { "uprn_known" => 0 },
"value" => "Not known",
},
]
@hidden_in_check_answers = true
end
ANSWER_OPTIONS = {

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

@ -11,6 +11,7 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::LivingBeforePurchase.new("living_before_purchase_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::AboutPriceRtb.new(nil, nil, self),
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_price_value_check", nil, self),
Form::Sales::Pages::PercentageDiscountValueCheck.new("percentage_discount_value_check", nil, self),
Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self),
Form::Sales::Pages::GrantValueCheck.new(nil, nil, self),
Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2),

2
app/models/form/sales/subsections/household_characteristics.rb

@ -26,6 +26,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::RetirementValueCheck.new("working_situation_1_retirement_value_check", nil, self, person_index: 1),
Form::Sales::Pages::Buyer1IncomeValueCheck.new("working_situation_buyer_1_income_value_check", nil, self),
Form::Sales::Pages::Buyer1LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_1_live_in_property_value_check", nil, self, person_index: 1),
Form::Sales::Pages::Buyer2RelationshipToBuyer1.new(nil, nil, self),
Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_relationship_student_not_child_value_check", nil, self, person_index: 2),
Form::Sales::Pages::Age2.new(nil, nil, self),
@ -40,6 +41,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::Buyer2IncomeValueCheck.new("working_situation_buyer_2_income_value_check", nil, self),
Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_working_situation_student_not_child_value_check", nil, self, person_index: 2),
Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_2_live_in_property_value_check", nil, self, person_index: 2),
Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property", nil, self, joint_purchase: false),
Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 2),

2
app/models/form/sales/subsections/property_information.rb

@ -13,6 +13,7 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_bedrooms_value_check", nil, self),
Form::Sales::Pages::PropertyUnitType.new(nil, nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_property_type_value_check", nil, self),
Form::Sales::Pages::PercentageDiscountValueCheck.new("percentage_discount_proptype_value_check", nil, self),
Form::Sales::Pages::PropertyBuildingType.new(nil, nil, self),
postcode_and_la_questions,
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
@ -23,7 +24,6 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions
if form.start_date.year >= 2023
[
Form::Sales::Pages::UprnKnown.new(nil, nil, self),
Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::Address.new(nil, nil, self),

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

@ -19,6 +19,8 @@ class Form::Sales::Subsections::Setup < ::Form::Subsection
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_type_value_check", nil, self),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_1_live_in_property_type_value_check", nil, self, person_index: 1),
Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_2_live_in_property_type_value_check", nil, self, person_index: 2),
Form::Sales::Pages::BuyerCompany.new(nil, nil, self),
Form::Sales::Pages::BuyerLive.new(nil, nil, self),
Form::Sales::Pages::JointPurchase.new(nil, nil, self),

26
app/models/lettings_log.rb

@ -58,7 +58,7 @@ class LettingsLog < Log
OPTIONAL_FIELDS = %w[rent_value_check first_time_property_let_as_social_housing tenancycode propcode chcharge].freeze
RENT_TYPE_MAPPING_LABELS = { 1 => "Social Rent", 2 => "Affordable Rent", 3 => "Intermediate Rent" }.freeze
HAS_BENEFITS_OPTIONS = [1, 6, 8, 7].freeze
NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52 }.freeze
NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52, 10 => 53 }.freeze
SUFFIX_FROM_PERIOD = { 2 => "every 2 weeks", 3 => "every 4 weeks", 4 => "every month" }.freeze
RETIREMENT_AGES = { "M" => 67, "F" => 60, "X" => 67 }.freeze
@ -203,7 +203,7 @@ class LettingsLog < Log
needstype == 2
end
def has_hbrentshortfall?
def has_housing_benefit_rent_shortfall?
# 1: Yes
hbrentshortfall == 1
end
@ -506,7 +506,27 @@ class LettingsLog < Log
end
def care_home_charge_expected_not_provided?
is_carehome == 1 && chcharge.blank?
is_carehome? && chcharge.blank?
end
def rent_and_charges_paid_weekly?
[1, 5, 6, 7, 8, 9, 10].include? period
end
def rent_and_charges_paid_every_4_weeks?
period == 3
end
def rent_and_charges_paid_every_2_weeks?
period == 2
end
def rent_and_charges_paid_monthly?
period == 4
end
def is_carehome?
is_carehome == 1
end
private

1
app/models/location.rb

@ -24,6 +24,7 @@ class Location < ApplicationRecord
scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) }
scope :active, -> { where(confirmed: true).and(started) }
scope :confirmed, -> { where(confirmed: true) }
scope :unconfirmed, -> { where.not(confirmed: true) }
LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h

17
app/models/log.rb

@ -1,4 +1,6 @@
class Log < ApplicationRecord
include CollectionTimeHelper
self.abstract_class = true
belongs_to :owning_organisation, class_name: "Organisation", optional: true
@ -50,6 +52,7 @@ class Log < ApplicationRecord
presenter = UprnDataPresenter.new(service.result)
self.uprn_known = 1
self.uprn_confirmed = nil
self.address_line1 = presenter.address_line1
self.address_line2 = presenter.address_line2
@ -87,6 +90,8 @@ class Log < ApplicationRecord
end
def collection_period_open?
return false if older_than_previous_collection_year?
form.end_date > Time.zone.today
end
@ -126,8 +131,20 @@ class Log < ApplicationRecord
end
end
def field_formatted_as_currency(field_name)
field_value = public_send(field_name)
format_as_currency(field_value)
end
private
# Handle logs that are older than previous collection start date
def older_than_previous_collection_year?
return false unless startdate
startdate < previous_collection_start_date
end
def plural_gender_for_person(person_num)
gender = public_send("sex#{person_num}".to_sym)
return unless gender

20
app/models/sales_log.rb

@ -43,7 +43,7 @@ class SalesLog < Log
}
scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) }
OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check].freeze
OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check buyer_livein_value_check].freeze
RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze
def lettings?
@ -216,7 +216,7 @@ class SalesLog < Log
def expected_shared_ownership_deposit_value
return unless value && equity
format_as_currency(value * equity / 100)
value * equity / 100
end
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
@ -323,11 +323,6 @@ class SalesLog < Log
format_as_currency(soft_min)
end
def field_formatted_as_currency(field_name)
field_value = public_send(field_name)
format_as_currency(field_value)
end
def should_process_uprn_change?
uprn_changed? && saledate && saledate.year >= 2023
end
@ -350,4 +345,15 @@ class SalesLog < Log
def beds_for_la_sale_range
beds.nil? ? nil : [beds, LaSaleRange::MAX_BEDS].min
end
def ownership_scheme
case ownershipsch
when 1
"shared ownership"
when 2
"discounted ownership"
when 3
"outright sale"
end
end
end

12
app/models/scheme.rb

@ -161,18 +161,6 @@ class Scheme < ApplicationRecord
]
end
def synonyms
locations.map(&:postcode).join(",")
end
def appended_text
"#{locations.count { |location| location.startdate.blank? || location.startdate <= Time.zone.today }} locations"
end
def hint
[primary_client_group, secondary_client_group].filter(&:present?).join(", ")
end
def care_acts_options_with_hints
hints = { "Yes – part registered as a care home": "A proportion of units are registered as being a care home." }

8
app/models/validations/financial_validations.rb

@ -4,7 +4,7 @@ module Validations::FinancialValidations
# Validations methods need to be called 'validate_<page_name>' to run on model save
# or 'validate_' to run on submit as well
def validate_outstanding_rent_amount(record)
if !record.has_hbrentshortfall? && record.tshortfall.present?
if !record.has_housing_benefit_rent_shortfall? && record.tshortfall.present?
record.errors.add :tshortfall, :no_outstanding_charges, message: I18n.t("validations.financial.tshortfall.outstanding_amount_not_required")
end
end
@ -69,7 +69,7 @@ module Validations::FinancialValidations
end
def validate_tshortfall(record)
if record.has_hbrentshortfall? && no_known_benefits?(record)
if record.has_housing_benefit_rent_shortfall? && no_known_benefits?(record)
record.errors.add :tshortfall, I18n.t("validations.financial.hbrentshortfall.outstanding_no_benefits")
end
end
@ -99,7 +99,7 @@ module Validations::FinancialValidations
end
if record.tcharge.present? && weekly_value_in_range(record, "tcharge", 0, 9.99)
record.errors.add :tcharge, I18n.t("validations.financial.tcharge.under_10")
record.errors.add :tcharge, :under_10, message: I18n.t("validations.financial.tcharge.under_10")
end
answered_questions = [record.tcharge, record.chcharge].concat(record.household_charge && record.household_charge == 1 ? [record.household_charge] : [])
@ -224,7 +224,7 @@ private
end
if record.weekly_value(record["brent"]) > rent_range.hard_max
record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max")
record.errors.add :brent, :over_hard_max, message: I18n.t("validations.financial.brent.above_hard_max")
record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max")
record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max")
record.errors.add :postcode_known, I18n.t("validations.financial.brent.postcode_known.above_hard_max")

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

@ -48,7 +48,7 @@ module Validations::Sales::SaleInformationValidations
end
def validate_discounted_ownership_value(record)
return unless record.saledate && collection_start_year(record.saledate) >= 2024
return unless record.saledate && collection_start_year_for_date(record.saledate) >= 2024
return unless record.value && record.deposit && record.ownershipsch
return unless record.mortgage || record.mortgageused == 2
return unless record.discount || record.grant || record.type == 29

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

@ -123,6 +123,30 @@ module Validations::Sales::SoftValidations
mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale?
end
def buyer1_livein_wrong_for_ownership_type?
return unless ownershipsch && buy1livein
(discounted_ownership_sale? || shared_ownership_scheme?) && buy1livein == 2
end
def buyer2_livein_wrong_for_ownership_type?
return unless ownershipsch && buy2livein
return unless joint_purchase?
(discounted_ownership_sale? || shared_ownership_scheme?) && buy2livein == 2
end
def percentage_discount_invalid?
return unless discount && proptype
case proptype
when 1, 2
discount > 50
when 3, 4, 9
discount > 35
end
end
private
def sale_range

8
app/models/validations/setup_validations.rb

@ -20,6 +20,14 @@ module Validations::SetupValidations
location_during_startdate_validation(record, :location_id)
end
def validate_scheme_has_confirmed_locations_validation(record)
return unless record.scheme
unless record.scheme.locations.confirmed.any?
record.errors.add :scheme_id, I18n.t("validations.scheme.no_completed_locations")
end
end
def validate_scheme(record)
location_during_startdate_validation(record, :scheme_id)
scheme_during_startdate_validation(record, :scheme_id)

1
app/models/validations/shared_validations.rb

@ -7,6 +7,7 @@ module Validations::SharedValidations
main_field_label = main_label || main_field.to_s.humanize(capitalize: false)
other_field_label = other_label || other_field.to_s.humanize(capitalize: false)
if record[main_field] == value_other && record[other_field].blank?
record.errors.add main_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
end

68
app/services/bulk_upload/lettings/year2022/row_parser.rb

@ -14,37 +14,37 @@ class BulkUpload::Lettings::Year2022::RowParser
field_9: "What is the tenancy type?",
field_10: "If 'Other', what is the tenancy type?",
field_11: "What is the length of the fixed-term tenancy to the nearest year?",
field_12: "Age of Person 1",
field_13: "Age of Person 2",
field_14: "Age of Person 3",
field_15: "Age of Person 4",
field_16: "Age of Person 5",
field_17: "Age of Person 6",
field_18: "Age of Person 7",
field_19: "Age of Person 8",
field_20: "Gender identity of Person 1",
field_21: "Gender identity of Person 2",
field_22: "Gender identity of Person 3",
field_23: "Gender identity of Person 4",
field_24: "Gender identity of Person 5",
field_25: "Gender identity of Person 6",
field_26: "Gender identity of Person 7",
field_27: "Gender identity of Person 8",
field_28: "Relationship to Person 1 for Person 2",
field_29: "Relationship to Person 1 for Person 3",
field_30: "Relationship to Person 1 for Person 4",
field_31: "Relationship to Person 1 for Person 5",
field_32: "Relationship to Person 1 for Person 6",
field_33: "Relationship to Person 1 for Person 7",
field_34: "Relationship to Person 1 for Person 8",
field_35: "Working situation of Person 1",
field_36: "Working situation of Person 2",
field_37: "Working situation of Person 3",
field_38: "Working situation of Person 4",
field_39: "Working situation of Person 5",
field_40: "Working situation of Person 6",
field_41: "Working situation of Person 7",
field_42: "Working situation of Person 8",
field_12: "Age of person 1",
field_13: "Age of person 2",
field_14: "Age of person 3",
field_15: "Age of person 4",
field_16: "Age of person 5",
field_17: "Age of person 6",
field_18: "Age of person 7",
field_19: "Age of person 8",
field_20: "Gender identity of person 1",
field_21: "Gender identity of person 2",
field_22: "Gender identity of person 3",
field_23: "Gender identity of person 4",
field_24: "Gender identity of person 5",
field_25: "Gender identity of person 6",
field_26: "Gender identity of person 7",
field_27: "Gender identity of person 8",
field_28: "Relationship to person 1 for person 2",
field_29: "Relationship to person 1 for person 3",
field_30: "Relationship to person 1 for person 4",
field_31: "Relationship to person 1 for person 5",
field_32: "Relationship to person 1 for person 6",
field_33: "Relationship to person 1 for person 7",
field_34: "Relationship to person 1 for person 8",
field_35: "Working situation of person 1",
field_36: "Working situation of person 2",
field_37: "Working situation of person 3",
field_38: "Working situation of person 4",
field_39: "Working situation of person 5",
field_40: "Working situation of person 6",
field_41: "Working situation of person 7",
field_42: "Working situation of person 8",
field_43: "What is the lead tenant's ethnic group?",
field_44: "What is the lead tenant's nationality?",
field_45: "Does anybody in the household have links to the UK armed forces?",
@ -340,10 +340,10 @@ class BulkUpload::Lettings::Year2022::RowParser
return true if blank_row?
super
log.valid?
super
log.errors.each do |error|
fields = field_mapping_for_errors[error.attribute] || []
@ -650,7 +650,7 @@ private
end
def questions
log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
@questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
end
def validate_nulls

9
app/services/bulk_upload/lettings/year2023/row_parser.rb

@ -292,6 +292,7 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true
validates :field_6, presence: { message: I18n.t("validations.not_answered", question: "property renewal") }
validates :field_7, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }
validates :field_8, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }
validates :field_9, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (year)") }
@ -342,10 +343,10 @@ class BulkUpload::Lettings::Year2023::RowParser
return true if blank_row?
super
log.valid?
super
log.errors.each do |error|
fields = field_mapping_for_errors[error.attribute] || []
@ -826,7 +827,7 @@ private
end
def questions
log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
@questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
end
def attributes_for_log
@ -1050,8 +1051,6 @@ private
1
when 2
0
when nil
rsnvac == 14 ? 1 : 0
else
field_6
end

46
app/services/bulk_upload/sales/year2022/row_parser.rb

@ -9,29 +9,29 @@ class BulkUpload::Sales::Year2022::RowParser
field_4: "What is the year of the sale completion date? - YY",
field_5: "This question has been removed",
field_6: "Was the buyer interviewed for any of the answers you will provide on this log?",
field_7: "Age of Buyer 1",
field_8: "Age of Person 2",
field_9: "Age of Person 3",
field_10: "Age of Person 4",
field_11: "Age of Person 5",
field_12: "Age of Person 6",
field_13: "Gender identity of Buyer 1",
field_14: "Gender identity of Person 2",
field_15: "Gender identity of Person 3",
field_16: "Gender identity of Person 4",
field_17: "Gender identity of Person 5",
field_18: "Gender identity of Person 6",
field_19: "Relationship to Buyer 1 for Person 2",
field_20: "Relationship to Buyer 1 for Person 3",
field_21: "Relationship to Buyer 1 for Person 4",
field_22: "Relationship to Buyer 1 for Person 5",
field_23: "Relationship to Buyer 1 for Person 6",
field_24: "Working situation of Buyer 1",
field_25: "Working situation of Person 2",
field_26: "Working situation of Person 3",
field_27: "Working situation of Person 4",
field_28: "Working situation of Person 5",
field_29: "Working situation of Person 6",
field_7: "Age of buyer 1",
field_8: "Age of person 2",
field_9: "Age of person 3",
field_10: "Age of person 4",
field_11: "Age of person 5",
field_12: "Age of person 6",
field_13: "Gender identity of buyer 1",
field_14: "Gender identity of person 2",
field_15: "Gender identity of person 3",
field_16: "Gender identity of person 4",
field_17: "Gender identity of person 5",
field_18: "Gender identity of person 6",
field_19: "Relationship to buyer 1 for person 2",
field_20: "Relationship to buyer 1 for person 3",
field_21: "Relationship to buyer 1 for person 4",
field_22: "Relationship to buyer 1 for person 5",
field_23: "Relationship to buyer 1 for person 6",
field_24: "Working situation of buyer 1",
field_25: "Working situation of person 2",
field_26: "Working situation of person 3",
field_27: "Working situation of person 4",
field_28: "Working situation of person 5",
field_29: "Working situation of person 6",
field_30: "What is buyer 1's ethnic group?",
field_31: "What is buyer 1's nationality?",
field_32: "What is buyer 1's gross annual income?",

9
app/services/exports/lettings_log_export_service.rb

@ -12,19 +12,20 @@ module Exports
start_time = Time.zone.now
logs_by_collection = retrieve_lettings_logs(start_time, full_update).group_by(&:collection_start_year)
daily_run_number = get_daily_run_number
archives_for_manifest = []
archives_for_manifest = {}
base_number = LogsExport.where(empty_export: false).maximum(:base_number) || 1
available_collection_years.each do |collection|
lettings_logs = logs_by_collection.fetch(collection, LettingsLog.none)
export = build_export_run(collection, start_time, base_number, full_update)
archives = write_export_archive(export, lettings_logs)
archives_for_manifest << archives if archives.any?
archives_for_manifest.merge!(archives)
export.empty_export = archives.empty?
export.save!
end
write_master_manifest(daily_run_number, archives_for_manifest.flatten)
write_master_manifest(daily_run_number, archives_for_manifest)
end
private
@ -129,7 +130,7 @@ module Exports
headers = ["zip-name", "date-time zipped folder generated", "zip-file-uri"]
csv_string = CSV.generate do |csv|
csv << headers
archive_datetimes.each do |archive, datetime|
archive_datetimes.each do |(archive, datetime)|
csv << [archive, datetime, "#{archive}.zip"]
end
end

10
config/initializers/feature_toggle.rb → app/services/feature_toggle.rb

@ -36,7 +36,11 @@ class FeatureToggle
true
end
def self.bulk_upload_logs?
def self.bulk_upload_lettings_logs?
!Rails.env.production?
end
def self.bulk_upload_sales_logs?
!Rails.env.production?
end
@ -53,4 +57,8 @@ class FeatureToggle
def self.collection_2023_2024_year_enabled?
true
end
def self.merge_organisations_enabled?
!Rails.env.production?
end
end

2
app/services/imports/lettings_logs_import_service.rb

@ -302,6 +302,8 @@ module Imports
%i[supcharg outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
%i[scharge outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
%i[location_id not_active] => %w[location_id scheme_id],
%i[tcharge under_10] => %w[brent scharge pscharge supcharg tcharge],
%i[brent over_hard_max] => %w[brent scharge pscharge supcharg tcharge],
}
(2..8).each do |person|

6
app/services/imports/sales_logs_import_service.rb

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

6
app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb

@ -10,14 +10,14 @@
<span class="govuk-caption-l">Upload lettings logs in bulk (<%= @form.year_combo %>)</span>
<h1 class="govuk-heading-l">We’re checking the file</h1>
<h2 class="govuk-heading-m">Once this is done, we’ll email you the outcome.</h2>
<h2 class="govuk-heading-s">Once this is done, we’ll email you the outcome.</h2>
<p class="govuk-body">
We’re checking for any missing data, issues or errors. Depending on the file size, this could take a few minutes.
We’re checking for any missing data, issues or errors. Depending on file size, this could take a few minutes.
</p>
<p class="govuk-body">
If there are errors we will email you a link to view all the errors.
If there are errors, we will email you to let you know how to fix them.
</p>
<p class="govuk-body">

1
app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb

@ -19,6 +19,7 @@
<h2 class="govuk-heading-s">Create your file</h2>
<ul class="govuk-list govuk-list--bullet">
<li>Fill in the template with CORE data from your housing management system according to the <%= govuk_link_to "Lettings #{@form.year_combo} Bulk Upload Specification", @form.specification_path %></li>
<li><strong>Username field:</strong> To assign a log to someone else, enter the email address they use to log into CORE</li>
<li>If you have to manually enter large volumes of data into the bulk upload template, we recommend creating logs directly in the service instead. <%= govuk_link_to "Find out more about exporting your data", bulk_upload_lettings_log_path(id: "guidance", form: { year: @form.year }) %></li>
</ul>

2
app/views/bulk_upload_lettings_results/show.html.erb

@ -13,7 +13,7 @@
<div class="govuk-grid-row">
<div class="govuk-grid-column-full">
<% @bulk_upload.bulk_upload_errors.group_by(&:row).each do |_row, errors_for_row| %>
<% @bulk_upload.bulk_upload_errors.order_by_cell.group_by(&:row).each do |_row, errors_for_row| %>
<%= render BulkUploadErrorRowComponent.new(bulk_upload_errors: errors_for_row) %>
<% end %>
</div>

6
app/views/bulk_upload_sales_logs/forms/checking_file.html.erb

@ -10,14 +10,14 @@
<span class="govuk-caption-l">Upload sales logs in bulk (<%= @form.year_combo %>)</span>
<h1 class="govuk-heading-l">We’re checking the file</h1>
<h2 class="govuk-heading-m">Once this is done, we’ll email you the outcome.</h2>
<h2 class="govuk-heading-s">Once this is done, we’ll email you the outcome.</h2>
<p class="govuk-body">
We’re checking for any missing data, issues or errors. Depending on the file size, this could take a few minutes.
We’re checking for any missing data, issues or errors. Depending on file size, this could take a few minutes.
</p>
<p class="govuk-body">
If there are errors we will email you a link to view all the errors.
If there are errors, we will email you to let you know how to fix them.
</p>
<p class="govuk-body">

1
app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb

@ -19,6 +19,7 @@
<h2 class="govuk-heading-s">Create your file</h2>
<ul class="govuk-list govuk-list--bullet">
<li>Fill in the template with CORE data from your housing management system according to the <%= govuk_link_to "Sales #{@form.year_combo} Bulk Upload Specification", @form.specification_path %></li>
<li><strong>Username field:</strong> To assign a log to someone else, enter the email address they use to log into CORE</li>
<li>If you have to manually enter large volumes of data into the bulk upload template, we recommend creating logs directly in the service instead. <%= govuk_link_to "Find out more about exporting your data", bulk_upload_sales_log_path(id: "guidance", form: { year: @form.year }) %></li>
</ul>

16
app/views/form/_select_question.html.erb

@ -7,14 +7,14 @@
"data-controller": "accessible-autocomplete",
caption: caption(caption_text, page_header, conditional),
hint: { text: question.hint_text&.html_safe }) do %>
<% answers.each do |answer| %>
<option value="<%= answer.id %>"
data-synonyms="<%= question.answer_option_synonyms(answer.resource) %>"
data-append="<%= question.answer_option_append(answer.resource) %>"
data-hint="<%= question.answer_option_hint(answer.resource) %>"
<%= question.answer_selected?(@log, answer) ? "selected" : "" %>
<%= answer.id == "" ? "disabled" : "" %>><%= answer.name || answer.resource %></option>
<% end %>
<% answers.each do |answer| %>
<option value="<%= answer.id %>"
data-synonyms="<%= answer_option_synonyms(answer.resource) %>"
data-append="<%= answer_option_append(answer.resource) %>"
data-hint="<%= answer_option_hint(answer.resource) %>"
<%= question.answer_selected?(@log, answer) ? "selected" : "" %>
<%= answer.id == "" ? "disabled" : "" %>><%= answer.name || answer.resource %></option>
<% end %>
<% end %>
<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %>

2
app/views/form/page.html.erb

@ -1,7 +1,7 @@
<% content_for :title, @page.header.presence || @page.questions.first.header.html_safe %>
<% content_for :before_content do %>
<%= govuk_back_link(href: "javascript:history.back()") %>
<%= govuk_back_link(href: send(@log.form.previous_page_redirect_path(@page, @log, current_user, params[:referrer]), @log)) %>
<% end %>
<div data-controller="govukfrontend"></div>

1
app/views/locations/availability.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_mobility_standards_path(@scheme, @location, route: params[:route]),
) %>
<% end %>

1
app/views/locations/check_answers.html.erb

@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: case params[:route]
when "locations"
scheme_locations_path(@scheme)

1
app/views/locations/index.html.erb

@ -4,7 +4,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: "/schemes/#{@scheme.id}",
) %>
<% end %>

1
app/views/locations/local_authority.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: case params[:referrer]
when "check_local_authority"
scheme_location_check_answers_path(@scheme, @location, route: params[:route])

1
app/views/locations/mobility_standards.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_type_of_unit_path(@scheme, @location, route: params[:route]),
) %>
<% end %>

1
app/views/locations/name.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: case params[:referrer]
when "check_answers"
scheme_location_check_answers_path(@scheme, @location, route: params[:route])

1
app/views/locations/postcode.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: if params[:referrer] == "check_answers"
scheme_location_check_answers_path(@scheme, @location, route: params[:route])
else

1
app/views/locations/show.html.erb

@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: scheme_locations_path(@scheme),
) %>
<% end %>

1
app/views/locations/toggle_active.html.erb

@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: scheme_location_path(@location.scheme, @location),
) %>
<% end %>

1
app/views/locations/type_of_unit.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_units_path(@scheme, @location, route: params[:route]),
) %>
<% end %>

1
app/views/locations/units.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_name_path(@scheme, @location, route: params[:route]),
) %>
<% end %>

8
app/views/logs/index.html.erb

@ -55,8 +55,12 @@
<%= govuk_button_to "Create a new sales log", sales_logs_path, class: "govuk-!-margin-right-6" %>
<% end %>
<% if FeatureToggle.bulk_upload_logs? %>
<%= govuk_button_link_to "Upload #{log_type_for_controller(controller)} logs in bulk", bulk_upload_path_for_controller(controller, id: "start"), secondary: true %>
<% if FeatureToggle.bulk_upload_lettings_logs? && log_type_for_controller(controller) == "lettings" %>
<%= govuk_button_link_to "Upload lettings logs in bulk", bulk_upload_path_for_controller(controller, id: "start"), secondary: true %>
<% end %>
<% if FeatureToggle.bulk_upload_sales_logs? && log_type_for_controller(controller) == "sales" %>
<%= govuk_button_link_to "Upload sales logs in bulk", bulk_upload_path_for_controller(controller, id: "start"), secondary: true %>
<% end %>
</div>
<% end %>

48
app/views/organisations/merge.html.erb

@ -0,0 +1,48 @@
<% content_for :before_content do %>
<% title = "Tell us if your organisation is merging" %>
<% content_for :title, title %>
<%= govuk_back_link href: organisation_path %>
<% end %>
<h2 class="govuk-heading-l">Tell us if your organisation is merging</h2>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds-from-desktop">
<p class="govuk-body">
Use this service to tell us if your organisation is merging with one or more other organisations. You can also use it to tell us about past merges that have not yet been reported to CORE.
</p>
<h2 class="govuk-heading-m">Before you start</h2>
<p class="govuk-body">Regardless of the merge type, you’ll be asked for:</p>
<ul class="govuk-list govuk-list--bullet">
<li>the organisations merging in CORE</li>
<li>the merge type: for example one organisation absorbing the rest, or them all creating a new organisation</li>
<li>to confirm or update the telephone number</li>
<li>the merge date</li>
<li>if user email addresses will change with this merge</li>
</ul>
<h2 class="govuk-heading-m">If email addresses are changing</h2>
<%= govuk_inset_text(text: "Update all user email addresses on CORE as soon as they change, so that everyone can still access their CORE account. ") %>
<p class="govuk-body">
Users must have access to their old email address, so they can confirm their new one.
</p>
<h2 class="govuk-heading-m">If merging into a new organisation</h2>
<p class="govuk-body">You'll also be asked for the new organisation’s:</p>
<ul class="govuk-list govuk-list--bullet">
<li>name</li>
<li>address</li>
<li>telephone number</li>
<li>housing provider type</li>
<li>Regulator of Social Housing registration number</li>
<li>held stock details</li>
</ul>
<%= govuk_warning_text text: "You will not be able to submit your request without the above information. Do not start the form until you have obtained all of the information. " %>
<%= govuk_start_button(
text: "Start now",
href: "#",
) %>
</div>
</div>

3
app/views/organisations/show.html.erb

@ -35,6 +35,9 @@
<% end %>
<% end %>
<% if FeatureToggle.merge_organisations_enabled? %>
<p>Is your organisation merging with another? <%= govuk_link_to "Let us know using this form", merge_organisation_path %></p>
<% end %>
</div>
<div class="govuk-grid-column-one-third-from-desktop">

1
app/views/schemes/confirm_secondary.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: request.query_parameters["check_answers"] ? "/schemes/#{@scheme.id}/check-answers" : "/schemes/#{@scheme.id}/primary-client-group",
) %>
<% end %>

5
app/views/schemes/details.html.erb

@ -1,10 +1,7 @@
<% content_for :title, "Create a new supported housing scheme" %>
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: :back,
) %>
<%= govuk_back_link(href: :back) %>
<% end %>
<%= form_for(@scheme, method: :patch) do |f| %>

5
app/views/schemes/edit_name.html.erb

@ -1,10 +1,7 @@
<% content_for :title, "Scheme details" %>
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: :back,
) %>
<%= govuk_back_link(href: :back) %>
<% end %>
<%= form_for(@scheme, method: :patch) do |f| %>

5
app/views/schemes/new.html.erb

@ -6,10 +6,7 @@
<% content_for :title, "Create a new supported housing scheme" %>
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: "javascript:history.go(-1);",
) %>
<%= govuk_back_link(href: "javascript:history.back()") %>
<% end %>
<h1 class="govuk-heading-l">

5
app/views/schemes/primary_client_group.html.erb

@ -7,10 +7,7 @@
<% end %>
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: back_button_path,
) %>
<%= govuk_back_link(href: back_button_path) %>
<% end %>
<%= form_for(@scheme, method: :patch) do |f| %>

1
app/views/schemes/secondary_client_group.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: request.query_parameters["check_answers"] ? "/schemes/#{@scheme.id}/check-answers" : "/schemes/#{@scheme.id}/confirm-secondary-client-group",
) %>
<% end %>

1
app/views/schemes/show.html.erb

@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: "/schemes",
) %>
<% end %>

1
app/views/schemes/support.html.erb

@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: request.query_parameters["check_answers"] ? "/schemes/#{@scheme.id}/check-answers" : "/schemes/#{@scheme.id}/secondary-client-group",
) %>
<% end %>

1
app/views/schemes/toggle_active.html.erb

@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
text: "Back",
href: scheme_details_path(@scheme),
) %>
<% end %>

201
config/forms/2022_2023.json

@ -7492,23 +7492,26 @@
"4": {
"value": "Every calendar month"
},
"5": {
"value": "Weekly for 50 weeks"
"9": {
"value": "Weekly for 46 weeks"
},
"6": {
"value": "Weekly for 49 weeks"
"8": {
"value": "Weekly for 47 weeks"
},
"7": {
"value": "Weekly for 48 weeks"
},
"8": {
"value": "Weekly for 47 weeks"
"6": {
"value": "Weekly for 49 weeks"
},
"9": {
"value": "Weekly for 46 weeks"
"5": {
"value": "Weekly for 50 weeks"
},
"1": {
"value": "Weekly for 52 weeks"
},
"10": {
"value": "Weekly for 53 weeks"
}
}
}
@ -7558,63 +7561,13 @@
},
"depends_on": [
{
"period": 1,
"needstype": 2,
"rent_and_charges_paid_weekly?": true,
"is_supported_housing?": true,
"household_charge": 0
},
{
"period": 1,
"needstype": 2,
"household_charge": null
},
{
"period": 5,
"needstype": 2,
"household_charge": 0
},
{
"period": 5,
"needstype": 2,
"household_charge": null
},
{
"period": 6,
"needstype": 2,
"household_charge": 0
},
{
"period": 6,
"needstype": 2,
"household_charge": null
},
{
"period": 7,
"needstype": 2,
"household_charge": 0
},
{
"period": 7,
"needstype": 2,
"household_charge": null
},
{
"period": 8,
"needstype": 2,
"household_charge": 0
},
{
"period": 8,
"needstype": 2,
"household_charge": null
},
{
"period": 9,
"needstype": 2,
"household_charge": 0
},
{
"period": 9,
"needstype": 2,
"rent_and_charges_paid_weekly?": true,
"is_supported_housing?": true,
"household_charge": null
}
]
@ -7898,124 +7851,14 @@
},
"depends_on": [
{
"period": 1,
"household_charge": 0,
"is_carehome": 0
},
{
"period": 1,
"household_charge": null,
"is_carehome": 0
},
{
"period": 5,
"household_charge": 0,
"is_carehome": 0
},
{
"period": 5,
"household_charge": null,
"is_carehome": 0
},
{
"period": 6,
"household_charge": 0,
"is_carehome": 0
},
{
"period": 6,
"household_charge": null,
"is_carehome": 0
},
{
"period": 7,
"household_charge": 0,
"is_carehome": 0
},
{
"period": 7,
"household_charge": null,
"is_carehome": 0
},
{
"period": 8,
"rent_and_charges_paid_weekly?": true,
"household_charge": 0,
"is_carehome": 0
"is_carehome?": false
},
{
"period": 8,
"rent_and_charges_paid_weekly?": true,
"household_charge": null,
"is_carehome": 0
},
{
"period": 9,
"household_charge": 0,
"is_carehome": 0
},
{
"period": 9,
"household_charge": null,
"is_carehome": 0
},
{
"period": 1,
"household_charge": 0,
"is_carehome": null
},
{
"period": 1,
"household_charge": null,
"is_carehome": null
},
{
"period": 5,
"household_charge": 0,
"is_carehome": null
},
{
"period": 5,
"household_charge": null,
"is_carehome": null
},
{
"period": 6,
"household_charge": 0,
"is_carehome": null
},
{
"period": 6,
"household_charge": null,
"is_carehome": null
},
{
"period": 7,
"household_charge": 0,
"is_carehome": null
},
{
"period": 7,
"household_charge": null,
"is_carehome": null
},
{
"period": 8,
"household_charge": 0,
"is_carehome": null
},
{
"period": 8,
"household_charge": null,
"is_carehome": null
},
{
"period": 9,
"household_charge": 0,
"is_carehome": null
},
{
"period": 9,
"household_charge": null,
"is_carehome": null
"is_carehome?": false
}
]
},
@ -8602,6 +8445,12 @@
"depends_on": {
"period": 1
}
},
{
"label": " every week for 53 weeks",
"depends_on": {
"period": 10
}
}
]
}

2
config/initializers/filter_parameter_logging.rb

@ -2,5 +2,5 @@
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += %i[
passw secret token crypt salt certificate otp ssn
passw secret token crypt salt certificate otp ssn reset_password_token
]

35
config/locales/en.yml

@ -190,11 +190,11 @@ en:
reactivating_soon: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date"
activating_soon: "%{name} is not available until %{date}. Enter a tenancy start date after %{date}"
owning_organisation:
invalid: "Please select owning organisation or managing organisation that you belong to"
invalid: "Please select the owning organisation or managing organisation that you belong to"
managing_organisation:
invalid: "Please select owning organisation or managing organisation that you belong to"
invalid: "Please select the owning organisation or managing organisation that you belong to"
created_by:
invalid: "Please select owning organisation or managing organisation that you belong to"
invalid: "Please select the owning organisation or managing organisation that you belong to"
lettype:
general_needs_mismatch: Lettings type must be a general needs type because you selected general needs when uploading the file
supported_housing_mismatch: Lettings type must be a supported housing type because you selected supported housing when uploading the file
@ -253,10 +253,10 @@ en:
freq_missing: "Select how often the household receives income"
earnings_missing: "Enter how much income the household has in total"
income:
over_hard_max_for_london: "Income must not exceed £90,000.00 for properties within London local authorities"
over_hard_max_for_outside_london: "Income must not exceed £80,000.00 for properties outside London local authorities"
combined_over_hard_max_for_london: "Combined income must not exceed £90,000.00 for properties within London local authorities"
combined_over_hard_max_for_outside_london: "Combined income must not exceed £80,000.00 for properties outside London local authorities"
over_hard_max_for_london: "Income must be £90,000 or lower for properties within a London local authority"
over_hard_max_for_outside_london: "Income must be £80,000 or lower for properties outside 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:
@ -283,7 +283,7 @@ en:
general_needs: "Enter a value for the support charge between £0 and £60 per week if the landlord is a local authority and it is a general needs letting"
supported_housing: "Enter a value for the support charge between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting"
ecstat:
over_hard_max: "Net income of £%{hard_max} per week is too high for given the tenant’s working situation"
over_hard_max: "Net income of %{hard_max} per week is too high given the tenant’s working situation"
brent:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
@ -314,7 +314,7 @@ en:
charges:
complete_1_of_3: "Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’"
tcharge:
under_10: "Enter a total charge that is at least £10 per week"
under_10: "Enter a total charge that is at least £10.00 per week"
rent_period:
invalid_for_org: "%{org_name} does not charge rent %{rent_period}"
carehome:
@ -466,6 +466,7 @@ en:
during_deactivated_period: "The scheme is already deactivated during this date, please enter a different date"
owning_organisation:
does_not_own_stock: "Enter an organisation that owns housing stock"
no_completed_locations: "This scheme cannot be chosen as it has no completed locations"
location:
postcode_blank: "Enter a postcode"
@ -516,8 +517,8 @@ en:
under_soft_min_for_economic_status: "You said income was %{income}, which is below this working situation's minimum (%{minimum})"
rent:
outside_range_title: "You told us the rent is %{brent}"
min_hint_text: "The minimum rent expected for this type of property in this local authority is £%{soft_min_for_period}."
max_hint_text: "The maximum rent expected for this type of property in this local authority is £%{soft_max_for_period}."
min_hint_text: "The minimum rent expected for this type of property in this local authority is %{soft_min_for_period}."
max_hint_text: "The maximum rent expected for this type of property in this local authority is %{soft_max_for_period}."
purchase_price:
title_text: "You told us the purchase price is %{value}"
hint_text: "The %{min_or_max} purchase price expected for this type of property in this local authority is %{soft_min_or_soft_max}"
@ -539,7 +540,7 @@ en:
void_date:
title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years"
shared_ownership_deposit:
title_text: "Mortgage, deposit and cash discount total should equal £%{expected_shared_ownership_deposit_value}"
title_text: "Mortgage, deposit and cash discount total should equal %{expected_shared_ownership_deposit_value}"
old_persons_shared_ownership: "At least one buyer should be aged over 64 for Older persons’ shared ownership scheme"
staircase_bought_seems_high: "You said %{percentage}% was bought in this staircasing transaction, which seems high. Are you sure?"
monthly_charges_over_soft_max:
@ -547,10 +548,16 @@ en:
student_not_child:
title_text: "You told us this person is a student aged beween 16 and 19"
discounted_sale_value:
title_text: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
informative_text: "Your given mortgage, deposit and grant total is £%{mortgage_deposit_and_grant_total}"
title_text: "Mortgage, deposit, and grant total must equal %{value_with_discount}"
informative_text: "Your given mortgage, deposit and grant total is %{mortgage_deposit_and_grant_total}"
care_home_charges:
title_text: "Care home charges should be provided if this is a care home accommodation"
buyer1_livein_wrong_for_ownership_type:
title_text: "You told us that buyer 1 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
buyer2_livein_wrong_for_ownership_type:
title_text: "You told us that buyer 2 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
percentage_discount_value:
title_text: "You told us that the percentage discount was %{discount}. This seems high for this type of property."
devise:
two_factor_authentication:

1
config/routes.rb

@ -119,6 +119,7 @@ Rails.application.routes.draw do
get "managing-agents/remove", to: "organisation_relationships#remove_managing_agent"
post "managing-agents", to: "organisation_relationships#create_managing_agent"
delete "managing-agents", to: "organisation_relationships#delete_managing_agent"
get "merge", to: "organisations#merge"
end
end

5
db/migrate/20230405074138_add_percentage_discount_value_check.rb

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

5
db/migrate/20230405140343_add_buyer_livin_value_check.rb

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

2
db/schema.rb

@ -573,6 +573,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_04_12_143245) do
t.integer "nationalbuy2"
t.integer "discounted_sale_value_check"
t.integer "student_not_child_value_check"
t.integer "buyer_livein_value_check"
t.integer "percentage_discount_value_check"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true

BIN
public/files/bulk-upload-lettings-specification-2023-24.xlsx

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save