- <% 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 %>
+
+ <% 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/locales/en.yml b/config/locales/en.yml
index 09200918c..63f70771a 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -429,6 +429,8 @@ en:
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"
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:
@@ -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"
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/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/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/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 4bc410328..4b5e65a4e 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_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
enable_extension "plpgsql"
@@ -25,6 +25,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) 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
@@ -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
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|
t.string "old_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 "fromprop"
t.integer "socprevten"
+ t.integer "mortlen"
t.integer "mortgagelender"
t.string "mortgagelenderother"
- t.integer "mortlen"
t.integer "extrabor"
t.integer "hhmemb"
t.integer "totadult"
@@ -512,11 +502,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_24_111328) do
t.boolean "is_la_inferred"
t.bigint "bulk_upload_id"
t.integer "retirement_value_check"
+ t.integer "deposit_and_mortgage_value_check"
+ t.integer "grant_value_check"
t.integer "hodate_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.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/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/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 56f6ac4bd..e4643fb0d 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
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/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
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 96f14a97f..a4e236051 100644
--- a/spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
+++ b/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
about_price_shared_ownership
about_price_shared_ownership_value_check
+ 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 f31037f48..81c332757 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(189)
+ expect(form.pages.count).to eq(192)
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(189)
+ expect(form.pages.count).to eq(192)
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/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/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/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb
index 222023cd1..9823f8493 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
diff --git a/spec/models/validations/sales/soft_validations_spec.rb b/spec/models/validations/sales/soft_validations_spec.rb
index 13cc09125..7d0dd3b59 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_exdate" do
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/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
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