From 9d80f6d245054408c012a99adc3357e1f2f3d614 Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Fri, 27 Jan 2023 09:03:16 +0000 Subject: [PATCH 1/6] Add max range to mortgage length (#1245) --- app/models/form/sales/questions/mortgage_length.rb | 1 + spec/models/form/sales/questions/mortgage_length_spec.rb | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/models/form/sales/questions/mortgage_length.rb b/app/models/form/sales/questions/mortgage_length.rb index 56a358f01..3f1603b75 100644 --- a/app/models/form/sales/questions/mortgage_length.rb +++ b/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?" @type = "numeric" @min = 0 + @max = 60 @width = 5 @suffix = " years" @hint_text = "You should round up to the nearest year. Value should not exceed 60 years." diff --git a/spec/models/form/sales/questions/mortgage_length_spec.rb b/spec/models/form/sales/questions/mortgage_length_spec.rb index e96a05174..0f3193244 100644 --- a/spec/models/form/sales/questions/mortgage_length_spec.rb +++ b/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 expect(question.min).to eq(0) end + + it "has correct max" do + expect(question.max).to eq(60) + end end From 8e084d0c61bd0c8aa306208d2fe5fa948825b2b2 Mon Sep 17 00:00:00 2001 From: Jack <113976590+bibblobcode@users.noreply.github.com> Date: Fri, 27 Jan 2023 09:03:27 +0000 Subject: [PATCH 2/6] Add more specs (#1243) --- .../models/form/sales/pages/buyer1_income_value_check_spec.rb | 4 ++++ spec/models/form/sales/pages/deposit_value_check_spec.rb | 4 ++++ spec/models/form/sales/pages/handover_date_check_spec.rb | 4 ++++ .../form/sales/pages/household_wheelchair_check_spec.rb | 4 ++++ spec/models/form/sales/pages/mortgage_value_check_spec.rb | 4 ++++ spec/models/form/sales/pages/retirement_value_check_spec.rb | 4 ++++ spec/models/form/sales/pages/savings_value_check_spec.rb | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb b/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb index 313708aaf..f770bd651 100644 --- a/spec/models/form/sales/pages/buyer1_income_value_check_spec.rb +++ b/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 + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end diff --git a/spec/models/form/sales/pages/deposit_value_check_spec.rb b/spec/models/form/sales/pages/deposit_value_check_spec.rb index 961a3b6ec..91e1cccc5 100644 --- a/spec/models/form/sales/pages/deposit_value_check_spec.rb +++ b/spec/models/form/sales/pages/deposit_value_check_spec.rb @@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::DepositValueCheck, type: :model do }, ]) end + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end diff --git a/spec/models/form/sales/pages/handover_date_check_spec.rb b/spec/models/form/sales/pages/handover_date_check_spec.rb index e7ad99c83..86c74fda6 100644 --- a/spec/models/form/sales/pages/handover_date_check_spec.rb +++ b/spec/models/form/sales/pages/handover_date_check_spec.rb @@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::HandoverDateCheck, type: :model do }, ]) end + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end diff --git a/spec/models/form/sales/pages/household_wheelchair_check_spec.rb b/spec/models/form/sales/pages/household_wheelchair_check_spec.rb index 5a6cb34f9..4eb6182d9 100644 --- a/spec/models/form/sales/pages/household_wheelchair_check_spec.rb +++ b/spec/models/form/sales/pages/household_wheelchair_check_spec.rb @@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::HouseholdWheelchairCheck, type: :model do }, ]) end + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end diff --git a/spec/models/form/sales/pages/mortgage_value_check_spec.rb b/spec/models/form/sales/pages/mortgage_value_check_spec.rb index bd6c0bdf5..d54e992f1 100644 --- a/spec/models/form/sales/pages/mortgage_value_check_spec.rb +++ b/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 end + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end + it "has correct depends_on" do expect(page.depends_on).to eq([ { diff --git a/spec/models/form/sales/pages/retirement_value_check_spec.rb b/spec/models/form/sales/pages/retirement_value_check_spec.rb index 9c04ef25c..f150e6663 100644 --- a/spec/models/form/sales/pages/retirement_value_check_spec.rb +++ b/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 + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end diff --git a/spec/models/form/sales/pages/savings_value_check_spec.rb b/spec/models/form/sales/pages/savings_value_check_spec.rb index d4334118d..80606afb5 100644 --- a/spec/models/form/sales/pages/savings_value_check_spec.rb +++ b/spec/models/form/sales/pages/savings_value_check_spec.rb @@ -30,4 +30,8 @@ RSpec.describe Form::Sales::Pages::SavingsValueCheck, type: :model do }, ]) end + + it "is interruption screen page" do + expect(page.interruption_screen?).to eq(true) + end end From 9513e1179d9bd5af2dd5a7d0e75552bddf4b5546 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Fri, 27 Jan 2023 09:31:40 +0000 Subject: [PATCH 3/6] CLDC-1764 Bulk upload filter (#1223) * refactor with extract method * can filter logs by bulk upload * hide log creation button when viewing bulk upload - this affects the logs index page filtering logs from a specific bulk upload * add info banner to bulk upload logs * placeholder for bulk upload logs header * when resuming bulk upload set filters * fill place holder with remaining logs to fix * add interstitial to resume if logs resolved * after resolving bulk upload logs show interstitial * fix linting error * extract view variable to helper method --- ...bulk_upload_lettings_results_controller.rb | 28 +++++ app/controllers/lettings_logs_controller.rb | 14 +++ app/controllers/modules/logs_filter.rb | 4 +- app/helpers/logs_helper.rb | 5 + app/models/log.rb | 4 + app/models/user.rb | 4 +- .../resume.html.erb | 11 ++ app/views/logs/_log_filters.erb | 54 +++++++-- app/views/logs/index.html.erb | 62 ++++++++--- config/routes.rb | 6 +- ...upload_lettings_results_controller_spec.rb | 68 ++++++++++++ spec/models/user_spec.rb | 6 +- .../requests/lettings_logs_controller_spec.rb | 103 ++++++++++++++++++ spec/support/bulk_upload/log_to_csv.rb | 34 ++---- 14 files changed, 344 insertions(+), 59 deletions(-) create mode 100644 app/views/bulk_upload_lettings_results/resume.html.erb create mode 100644 spec/controllers/bulk_upload_lettings_results_controller_spec.rb diff --git a/app/controllers/bulk_upload_lettings_results_controller.rb b/app/controllers/bulk_upload_lettings_results_controller.rb index a0a962b3e..1c5342cd8 100644 --- a/app/controllers/bulk_upload_lettings_results_controller.rb +++ b/app/controllers/bulk_upload_lettings_results_controller.rb @@ -6,4 +6,32 @@ class BulkUploadLettingsResultsController < ApplicationController def show @bulk_upload = current_user.bulk_uploads.lettings.find(params[:id]) 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 diff --git a/app/controllers/lettings_logs_controller.rb b/app/controllers/lettings_logs_controller.rb index e7d233f87..a7bc2dc56 100644 --- a/app/controllers/lettings_logs_controller.rb +++ b/app/controllers/lettings_logs_controller.rb @@ -3,6 +3,9 @@ class LettingsLogsController < LogsController before_action :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 respond_to do |format| format.html do @@ -109,6 +112,17 @@ class LettingsLogsController < LogsController 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 params.require(:lettings_log).permit(LettingsLog.editable_fields) end diff --git a/app/controllers/modules/logs_filter.rb b/app/controllers/modules/logs_filter.rb index 7c60bb027..06109cfb0 100644 --- a/app/controllers/modules/logs_filter.rb +++ b/app/controllers/modules/logs_filter.rb @@ -7,7 +7,9 @@ module Modules::LogsFilter def load_session_filters(specific_org: false) current_filters = session[:logs_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 end diff --git a/app/helpers/logs_helper.rb b/app/helpers/logs_helper.rb index 6567f0a13..88ab2b314 100644 --- a/app/helpers/logs_helper.rb +++ b/app/helpers/logs_helper.rb @@ -18,4 +18,9 @@ module LogsHelper bulk_upload_sales_log_path(id:) 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 diff --git a/app/models/log.rb b/app/models/log.rb index 3217251b1..fcde08bdb 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -24,6 +24,10 @@ class Log < ApplicationRecord where(created_by: user) 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) } def collection_start_year diff --git a/app/models/user.rb b/app/models/user.rb index 04a545584..4d2aeeca1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -145,9 +145,9 @@ class User < ApplicationRecord def logs_filters(specific_org: false) if (support? && !specific_org) || organisation.has_managing_agents? - %w[status years user organisation] + %w[status years user organisation bulk_upload_id] else - %w[status years user] + %w[status years user bulk_upload_id] end end diff --git a/app/views/bulk_upload_lettings_results/resume.html.erb b/app/views/bulk_upload_lettings_results/resume.html.erb new file mode 100644 index 000000000..a5af1bd9d --- /dev/null +++ b/app/views/bulk_upload_lettings_results/resume.html.erb @@ -0,0 +1,11 @@ +
+
+

There are no more logs that need updating

+
+
+ +

+ You’ve completed all the logs that had errors from your bulk upload. +

+ +<%= govuk_button_link_to "Back to all logs", lettings_logs_path, button: true %> diff --git a/app/views/logs/_log_filters.erb b/app/views/logs/_log_filters.erb index d2a327d99..8fb4f2ba4 100644 --- a/app/views/logs/_log_filters.erb +++ b/app/views/logs/_log_filters.erb @@ -3,13 +3,48 @@

Filters

+
<%= form_with html: { method: :get } do |f| %> - <% years = {"2021": "2021/22", "2022": "2022/23"} %> - <% 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" } %> - <%= render partial: "filters/radio_filter", locals: { f: f, options: all_or_yours, label: "Logs", category: "user", } %> + <% years = { "2021": "2021/22", "2022": "2022/23" } %> + <% all_or_yours = { "all": { label: "All" }, "yours": { label: "Yours" } } %> + + <% if bulk_upload_options(@bulk_upload).present? %> + <%= 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" %> <%= render partial: "filters/radio_filter", locals: { f: f, @@ -21,14 +56,15 @@ type: "select", label: "Organisation", category: "organisation", - options: organisations_filter_options(@current_user) - } - } + options: organisations_filter_options(@current_user), + }, + }, }, label: "Organisation", - category: "organisation_select" + category: "organisation_select", } %> <% end %> + <%= f.govuk_submit "Apply filters", class: "govuk-!-margin-bottom-0" %> <% end %>
diff --git a/app/views/logs/index.html.erb b/app/views/logs/index.html.erb index 3f0d2031d..31768c731 100644 --- a/app/views/logs/index.html.erb +++ b/app/views/logs/index.html.erb @@ -11,32 +11,58 @@ title_id: "impacted-logs-banner", ) do |notification_banner| %> <% notification_banner.heading(text: "A scheme has changed and it has affected #{@unresolved_count} #{'log'.pluralize(@unresolved_count)}") %> -
- <%= govuk_link_to "Update logs", update_logs_lettings_logs_path, class: "govuk-notification-banner__link" %> -
- <% end %> +
+ <%= govuk_link_to "Update logs", update_logs_lettings_logs_path, class: "govuk-notification-banner__link" %> +
<% end %> - <%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Lettings logs", sub: nil } : { main: "Lettings logs", sub: current_user.organisation.name } %> -<% 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 %> -
-
- <% 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 @bulk_upload.blank? %> + <%= 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 } %> +<% else %> + <%= render partial: "organisations/headings", + 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') %> - <%= govuk_button_to "Create a new sales log", sales_logs_path, class: "govuk-!-margin-right-6" %> - <% end %> +
+
+
+

+ 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. +

- <% 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 %> +

+ Bulk Upload details:
+ <%= @bulk_upload.filename %>
+ Uploaded on <%= @bulk_upload.created_at.to_fs(:govuk_date_and_time) %>
+

+
+
+<% end %> + +
+ <% unless @bulk_upload %> +
+ <% 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 %> +
+ <% end %> <%= render partial: "log_filters" %> +
<%= 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") %> diff --git a/config/routes.rb b/config/routes.rb index 4e5b224c1..913212dd2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -134,7 +134,11 @@ Rails.application.routes.draw do 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" end diff --git a/spec/controllers/bulk_upload_lettings_results_controller_spec.rb b/spec/controllers/bulk_upload_lettings_results_controller_spec.rb new file mode 100644 index 000000000..7fb50a76a --- /dev/null +++ b/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 diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9244ad7e5..b285a55e7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -123,7 +123,7 @@ RSpec.describe User, type: :model do end 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 @@ -133,7 +133,7 @@ RSpec.describe User, type: :model do end 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 @@ -159,7 +159,7 @@ RSpec.describe User, type: :model do end 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 diff --git a/spec/requests/lettings_logs_controller_spec.rb b/spec/requests/lettings_logs_controller_spec.rb index 9565f08ec..1bb0afbf9 100644 --- a/spec/requests/lettings_logs_controller_spec.rb +++ b/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) 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 diff --git a/spec/support/bulk_upload/log_to_csv.rb b/spec/support/bulk_upload/log_to_csv.rb index 3b49f0b86..7734d9fe2 100644 --- a/spec/support/bulk_upload/log_to_csv.rb +++ b/spec/support/bulk_upload/log_to_csv.rb @@ -159,12 +159,7 @@ class BulkUpload::LogToCsv end def renewal - case log.renewal - when 1 - 1 - when 0 - 2 - end + checkbox_value(log.renewal) end def london_affordable_rent @@ -210,12 +205,7 @@ class BulkUpload::LogToCsv end def previous_postcode_known - case log.ppcodenk - when 1 - 1 - when 0 - 2 - end + checkbox_value(log.ppcodenk) end def homeless @@ -228,25 +218,19 @@ class BulkUpload::LogToCsv end def cbl - case log.cbl - when 0 - 2 - when 1 - 1 - end + checkbox_value(log.cbl) end def chr - case log.chr - when 0 - 2 - when 1 - 1 - end + checkbox_value(log.chr) end def cap - case log.cap + checkbox_value(log.cap) + end + + def checkbox_value(field) + case field when 0 2 when 1 From d65b18d48f04bceb1d770410cd75ab3462b07edf Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Mon, 30 Jan 2023 09:30:26 +0000 Subject: [PATCH 4/6] persist column for bulk upload errors (#1239) --- app/services/bulk_upload/lettings/validator.rb | 1 + .../20230126145529_add_column_to_bulk_upload_errors.rb | 5 +++++ db/schema.rb | 3 ++- spec/services/bulk_upload/lettings/validator_spec.rb | 9 ++++++++- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20230126145529_add_column_to_bulk_upload_errors.rb diff --git a/app/services/bulk_upload/lettings/validator.rb b/app/services/bulk_upload/lettings/validator.rb index 8cfdee684..b96739836 100644 --- a/app/services/bulk_upload/lettings/validator.rb +++ b/app/services/bulk_upload/lettings/validator.rb @@ -164,6 +164,7 @@ class BulkUpload::Lettings::Validator property_ref: row_parser.field_100, 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 diff --git a/db/migrate/20230126145529_add_column_to_bulk_upload_errors.rb b/db/migrate/20230126145529_add_column_to_bulk_upload_errors.rb new file mode 100644 index 000000000..437b5f2cd --- /dev/null +++ b/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 diff --git a/db/schema.rb b/db/schema.rb index 8722ec6a4..fc060fc47 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_23_160741) 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 enable_extension "plpgsql" @@ -25,6 +25,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_23_160741) do t.text "error" t.datetime "created_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" end diff --git a/spec/services/bulk_upload/lettings/validator_spec.rb b/spec/services/bulk_upload/lettings/validator_spec.rb index e242858bf..661119448 100644 --- a/spec/services/bulk_upload/lettings/validator_spec.rb +++ b/spec/services/bulk_upload/lettings/validator_spec.rb @@ -43,7 +43,14 @@ RSpec.describe BulkUpload::Lettings::Validator do validator.call 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 From 2787815a9d0854f7483a2a0868b332ab0db9c22f Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Mon, 30 Jan 2023 09:54:40 +0000 Subject: [PATCH 5/6] CLDC-878 Validate basic monthly rent (#1228) * Validate basic monthly rent * Make the test description clearer --- app/models/sales_log.rb | 4 ++ .../sales/sale_information_validations.rb | 9 +++ config/locales/en.yml | 2 + .../sale_information_validations_spec.rb | 57 +++++++++++++++++++ 4 files changed, 72 insertions(+) diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb index aa3eb1c09..a9e8b807e 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -211,4 +211,8 @@ class SalesLog < Log def old_persons_shared_ownership? type == 24 end + + def shared_owhership_scheme? + ownershipsch == 1 + end end diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index c42c42ccc..53d76fd48 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -54,4 +54,13 @@ module Validations::Sales::SaleInformationValidations 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 diff --git a/config/locales/en.yml b/config/locales/en.yml index 3dd612e8e..67a819e52 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -426,6 +426,8 @@ en: previous_property_type: property_type_bedsit: "A bedsit can not have more than 1 bedroom" 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: net_income: diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index d2921e8f0..8783efd09 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -371,4 +371,61 @@ RSpec.describe Validations::Sales::SaleInformationValidations do 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 From 7bd76c4d32704b866d3c5afd6c64cf917b5e00b2 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Mon, 30 Jan 2023 10:40:17 +0000 Subject: [PATCH 6/6] CLDC-1575 Add shared ownership validations (#1217) * Add income error to ownership type and ecstat fields * Add shared_ownership_deposit_value_check field * Add shared_ownership_deposit_invalid? soft validation * Add shared ownership deposit check pages and questions * Add pages to the subsection and update validation message * tests * Update validation to only trigger if la is given * Run the soft validation when mortgage isn't used or cash discount isn't given * test --- .../shared_ownership_deposit_value_check.rb | 27 +++++ .../shared_ownership_deposit_value_check.rb | 23 ++++ .../subsections/shared_ownership_scheme.rb | 5 +- app/models/sales_log.rb | 6 + .../sales/financial_validations.rb | 10 +- .../validations/sales/soft_validations.rb | 10 ++ config/locales/en.yml | 2 + ...dd_shared_ownership_deposit_value_check.rb | 7 ++ db/schema.rb | 1 + ...ared_ownership_deposit_value_check_spec.rb | 50 +++++++++ ...ared_ownership_deposit_value_check_spec.rb | 61 ++++++++++ .../shared_ownership_scheme_spec.rb | 3 + spec/models/form_handler_spec.rb | 4 +- spec/models/sales_log_spec.rb | 8 ++ .../sales/financial_validations_spec.rb | 26 ++++- .../sales/soft_validations_spec.rb | 104 ++++++++++++++++++ 16 files changed, 342 insertions(+), 5 deletions(-) create mode 100644 app/models/form/sales/pages/shared_ownership_deposit_value_check.rb create mode 100644 app/models/form/sales/questions/shared_ownership_deposit_value_check.rb create mode 100644 db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb create mode 100644 spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb create mode 100644 spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb diff --git a/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb b/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb new file mode 100644 index 000000000..907968028 --- /dev/null +++ b/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 diff --git a/app/models/form/sales/questions/shared_ownership_deposit_value_check.rb b/app/models/form/sales/questions/shared_ownership_deposit_value_check.rb new file mode 100644 index 000000000..3f8111881 --- /dev/null +++ b/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 diff --git a/app/models/form/sales/subsections/shared_ownership_scheme.rb b/app/models/form/sales/subsections/shared_ownership_scheme.rb index 8c05cd82d..e7ff1cf6e 100644 --- a/app/models/form/sales/subsections/shared_ownership_scheme.rb +++ b/app/models/form/sales/subsections/shared_ownership_scheme.rb @@ -21,15 +21,18 @@ class Form::Sales::Subsections::SharedOwnershipScheme < ::Form::Subsection Form::Sales::Pages::PreviousPropertyType.new(nil, nil, self), Form::Sales::Pages::PreviousTenure.new(nil, nil, self), Form::Sales::Pages::AboutPriceSharedOwnership.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::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::MortgageLenderOther.new("mortgage_lender_other_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::AboutDepositWithDiscount.new(nil, 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::LeaseholdCharges.new("leasehold_charges_shared_ownership", nil, self), ] diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb index a9e8b807e..daea6f060 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -159,6 +159,12 @@ class SalesLog < Log 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) return if postcode.blank? diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb index 116ecf301..233f32b6b 100644 --- a/app/models/validations/sales/financial_validations.rb +++ b/app/models/validations/sales/financial_validations.rb @@ -3,11 +3,19 @@ module Validations::Sales::FinancialValidations # or 'validate_' to run on submit as well 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? 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 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 diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb index 742e505a5..4ae681922 100644 --- a/app/models/validations/sales/soft_validations.rb +++ b/app/models/validations/sales/soft_validations.rb @@ -43,6 +43,16 @@ module Validations::Sales::SoftValidations extrabor != 1 && mortgage + deposit > value - value * discount / 100 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 diff --git a/config/locales/en.yml b/config/locales/en.yml index 67a819e52..f9c84253e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -461,6 +461,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" 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_owhership_deposit: + title_text: "Mortgage, deposit and cash discount total should equal £%{expected_shared_ownership_deposit_value}" devise: two_factor_authentication: diff --git a/db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb b/db/migrate/20230123101256_add_shared_ownership_deposit_value_check.rb new file mode 100644 index 000000000..07efc5e4a --- /dev/null +++ b/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 diff --git a/db/schema.rb b/db/schema.rb index fc060fc47..4b5e65a4e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -507,6 +507,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_26_145529) do t.integer "hodate_check" t.integer "extrabor_value_check" 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 ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id" diff --git a/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb b/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb new file mode 100644 index 000000000..afe25f4d3 --- /dev/null +++ b/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 diff --git a/spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb b/spec/models/form/sales/questions/shared_ownership_deposit_value_check_spec.rb new file mode 100644 index 000000000..c33892f28 --- /dev/null +++ b/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 diff --git a/spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb b/spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb index 1cafa8072..d131bc605 100644 --- a/spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb +++ b/spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb @@ -27,14 +27,17 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipScheme, type: :model do previous_property_type shared_ownership_previous_tenure about_price_shared_ownership + shared_ownership_equity_value_check mortgage_used_shared_ownership mortgage_amount_shared_ownership + shared_ownership_mortgage_amount_value_check mortgage_lender_shared_ownership mortgage_lender_other_shared_ownership mortgage_length_shared_ownership extra_borrowing_shared_ownership about_deposit_with_discount about_deposit_shared_ownership + deposit_value_check shared_ownership_deposit_value_check monthly_rent leasehold_charges_shared_ownership diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index c7bfdc85b..e51d5ea59 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -52,14 +52,14 @@ RSpec.describe FormHandler do it "is able to load a current sales form" do form = form_handler.get_form("current_sales") expect(form).to be_a(Form) - expect(form.pages.count).to eq(188) + expect(form.pages.count).to eq(191) expect(form.name).to eq("2022_2023_sales") end it "is able to load a previous sales form" do form = form_handler.get_form("previous_sales") expect(form).to be_a(Form) - expect(form.pages.count).to eq(188) + expect(form.pages.count).to eq(191) expect(form.name).to eq("2021_2022_sales") end end diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb index ccfff433f..e49e56e01 100644 --- a/spec/models/sales_log_spec.rb +++ b/spec/models/sales_log_spec.rb @@ -339,4 +339,12 @@ RSpec.describe SalesLog, type: :model do expect(record_from_db["prevloc"]).to eq(nil) 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 diff --git a/spec/models/validations/sales/financial_validations_spec.rb b/spec/models/validations/sales/financial_validations_spec.rb index 7b5b8868b..4bc19afbe 100644 --- a/spec/models/validations/sales/financial_validations_spec.rb +++ b/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 } } 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 "and non london borough" do @@ -17,6 +17,14 @@ RSpec.describe Validations::Sales::FinancialValidations do financial_validator.validate_income1(record) expect(record.errors["income1"]) .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 @@ -25,6 +33,10 @@ RSpec.describe Validations::Sales::FinancialValidations do record.ecstat1 = 1 financial_validator.validate_income1(record) 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 @@ -41,6 +53,14 @@ RSpec.describe Validations::Sales::FinancialValidations do financial_validator.validate_income1(record) expect(record.errors["income1"]) .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 @@ -49,6 +69,10 @@ RSpec.describe Validations::Sales::FinancialValidations do record.ecstat1 = 1 financial_validator.validate_income1(record) 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 diff --git a/spec/models/validations/sales/soft_validations_spec.rb b/spec/models/validations/sales/soft_validations_spec.rb index da0ab8ed9..b0b253c15 100644 --- a/spec/models/validations/sales/soft_validations_spec.rb +++ b/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 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 describe "hodate_more_than_3_years_before_saledate" do