Browse Source

Merge branch 'main' into CLDC-868-purchase-price-validations

# Conflicts:
#	app/models/form/sales/subsections/shared_ownership_scheme.rb
#	app/models/sales_log.rb
#	app/models/validations/sales/soft_validations.rb
#	db/schema.rb
#	spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
#	spec/models/form_handler_spec.rb
pull/1225/head
natdeanlewissoftwire 3 years ago
parent
commit
7861db285e
  1. 28
      app/controllers/bulk_upload_lettings_results_controller.rb
  2. 14
      app/controllers/lettings_logs_controller.rb
  3. 4
      app/controllers/modules/logs_filter.rb
  4. 5
      app/helpers/logs_helper.rb
  5. 27
      app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
  6. 1
      app/models/form/sales/questions/mortgage_length.rb
  7. 23
      app/models/form/sales/questions/shared_ownership_deposit_value_check.rb
  8. 5
      app/models/form/sales/subsections/shared_ownership_scheme.rb
  9. 4
      app/models/log.rb
  10. 10
      app/models/sales_log.rb
  11. 4
      app/models/user.rb
  12. 10
      app/models/validations/sales/financial_validations.rb
  13. 9
      app/models/validations/sales/sale_information_validations.rb
  14. 13
      app/models/validations/sales/soft_validations.rb
  15. 1
      app/services/bulk_upload/lettings/validator.rb
  16. 11
      app/views/bulk_upload_lettings_results/resume.html.erb
  17. 54
      app/views/logs/_log_filters.erb
  18. 62
      app/views/logs/index.html.erb
  19. 4
      config/locales/en.yml
  20. 6
      config/routes.rb
  21. 7
      db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb
  22. 5
      db/migrate/20230126145529_add_column_to_bulk_upload_errors.rb
  23. 21
      db/schema.rb
  24. 68
      spec/controllers/bulk_upload_lettings_results_controller_spec.rb
  25. 4
      spec/models/form/sales/pages/buyer1_income_value_check_spec.rb
  26. 4
      spec/models/form/sales/pages/deposit_value_check_spec.rb
  27. 4
      spec/models/form/sales/pages/handover_date_check_spec.rb
  28. 4
      spec/models/form/sales/pages/household_wheelchair_check_spec.rb
  29. 4
      spec/models/form/sales/pages/mortgage_value_check_spec.rb
  30. 4
      spec/models/form/sales/pages/retirement_value_check_spec.rb
  31. 4
      spec/models/form/sales/pages/savings_value_check_spec.rb
  32. 50
      spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
  33. 4
      spec/models/form/sales/questions/mortgage_length_spec.rb
  34. 61
      spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb
  35. 3
      spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
  36. 4
      spec/models/form_handler_spec.rb
  37. 8
      spec/models/sales_log_spec.rb
  38. 6
      spec/models/user_spec.rb
  39. 26
      spec/models/validations/sales/financial_validations_spec.rb
  40. 57
      spec/models/validations/sales/sale_information_validations_spec.rb
  41. 104
      spec/models/validations/sales/soft_validations_spec.rb
  42. 103
      spec/requests/lettings_logs_controller_spec.rb
  43. 9
      spec/services/bulk_upload/lettings/validator_spec.rb
  44. 34
      spec/support/bulk_upload/log_to_csv.rb

28
app/controllers/bulk_upload_lettings_results_controller.rb

@ -6,4 +6,32 @@ class BulkUploadLettingsResultsController < ApplicationController
def show def show
@bulk_upload = current_user.bulk_uploads.lettings.find(params[:id]) @bulk_upload = current_user.bulk_uploads.lettings.find(params[:id])
end end
def resume
@bulk_upload = current_user.bulk_uploads.lettings.find(params[:id])
if @bulk_upload.lettings_logs.in_progress.count.positive?
set_bulk_upload_logs_filters
redirect_to(lettings_logs_path(bulk_upload_id: [@bulk_upload.id]))
else
reset_logs_filters
end
end
private
def reset_logs_filters
session["logs_filters"] = {}.to_json
end
def set_bulk_upload_logs_filters
hash = {
years: [""],
status: ["", "in_progress"],
user: "all",
}
session["logs_filters"] = hash.to_json
end
end end

14
app/controllers/lettings_logs_controller.rb

@ -3,6 +3,9 @@ class LettingsLogsController < LogsController
before_action :session_filters, if: :current_user before_action :session_filters, if: :current_user
before_action :set_session_filters, if: :current_user before_action :set_session_filters, if: :current_user
before_action :extract_bulk_upload_from_session_filters, only: [:index]
before_action :redirect_if_bulk_upload_resolved, only: [:index]
def index def index
respond_to do |format| respond_to do |format|
format.html do format.html do
@ -109,6 +112,17 @@ class LettingsLogsController < LogsController
private private
def redirect_if_bulk_upload_resolved
if @bulk_upload && @bulk_upload.lettings_logs.in_progress.count.zero?
redirect_to resume_bulk_upload_lettings_result_path(@bulk_upload)
end
end
def extract_bulk_upload_from_session_filters
id = ((@session_filters["bulk_upload_id"] || []).reject(&:blank?))[0]
@bulk_upload = current_user.bulk_uploads.find_by(id:)
end
def permitted_log_params def permitted_log_params
params.require(:lettings_log).permit(LettingsLog.editable_fields) params.require(:lettings_log).permit(LettingsLog.editable_fields)
end end

4
app/controllers/modules/logs_filter.rb

@ -7,7 +7,9 @@ module Modules::LogsFilter
def load_session_filters(specific_org: false) def load_session_filters(specific_org: false)
current_filters = session[:logs_filters] current_filters = session[:logs_filters]
new_filters = current_filters.present? ? JSON.parse(current_filters) : {} new_filters = current_filters.present? ? JSON.parse(current_filters) : {}
current_user.logs_filters(specific_org:).each { |filter| new_filters[filter] = params[filter] if params[filter].present? } current_user.logs_filters(specific_org:).each do |filter|
new_filters[filter] = params[filter] if params[filter].present?
end
params["organisation_select"] == "all" ? new_filters.except("organisation") : new_filters params["organisation_select"] == "all" ? new_filters.except("organisation") : new_filters
end end

5
app/helpers/logs_helper.rb

@ -18,4 +18,9 @@ module LogsHelper
bulk_upload_sales_log_path(id:) bulk_upload_sales_log_path(id:)
end end
end end
def bulk_upload_options(bulk_upload)
array = bulk_upload ? [bulk_upload.id] : []
array.index_with { |_bulk_upload_id| "With logs from bulk upload" }
end
end end

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

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

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

@ -6,6 +6,7 @@ class Form::Sales::Questions::MortgageLength < ::Form::Question
@header = "What is the length of the mortgage?" @header = "What is the length of the mortgage?"
@type = "numeric" @type = "numeric"
@min = 0 @min = 0
@max = 60
@width = 5 @width = 5
@suffix = " years" @suffix = " years"
@hint_text = "You should round up to the nearest year. Value should not exceed 60 years." @hint_text = "You should round up to the nearest year. Value should not exceed 60 years."

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

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

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

@ -22,15 +22,18 @@ class Form::Sales::Subsections::SharedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::PreviousTenure.new(nil, nil, self), Form::Sales::Pages::PreviousTenure.new(nil, nil, self),
Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self), Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self),
Form::Sales::Pages::AboutPriceSharedOwnershipValueCheck.new(nil, nil, self), Form::Sales::Pages::AboutPriceSharedOwnershipValueCheck.new(nil, nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_equity_value_check", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_mortgage_amount_value_check", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_shared_ownership", nil, self), Form::Sales::Pages::MortgageLender.new("mortgage_lender_shared_ownership", nil, self),
Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_shared_ownership", nil, self), Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_shared_ownership", nil, self),
Form::Sales::Pages::MortgageLength.new("mortgage_length_shared_ownership", nil, self), Form::Sales::Pages::MortgageLength.new("mortgage_length_shared_ownership", nil, self),
Form::Sales::Pages::ExtraBorrowing.new("extra_borrowing_shared_ownership", nil, self), Form::Sales::Pages::ExtraBorrowing.new("extra_borrowing_shared_ownership", nil, self),
Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self), Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self), Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self),
Form::Sales::Pages::DepositValueCheck.new("shared_ownership_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("deposit_value_check", nil, self),
Form::Sales::Pages::SharedOwnershipDepositValueCheck.new("shared_ownership_deposit_value_check", nil, self),
Form::Sales::Pages::MonthlyRent.new(nil, nil, self), Form::Sales::Pages::MonthlyRent.new(nil, nil, self),
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_shared_ownership", nil, self), Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_shared_ownership", nil, self),
] ]

4
app/models/log.rb

@ -24,6 +24,10 @@ class Log < ApplicationRecord
where(created_by: user) where(created_by: user)
end end
} }
scope :filter_by_bulk_upload_id, lambda { |bulk_upload_id, user|
joins(:bulk_upload)
.where(bulk_upload: { id: bulk_upload_id, user: })
}
scope :created_by, ->(user) { where(created_by: user) } scope :created_by, ->(user) { where(created_by: user) }
def collection_start_year def collection_start_year

10
app/models/sales_log.rb

@ -159,6 +159,12 @@ class SalesLog < Log
end end
end end
def expected_shared_ownership_deposit_value
return unless value && equity
(value * equity / 100).round(2)
end
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key) def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
return if postcode.blank? return if postcode.blank?
@ -212,6 +218,10 @@ class SalesLog < Log
type == 24 type == 24
end end
def shared_ownership_scheme?
ownershipsch == 1
end
def purchase_price_soft_min def purchase_price_soft_min
LaSaleRange.find_by(start_year: collection_start_year, la:, bedrooms: beds).soft_min LaSaleRange.find_by(start_year: collection_start_year, la:, bedrooms: beds).soft_min
end end

4
app/models/user.rb

@ -145,9 +145,9 @@ class User < ApplicationRecord
def logs_filters(specific_org: false) def logs_filters(specific_org: false)
if (support? && !specific_org) || organisation.has_managing_agents? if (support? && !specific_org) || organisation.has_managing_agents?
%w[status years user organisation] %w[status years user organisation bulk_upload_id]
else else
%w[status years user] %w[status years user bulk_upload_id]
end end
end end

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

@ -3,11 +3,19 @@ module Validations::Sales::FinancialValidations
# or 'validate_' to run on submit as well # or 'validate_' to run on submit as well
def validate_income1(record) def validate_income1(record)
if record.ecstat1 && record.income1 && record.ownershipsch == 1 if record.ecstat1 && record.income1 && record.la && record.ownershipsch == 1
if record.london_property? if record.london_property?
record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000 record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :ecstat1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :ownershipsch, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :la, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
record.errors.add :postcode_full, I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000) if record.income1 > 90_000
elsif record.income1 > 80_000 elsif record.income1 > 80_000
record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000) record.errors.add :income1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :ecstat1, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :ownershipsch, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)
record.errors.add :la, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000) if record.income1 > 80_000
record.errors.add :postcode_full, I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000) if record.income1 > 80_000
end end
end end
end end

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

@ -63,4 +63,13 @@ module Validations::Sales::SaleInformationValidations
end end
end end
end end
def validate_basic_monthly_rent(record)
return unless record.mrent && record.ownershipsch && record.type
if record.shared_owhership_scheme? && !record.old_persons_shared_ownership? && record.mrent > 9999
record.errors.add :mrent, I18n.t("validations.sale_information.monthly_rent.higher_than_expected")
record.errors.add :type, I18n.t("validations.sale_information.monthly_rent.higher_than_expected")
end
end
end end

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

@ -55,6 +55,19 @@ module Validations::Sales::SoftValidations
sale_range.present? && !value.between?(sale_range.soft_min, sale_range.soft_max) sale_range.present? && !value.between?(sale_range.soft_min, sale_range.soft_max)
end end
def shared_ownership_deposit_invalid?
return unless mortgage || mortgageused == 2
return unless cashdis || !is_type_discount?
return unless deposit && value && equity
cash_discount = cashdis || 0
mortgage_value = mortgage || 0
mortgage_value + deposit + cash_discount != value * equity / 100
end
def hodate_3_years_or_more_saledate?
return unless hodate && saledate
def purchase_price_min_or_max_text def purchase_price_min_or_max_text
value < sale_range.soft_min ? "minimum" : "maximum" value < sale_range.soft_min ? "minimum" : "maximum"
end end

1
app/services/bulk_upload/lettings/validator.rb

@ -164,6 +164,7 @@ class BulkUpload::Lettings::Validator
property_ref: row_parser.field_100, property_ref: row_parser.field_100,
row:, row:,
cell: "#{cols[field_number_for_attribute(error.attribute) - col_offset + 1]}#{row}", cell: "#{cols[field_number_for_attribute(error.attribute) - col_offset + 1]}#{row}",
col: cols[field_number_for_attribute(error.attribute) - col_offset + 1],
) )
end end
end end

11
app/views/bulk_upload_lettings_results/resume.html.erb

@ -0,0 +1,11 @@
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-xl">There are no more logs that need updating</h1>
</div>
</div>
<p class="govuk-body-l">
You’ve completed all the logs that had errors from your bulk upload.
</p>
<%= govuk_button_link_to "Back to all logs", lettings_logs_path, button: true %>

54
app/views/logs/_log_filters.erb

@ -3,13 +3,48 @@
<div class="app-filter__header"> <div class="app-filter__header">
<h2 class="govuk-heading-m">Filters</h2> <h2 class="govuk-heading-m">Filters</h2>
</div> </div>
<div class="app-filter__content"> <div class="app-filter__content">
<%= form_with html: { method: :get } do |f| %> <%= form_with html: { method: :get } do |f| %>
<% years = {"2021": "2021/22", "2022": "2022/23"} %> <% years = { "2021": "2021/22", "2022": "2022/23" } %>
<% all_or_yours = {"all": { label: "All" }, "yours": { label: "Yours" } } %> <% all_or_yours = { "all": { label: "All" }, "yours": { label: "Yours" } } %>
<%= render partial: "filters/checkbox_filter", locals: { f: f, options: years, label: "Collection year", category: "years" } %>
<%= render partial: "filters/checkbox_filter", locals: { f: f, options: status_filters, label: "Status", category: "status" } %> <% if bulk_upload_options(@bulk_upload).present? %>
<%= render partial: "filters/radio_filter", locals: { f: f, options: all_or_yours, label: "Logs", category: "user", } %> <%= render partial: "filters/checkbox_filter",
locals: {
f: f,
options: bulk_upload_options(@bulk_upload),
label: "Bulk upload",
category: "bulk_upload_id",
} %>
<% end %>
<% if bulk_upload_options(@bulk_upload).blank? %>
<%= render partial: "filters/checkbox_filter",
locals: {
f: f,
options: years,
label: "Collection year",
category: "years",
} %>
<%= render partial: "filters/checkbox_filter",
locals: {
f: f,
options: status_filters,
label: "Status",
category: "status",
} %>
<% end %>
<%= render partial: "filters/radio_filter",
locals: {
f: f,
options: all_or_yours,
label: "Logs",
category: "user",
} %>
<% if (@current_user.support? || @current_user.organisation.has_managing_agents?) && request.path == "/lettings-logs" %> <% if (@current_user.support? || @current_user.organisation.has_managing_agents?) && request.path == "/lettings-logs" %>
<%= render partial: "filters/radio_filter", locals: { <%= render partial: "filters/radio_filter", locals: {
f: f, f: f,
@ -21,14 +56,15 @@
type: "select", type: "select",
label: "Organisation", label: "Organisation",
category: "organisation", category: "organisation",
options: organisations_filter_options(@current_user) options: organisations_filter_options(@current_user),
} },
} },
}, },
label: "Organisation", label: "Organisation",
category: "organisation_select" category: "organisation_select",
} %> } %>
<% end %> <% end %>
<%= f.govuk_submit "Apply filters", class: "govuk-!-margin-bottom-0" %> <%= f.govuk_submit "Apply filters", class: "govuk-!-margin-bottom-0" %>
<% end %> <% end %>
</div> </div>

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

@ -11,32 +11,58 @@
title_id: "impacted-logs-banner", title_id: "impacted-logs-banner",
) do |notification_banner| %> ) do |notification_banner| %>
<% notification_banner.heading(text: "A scheme has changed and it has affected #{@unresolved_count} #{'log'.pluralize(@unresolved_count)}") %> <% notification_banner.heading(text: "A scheme has changed and it has affected #{@unresolved_count} #{'log'.pluralize(@unresolved_count)}") %>
<div class="govuk-notification-banner__heading"> <div class="govuk-notification-banner__heading">
<%= govuk_link_to "Update logs", update_logs_lettings_logs_path, class: "govuk-notification-banner__link" %> <%= govuk_link_to "Update logs", update_logs_lettings_logs_path, class: "govuk-notification-banner__link" %>
</div> </div>
<% end %>
<% end %> <% end %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Lettings logs", sub: nil } : { main: "Lettings logs", sub: current_user.organisation.name } %> <% end %>
<% elsif current_page?(controller: 'sales_logs', action: 'index') %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Sales logs", sub: nil } : { main: "Sales logs", sub: current_user.organisation.name } %>
<% end %> <% end %>
<div class="app-filter-layout" data-controller="filter-layout"> <% if @bulk_upload.blank? %>
<div class="govuk-button-group app-filter-toggle govuk-!-margin-bottom-6"> <%= render partial: "organisations/headings", locals: current_user.support? ? { main: "#{log_type_for_controller(controller).capitalize} logs", sub: nil } : { main: "#{log_type_for_controller(controller).capitalize} logs", sub: current_user.organisation.name } %>
<% if current_page?(controller: 'lettings_logs', action: 'index') %> <% else %>
<%= govuk_button_to "Create a new lettings log", lettings_logs_path, class: "govuk-!-margin-right-6" %> <%= render partial: "organisations/headings",
<% end %> locals: {
main: "You need to fix #{pluralize(@pagy.count, 'log')} from your bulk upload",
sub: "#{log_type_for_controller(controller).capitalize} logs (#{@bulk_upload.year_combo})",
} %>
<% if FeatureToggle.sales_log_enabled? && current_page?(controller: 'sales_logs', action: 'index') %> <div class="app-card govuk-!-margin-bottom-9">
<%= govuk_button_to "Create a new sales log", sales_logs_path, class: "govuk-!-margin-right-6" %> <div class="govuk-grid-row">
<% end %> <div class="govuk-grid-column-two-thirds">
<p class="govuk-body-l">
The following logs are from your recent bulk upload. They have some incorrect or incomplete data. You’ll need to answer a few more questions for each one to mark them as complete.
</p>
<% if FeatureToggle.bulk_upload_logs? %> <p class="govuk-body">
<%= govuk_button_link_to "Upload #{log_type_for_controller(controller)} logs in bulk", bulk_upload_path_for_controller(controller, id: "start"), secondary: true %> <strong>Bulk Upload details:</strong><br>
<% end %> <%= @bulk_upload.filename %><br>
Uploaded on <%= @bulk_upload.created_at.to_fs(:govuk_date_and_time) %><br>
</p>
</div>
</div>
</div> </div>
<% end %>
<div class="app-filter-layout" data-controller="filter-layout">
<% unless @bulk_upload %>
<div class="govuk-button-group app-filter-toggle govuk-!-margin-bottom-6">
<% if current_page?(controller: 'lettings_logs', action: 'index') %>
<%= govuk_button_to "Create a new lettings log", lettings_logs_path, class: "govuk-!-margin-right-6" %>
<% end %>
<% if FeatureToggle.sales_log_enabled? && current_page?(controller: 'sales_logs', action: 'index') %>
<%= 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 %>
<% end %>
</div>
<% end %>
<%= render partial: "log_filters" %> <%= render partial: "log_filters" %>
<div class="app-filter-layout__content"> <div class="app-filter-layout__content">
<%= render SearchComponent.new(current_user:, search_label: "Search by log ID, tenant code, property reference or postcode", value: @searched) %> <%= render SearchComponent.new(current_user:, search_label: "Search by log ID, tenant code, property reference or postcode", value: @searched) %>
<%= govuk_section_break(visible: true, size: "m") %> <%= govuk_section_break(visible: true, size: "m") %>

4
config/locales/en.yml

@ -429,6 +429,8 @@ en:
handover_before_exchange: "Practical completion or handover date must be before exchange date" handover_before_exchange: "Practical completion or handover date must be before exchange date"
exchange_after_handover: "Exchange date must be after practical completion or handover date" exchange_after_handover: "Exchange date must be after practical completion or handover date"
discounted_ownership_value: "Mortgage, deposit, and grant total must equal £%{value_with_discount}" discounted_ownership_value: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
monthly_rent:
higher_than_expected: "Basic monthly rent must be between £0 and £9,999"
soft_validations: soft_validations:
net_income: net_income:
@ -465,6 +467,8 @@ en:
title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years" title_text: "You told us the time between the start of the tenancy and the major repairs completion date is more than 2 years"
void_date: void_date:
title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years" title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years"
shared_owhership_deposit:
title_text: "Mortgage, deposit and cash discount total should equal £%{expected_shared_ownership_deposit_value}"
devise: devise:
two_factor_authentication: two_factor_authentication:

6
config/routes.rb

@ -134,7 +134,11 @@ Rails.application.routes.draw do
end end
end end
resources :bulk_upload_lettings_results, path: "bulk-upload-results", only: [:show] resources :bulk_upload_lettings_results, path: "bulk-upload-results", only: [:show] do
member do
get :resume
end
end
get "update-logs", to: "lettings_logs#update_logs" get "update-logs", to: "lettings_logs#update_logs"
end end

7
db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb

@ -0,0 +1,7 @@
class AddSharedOwnershipDepositValueCheck < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :shared_ownership_deposit_value_check, :integer
end
end
end

5
db/migrate/20230126145529_add_column_to_bulk_upload_errors.rb

@ -0,0 +1,5 @@
class AddColumnToBulkUploadErrors < ActiveRecord::Migration[7.0]
def change
add_column :bulk_upload_errors, :col, :text
end
end

21
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do ActiveRecord::Schema[7.0].define(version: 2023_01_26_145529) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -25,6 +25,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do
t.text "error" t.text "error"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.text "col"
t.index ["bulk_upload_id"], name: "index_bulk_upload_errors_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_bulk_upload_errors_on_bulk_upload_id"
end end
@ -69,17 +70,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do
t.index ["start_year", "lettype", "beds", "la"], name: "index_la_rent_ranges_on_start_year_and_lettype_and_beds_and_la", unique: true t.index ["start_year", "lettype", "beds", "la"], name: "index_la_rent_ranges_on_start_year_and_lettype_and_beds_and_la", unique: true
end end
create_table "la_sale_ranges", force: :cascade do |t|
t.string "la"
t.integer "bedrooms"
t.decimal "soft_min", precision: 10, scale: 2
t.decimal "soft_max", precision: 10, scale: 2
t.integer "start_year"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["start_year", "bedrooms", "la"], name: "index_la_sale_ranges_on_start_year_bedrooms_la", unique: true
end
create_table "legacy_users", force: :cascade do |t| create_table "legacy_users", force: :cascade do |t|
t.string "old_user_id" t.string "old_user_id"
t.integer "user_id" t.integer "user_id"
@ -497,9 +487,9 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do
t.integer "hoyear" t.integer "hoyear"
t.integer "fromprop" t.integer "fromprop"
t.integer "socprevten" t.integer "socprevten"
t.integer "mortlen"
t.integer "mortgagelender" t.integer "mortgagelender"
t.string "mortgagelenderother" t.string "mortgagelenderother"
t.integer "mortlen"
t.integer "extrabor" t.integer "extrabor"
t.integer "hhmemb" t.integer "hhmemb"
t.integer "totadult" t.integer "totadult"
@ -512,11 +502,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do
t.boolean "is_la_inferred" t.boolean "is_la_inferred"
t.bigint "bulk_upload_id" t.bigint "bulk_upload_id"
t.integer "retirement_value_check" t.integer "retirement_value_check"
t.integer "deposit_and_mortgage_value_check"
t.integer "grant_value_check"
t.integer "hodate_check" t.integer "hodate_check"
t.integer "extrabor_value_check" t.integer "extrabor_value_check"
t.integer "grant_value_check"
t.integer "value_value_check"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.integer "shared_ownership_deposit_value_check"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"
t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id" t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id"

68
spec/controllers/bulk_upload_lettings_results_controller_spec.rb

@ -0,0 +1,68 @@
require "rails_helper"
RSpec.describe BulkUploadLettingsResultsController do
before do
sign_in user
end
describe "GET #resume /lettings-logs/bulk-upload-results/:ID/resume" do
let(:user) { create(:user) }
let(:bulk_upload) { create(:bulk_upload, :lettings, user:) }
context "when there are no logs left to resolve" do
render_views
it "displays copy to user" do
get :resume, params: { id: bulk_upload.id }
expect(response.body).to include("There are no more logs that need updating")
end
it "resets logs filters" do
get :resume, params: { id: bulk_upload.id }
expect(JSON.parse(session["logs_filters"])).to eql({})
end
end
context "when there are logs left to resolve" do
before do
create(:lettings_log, :in_progress, bulk_upload:)
end
it "clears the year filter" do
hash = {
years: ["", "2022"],
}
session["logs_filters"] = hash.to_json
get :resume, params: { id: bulk_upload.id }
expect(JSON.parse(session["logs_filters"])["years"]).to eql([""])
end
it "sets the status filter to in progress" do
session["logs_filters"] ||= {}.to_json
get :resume, params: { id: bulk_upload.id }
expect(JSON.parse(session["logs_filters"])["status"]).to eql(["", "in_progress"])
end
it "sets the user filter to all" do
session["logs_filters"] ||= {}.to_json
get :resume, params: { id: bulk_upload.id }
expect(JSON.parse(session["logs_filters"])["user"]).to eql("all")
end
it "redirects to logs with bulk upload filter applied" do
get :resume, params: { id: bulk_upload.id }
expect(response).to redirect_to("/lettings-logs?bulk_upload_id%5B%5D=#{bulk_upload.id}")
end
end
end
end

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

@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::Buyer1IncomeValueCheck, type: :model do
}, },
]) ])
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

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

@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::DepositValueCheck, type: :model do
}, },
]) ])
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

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

@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::HandoverDateCheck, type: :model do
}, },
]) ])
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

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

@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::HouseholdWheelchairCheck, type: :model do
}, },
]) ])
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

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

@ -23,6 +23,10 @@ RSpec.describe Form::Sales::Pages::MortgageValueCheck, type: :model do
expect(page.header).to be_nil expect(page.header).to be_nil
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to eq([ expect(page.depends_on).to eq([
{ {

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

@ -600,4 +600,8 @@ RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do
end end
end end
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

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

@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::SavingsValueCheck, type: :model do
}, },
]) ])
end end
it "is interruption screen page" do
expect(page.interruption_screen?).to eq(true)
end
end end

50
spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb

@ -0,0 +1,50 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::SharedOwnershipDepositValueCheck, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "shared_ownership_deposit_value_check" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[shared_ownership_deposit_value_check])
end
it "has the correct id" do
expect(page.id).to eq("shared_ownership_deposit_value_check")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to eq([
{
"shared_ownership_deposit_invalid?" => true,
},
])
end
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.shared_owhership_deposit.title_text",
"arguments" => [
{
"key" => "expected_shared_ownership_deposit_value",
"label" => false,
"i18n_template" => "expected_shared_ownership_deposit_value",
},
],
})
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({})
end
end

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

@ -48,4 +48,8 @@ RSpec.describe Form::Sales::Questions::MortgageLength, type: :model do
it "has correct min" do it "has correct min" do
expect(question.min).to eq(0) expect(question.min).to eq(0)
end end
it "has correct max" do
expect(question.max).to eq(60)
end
end end

61
spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb

@ -0,0 +1,61 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::SharedOwnershipDepositValueCheck, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("shared_ownership_deposit_value_check")
end
it "has the correct header" do
expect(question.header).to eq("Are you sure this is correct?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Shared ownership deposit confirmation")
end
it "has the correct type" do
expect(question.type).to eq("interruption_screen")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
# it "has a correct check_answers_card_number" do
# expect(question.check_answers_card_number).to eq(0)
# end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
})
end
it "has the correct hidden_in_check_answers" do
expect(question.hidden_in_check_answers).to eq({
"depends_on" => [
{
"shared_ownership_deposit_value_check" => 0,
},
{
"shared_ownership_deposit_value_check" => 1,
},
],
})
end
end

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

@ -28,14 +28,17 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipScheme, type: :model do
shared_ownership_previous_tenure shared_ownership_previous_tenure
about_price_shared_ownership about_price_shared_ownership
about_price_shared_ownership_value_check about_price_shared_ownership_value_check
shared_ownership_equity_value_check
mortgage_used_shared_ownership mortgage_used_shared_ownership
mortgage_amount_shared_ownership mortgage_amount_shared_ownership
shared_ownership_mortgage_amount_value_check
mortgage_lender_shared_ownership mortgage_lender_shared_ownership
mortgage_lender_other_shared_ownership mortgage_lender_other_shared_ownership
mortgage_length_shared_ownership mortgage_length_shared_ownership
extra_borrowing_shared_ownership extra_borrowing_shared_ownership
about_deposit_with_discount about_deposit_with_discount
about_deposit_shared_ownership about_deposit_shared_ownership
deposit_value_check
shared_ownership_deposit_value_check shared_ownership_deposit_value_check
monthly_rent monthly_rent
leasehold_charges_shared_ownership leasehold_charges_shared_ownership

4
spec/models/form_handler_spec.rb

@ -52,14 +52,14 @@ RSpec.describe FormHandler do
it "is able to load a current sales form" do it "is able to load a current sales form" do
form = form_handler.get_form("current_sales") form = form_handler.get_form("current_sales")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to eq(189) expect(form.pages.count).to eq(192)
expect(form.name).to eq("2022_2023_sales") expect(form.name).to eq("2022_2023_sales")
end end
it "is able to load a previous sales form" do it "is able to load a previous sales form" do
form = form_handler.get_form("previous_sales") form = form_handler.get_form("previous_sales")
expect(form).to be_a(Form) expect(form).to be_a(Form)
expect(form.pages.count).to eq(189) expect(form.pages.count).to eq(192)
expect(form.name).to eq("2021_2022_sales") expect(form.name).to eq("2021_2022_sales")
end end
end end

8
spec/models/sales_log_spec.rb

@ -339,4 +339,12 @@ RSpec.describe SalesLog, type: :model do
expect(record_from_db["prevloc"]).to eq(nil) expect(record_from_db["prevloc"]).to eq(nil)
end end
end end
describe "expected_shared_ownership_deposit_value" do
let!(:completed_sales_log) { create(:sales_log, :completed, ownershipsch: 1, type: 2, value: 1000, equity: 50) }
it "is set to completed for a completed sales log" do
expect(completed_sales_log.expected_shared_ownership_deposit_value).to eq(500)
end
end
end end

6
spec/models/user_spec.rb

@ -123,7 +123,7 @@ RSpec.describe User, type: :model do
end end
it "can filter lettings logs by user, year and status" do it "can filter lettings logs by user, year and status" do
expect(user.logs_filters).to eq(%w[status years user]) expect(user.logs_filters).to eq(%w[status years user bulk_upload_id])
end end
end end
@ -133,7 +133,7 @@ RSpec.describe User, type: :model do
end end
it "can filter lettings logs by user, year, status and organisation" do it "can filter lettings logs by user, year, status and organisation" do
expect(user.logs_filters).to eq(%w[status years user organisation]) expect(user.logs_filters).to eq(%w[status years user organisation bulk_upload_id])
end end
end end
end end
@ -159,7 +159,7 @@ RSpec.describe User, type: :model do
end end
it "can filter lettings logs by user, year, status and organisation" do it "can filter lettings logs by user, year, status and organisation" do
expect(user.logs_filters).to eq(%w[status years user organisation]) expect(user.logs_filters).to eq(%w[status years user organisation bulk_upload_id])
end end
end end

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

@ -6,7 +6,7 @@ RSpec.describe Validations::Sales::FinancialValidations do
let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } } let(:validator_class) { Class.new { include Validations::Sales::FinancialValidations } }
describe "income validations" do describe "income validations" do
let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1) } let(:record) { FactoryBot.create(:sales_log, ownershipsch: 1, la: "E08000035") }
context "with shared ownership" do context "with shared ownership" do
context "and non london borough" do context "and non london borough" do
@ -17,6 +17,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]) expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000)) .to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["ecstat1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["ownershipsch"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["la"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
expect(record.errors["postcode_full"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 80_000))
end end
end end
@ -25,6 +33,10 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.ecstat1 = 1 record.ecstat1 = 1
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty expect(record.errors["income1"]).to be_empty
expect(record.errors["ecstat1"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
expect(record.errors["la"]).to be_empty
expect(record.errors["postcode_full"]).to be_empty
end end
end end
@ -41,6 +53,14 @@ RSpec.describe Validations::Sales::FinancialValidations do
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]) expect(record.errors["income1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000)) .to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["ecstat1"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["ownershipsch"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["la"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
expect(record.errors["postcode_full"])
.to include(match I18n.t("validations.financial.income1.over_hard_max", hard_max: 90_000))
end end
end end
@ -49,6 +69,10 @@ RSpec.describe Validations::Sales::FinancialValidations do
record.ecstat1 = 1 record.ecstat1 = 1
financial_validator.validate_income1(record) financial_validator.validate_income1(record)
expect(record.errors["income1"]).to be_empty expect(record.errors["income1"]).to be_empty
expect(record.errors["ecstat1"]).to be_empty
expect(record.errors["ownershipsch"]).to be_empty
expect(record.errors["la"]).to be_empty
expect(record.errors["postcode_full"]).to be_empty
end end
end end
end end

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

@ -371,4 +371,61 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end end
end end
end end
describe "#validate_basic_monthly_rent" do
context "when within permitted bounds" do
let(:record) { build(:sales_log, mrent: 9998, ownershipsch: 1, type: 2) }
it "does not add an error" do
sale_information_validator.validate_basic_monthly_rent(record)
expect(record.errors[:mrent]).not_to be_present
expect(record.errors[:type]).not_to be_present
end
end
context "when the rent is blank" do
let(:record) { build(:sales_log, mrent: nil, ownershipsch: 1, type: 2) }
it "does not add an error" do
sale_information_validator.validate_basic_monthly_rent(record)
expect(record.errors[:mrent]).not_to be_present
expect(record.errors[:type]).not_to be_present
end
end
context "when the type is old persons shared ownership" do
let(:record) { build(:sales_log, mrent: 100_000, ownershipsch: 1, type: 24) }
it "does not add an error" do
sale_information_validator.validate_basic_monthly_rent(record)
expect(record.errors[:mrent]).not_to be_present
expect(record.errors[:type]).not_to be_present
end
end
context "when the type is blank" do
let(:record) { build(:sales_log, mrent: 100_000, ownershipsch: 1, type: nil) }
it "does not add an error" do
sale_information_validator.validate_basic_monthly_rent(record)
expect(record.errors[:mrent]).not_to be_present
expect(record.errors[:type]).not_to be_present
end
end
context "when higher than upper bound" do
let(:record) { build(:sales_log, mrent: 100_000, ownershipsch: 1, type: 2) }
it "adds an error" do
sale_information_validator.validate_basic_monthly_rent(record)
expect(record.errors[:mrent]).to include(I18n.t("validations.sale_information.monthly_rent.higher_than_expected"))
expect(record.errors[:type]).to include(I18n.t("validations.sale_information.monthly_rent.higher_than_expected"))
end
end
end
end end

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

@ -321,6 +321,110 @@ RSpec.describe Validations::Sales::SoftValidations do
.not_to be_deposit_over_soft_max .not_to be_deposit_over_soft_max
end end
end end
context "when validating shared ownership deposit" do
it "returns false if MORTGAGE + DEPOSIT + CASHDIS are equal VALUE * EQUITY/100" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if mortgage is used and no mortgage is given" do
record.mortgage = nil
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if mortgage is not used and no mortgage is given" do
record.mortgage = nil
record.mortgageused = 2
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
it "returns false if no deposit is given" do
record.mortgage = 1000
record.deposit = nil
record.cashdis = 1000
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if no cashdis is given and cashdis is routed to" do
record.mortgage = 1000
record.deposit = 1000
record.type = 18
record.cashdis = nil
record.value = 3000
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if no cashdis is given and cashdis is not routed to" do
record.mortgage = 1000
record.deposit = 1000
record.type = 2
record.cashdis = nil
record.value = 3000
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
it "returns false if no value is given" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = nil
record.equity = 100
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns false if no equity is given" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 3000
record.equity = nil
expect(record)
.not_to be_shared_ownership_deposit_invalid
end
it "returns true if MORTGAGE + DEPOSIT + CASHDIS are not equal VALUE * EQUITY/100" do
record.mortgage = 1000
record.deposit = 1000
record.cashdis = 1000
record.value = 4323
record.equity = 100
expect(record)
.to be_shared_ownership_deposit_invalid
end
end
end end
describe "hodate_more_than_3_years_before_exdate" do describe "hodate_more_than_3_years_before_exdate" do

103
spec/requests/lettings_logs_controller_spec.rb

@ -400,6 +400,109 @@ RSpec.describe LettingsLogsController, type: :request do
expect(page).not_to have_link(lettings_log_2022.id.to_s) expect(page).not_to have_link(lettings_log_2022.id.to_s)
end end
end end
context "with bulk_upload_id filter" do
context "with bulk upload that belongs to current user" do
let(:organisation) { create(:organisation) }
let(:user) { create(:user, organisation:) }
let(:bulk_upload) { create(:bulk_upload, user:) }
let!(:included_log) { create(:lettings_log, :in_progress, bulk_upload:, owning_organisation: organisation) }
let!(:excluded_log) { create(:lettings_log, :in_progress, owning_organisation: organisation) }
it "returns logs only associated with the bulk upload" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).to have_content(included_log.id)
expect(page).not_to have_content(excluded_log.id)
end
it "dislays how many logs remaining to fix" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).to have_content("You need to fix 1 log")
end
it "displays filter" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).to have_content("With logs from bulk upload")
end
it "hides collection year filter" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).not_to have_content("Collection year")
end
it "hides status filter" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).not_to have_content("Status")
end
it "hides button to create a new log" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).not_to have_content("Create a new lettings log")
end
it "displays card with help info" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).to have_content("The following logs are from your recent bulk upload")
end
it "displays meta info about the bulk upload" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).to have_content(bulk_upload.filename)
expect(page).to have_content(bulk_upload.created_at.to_fs(:govuk_date_and_time))
end
end
context "with bulk upload that belongs to another user" do
let(:organisation) { create(:organisation) }
let(:user) { create(:user, organisation:) }
let(:other_user) { create(:user, organisation:) }
let(:bulk_upload) { create(:bulk_upload, user: other_user) }
let!(:excluded_log) { create(:lettings_log, bulk_upload:, owning_organisation: organisation) }
let!(:also_excluded_log) { create(:lettings_log, owning_organisation: organisation) }
it "does not return any logs" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(page).not_to have_content(excluded_log.id)
expect(page).not_to have_content(also_excluded_log.id)
end
end
context "when bulk upload has been resolved" do
let(:organisation) { create(:organisation) }
let(:user) { create(:user, organisation:) }
let(:bulk_upload) { create(:bulk_upload, user:) }
it "redirects to resume the bulk upload" do
get "/lettings-logs?bulk_upload_id[]=#{bulk_upload.id}"
expect(response).to redirect_to(resume_bulk_upload_lettings_result_path(bulk_upload))
end
end
end
context "without bulk_upload_id" do
it "does not display filter" do
get "/lettings-logs"
expect(page).not_to have_content("With logs from bulk upload")
end
it "displays button to create a new log" do
get "/lettings-logs"
expect(page).to have_content("Create a new lettings log")
end
it "does not display card with help info" do
get "/lettings-logs"
expect(page).not_to have_content("The following logs are from your recent bulk upload")
end
end
end end
end end

9
spec/services/bulk_upload/lettings/validator_spec.rb

@ -43,7 +43,14 @@ RSpec.describe BulkUpload::Lettings::Validator do
validator.call validator.call
error = BulkUploadError.first error = BulkUploadError.first
expect(error.row).to eq("7")
expect(error.field).to eql("field_96")
expect(error.error).to eql("blank")
expect(error.tenant_code).to eql("123")
expect(error.property_ref).to be_nil
expect(error.row).to eql("7")
expect(error.cell).to eql("CS7")
expect(error.col).to eql("CS")
end end
end end

34
spec/support/bulk_upload/log_to_csv.rb

@ -159,12 +159,7 @@ class BulkUpload::LogToCsv
end end
def renewal def renewal
case log.renewal checkbox_value(log.renewal)
when 1
1
when 0
2
end
end end
def london_affordable_rent def london_affordable_rent
@ -210,12 +205,7 @@ class BulkUpload::LogToCsv
end end
def previous_postcode_known def previous_postcode_known
case log.ppcodenk checkbox_value(log.ppcodenk)
when 1
1
when 0
2
end
end end
def homeless def homeless
@ -228,25 +218,19 @@ class BulkUpload::LogToCsv
end end
def cbl def cbl
case log.cbl checkbox_value(log.cbl)
when 0
2
when 1
1
end
end end
def chr def chr
case log.chr checkbox_value(log.chr)
when 0
2
when 1
1
end
end end
def cap def cap
case log.cap checkbox_value(log.cap)
end
def checkbox_value(field)
case field
when 0 when 0
2 2
when 1 when 1

Loading…
Cancel
Save