Browse Source

Merge branch 'main' into CLDC-3351-clear-deposit-when-switched-from-inferred-to-question

pull/2354/head
Robert Sullivan 2 years ago committed by GitHub
parent
commit
2c2895b11a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      app/controllers/form_controller.rb
  2. 8
      app/models/form/lettings/questions/reason.rb
  3. 8
      app/models/form/lettings/questions/reason_renewal.rb
  4. 14
      app/models/validations/sales/sale_information_validations.rb
  5. 2
      app/views/form/guidance/_finding_location.erb
  6. 2
      app/views/schemes/changes.html.erb
  7. 3
      config/locales/en.yml
  8. 8
      spec/models/form/lettings/questions/reason_renewal_spec.rb
  9. 8
      spec/models/form/lettings/questions/reason_spec.rb
  10. 88
      spec/models/validations/sales/sale_information_validations_spec.rb
  11. 104
      spec/requests/form_controller_spec.rb
  12. 2
      spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

4
app/controllers/form_controller.rb

@ -250,7 +250,9 @@ private
def check_collection_period def check_collection_period
return unless @log return unless @log
redirect_to lettings_log_path(@log) unless @log.collection_period_open_for_editing? unless @log.collection_period_open_for_editing?
redirect_to @log.lettings? ? lettings_log_path(@log) : sales_log_path(@log)
end
end end
CONFIRMATION_PAGE_IDS = %w[uprn_confirmation uprn_selection].freeze CONFIRMATION_PAGE_IDS = %w[uprn_confirmation uprn_selection].freeze

8
app/models/form/lettings/questions/reason.rb

@ -18,10 +18,10 @@ class Form::Lettings::Questions::Reason < ::Form::Question
def answer_options def answer_options
if form.start_year_after_2024? if form.start_year_after_2024?
{ {
"50" => { "value" => "End of social housing tenancy - no fault" }, "50" => { "value" => "End of social or private sector tenancy - no fault" },
"51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, "51" => { "value" => "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)" },
"52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, "52" => { "value" => "End of social or private sector tenancy - evicted due to rent arrears" },
"53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, "53" => { "value" => "End of social or private sector tenancy - evicted for any other reason" },
"1" => { "value" => "Permanently decanted from another property owned by this landlord" }, "1" => { "value" => "Permanently decanted from another property owned by this landlord" },
"2" => { "value" => "Left home country as a refugee" }, "2" => { "value" => "Left home country as a refugee" },
"45" => { "value" => "Discharged from prison" }, "45" => { "value" => "Discharged from prison" },

8
app/models/form/lettings/questions/reason_renewal.rb

@ -18,10 +18,10 @@ class Form::Lettings::Questions::ReasonRenewal < ::Form::Question
def answer_options def answer_options
if form.start_year_after_2024? if form.start_year_after_2024?
{ {
"50" => { "value" => "End of social housing tenancy - no fault" }, "50" => { "value" => "End of social or private sector tenancy - no fault" },
"51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, "51" => { "value" => "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)" },
"52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, "52" => { "value" => "End of social or private sector tenancy - evicted due to rent arrears" },
"53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, "53" => { "value" => "End of social or private sector tenancy - evicted for any other reason" },
"20" => { "value" => "Other" }, "20" => { "value" => "Other" },
"47" => { "value" => "Tenant prefers not to say" }, "47" => { "value" => "Tenant prefers not to say" },
"divider" => { "value" => true }, "divider" => { "value" => true },

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

@ -54,6 +54,20 @@ module Validations::Sales::SaleInformationValidations
end end
end end
def validate_outright_sale_value_matches_mortgage_plus_deposit(record)
return unless record.saledate && record.form.start_year_after_2024?
return unless record.outright_sale?
return unless record.mortgage_used? && record.mortgage
return unless record.deposit && record.value
if over_tolerance?(record.mortgage_and_deposit_total, record.value, 1)
%i[mortgageused mortgage value deposit].each do |field|
record.errors.add field, I18n.t("validations.sale_information.outright_sale_value", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), value: record.field_formatted_as_currency("value"))
end
record.errors.add :ownershipsch, :skip_bu_error, message: I18n.t("validations.sale_information.outright_sale_value", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), value: record.field_formatted_as_currency("value"))
end
end
def validate_basic_monthly_rent(record) def validate_basic_monthly_rent(record)
return unless record.mrent && record.ownershipsch && record.type return unless record.mrent && record.ownershipsch && record.type

2
app/views/form/guidance/_finding_location.erb

@ -1,4 +1,4 @@
<%= govuk_details(summary_text: "What is a location?") do %> <%= govuk_details(summary_text: "What is a location?") do %>
<p class="govuk-body">A location is a postcode where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode.</p> <p class="govuk-body">A location is a postcode area where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode.</p>
<p class="govuk-body"><%= govuk_link_to("Read more about schemes and locations", scheme_changes_path) %></p> <p class="govuk-body"><%= govuk_link_to("Read more about schemes and locations", scheme_changes_path) %></p>
<% end %> <% end %>

2
app/views/schemes/changes.html.erb

@ -9,7 +9,7 @@
<p class="govuk-body">A supported housing scheme (also known as a ‘supported housing service’) provides shared or self-contained housing for a particular client group, for example younger or vulnerable people.</p> <p class="govuk-body">A supported housing scheme (also known as a ‘supported housing service’) provides shared or self-contained housing for a particular client group, for example younger or vulnerable people.</p>
<h2 class="govuk-heading-m">What is a location?</h2> <h2 class="govuk-heading-m">What is a location?</h2>
<p class="govuk-body">A location is a postcode where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode.</p> <p class="govuk-body">A location is a postcode area where supported housing is provided under a scheme. A scheme can have multiple locations, and a location can have multiple units at the same postcode.</p>
<h2 class="govuk-heading-m">How schemes have changed</h2> <h2 class="govuk-heading-m">How schemes have changed</h2>
<p class="govuk-body">We have restructured the way we group supported housing scheme data.</p> <p class="govuk-body">We have restructured the way we group supported housing scheme data.</p>

3
config/locales/en.yml

@ -554,7 +554,7 @@ en:
reason: reason:
not_internal_transfer: "Answer cannot be ‘permanently decanted from another property owned by this landlord’ as you told us the source of referral for this tenancy was not an internal transfer" not_internal_transfer: "Answer cannot be ‘permanently decanted from another property owned by this landlord’ as you told us the source of referral for this tenancy was not an internal transfer"
renewal_reason_needed: 'The reason for leaving must be "End of assured shorthold tenancy - no fault" or "End of fixed term tenancy - no fault" if the letting is a renewal' renewal_reason_needed: 'The reason for leaving must be "End of assured shorthold tenancy - no fault" or "End of fixed term tenancy - no fault" if the letting is a renewal'
renewal_reason_needed_2024: 'The reason for leaving must be "End of social housing tenancy - no fault", "End of social housing tenancy - evicted due to anti-social behaviour (ASB)", "End of social housing tenancy - evicted due to rent arrears" or "End of social housing tenancy - evicted for any other reason"' renewal_reason_needed_2024: 'The reason for leaving must be "End of social or private sector tenancy - no fault", "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)", "End of social or private sector tenancy - evicted due to rent arrears" or "End of social or private sector tenancy - evicted for any other reason"'
other_not_settled: "Please give the reason for the tenant leaving their last settled home. This is where they were living before they became homeless, were living in temporary accommodation or sleeping rough" other_not_settled: "Please give the reason for the tenant leaving their last settled home. This is where they were living before they became homeless, were living in temporary accommodation or sleeping rough"
condition_effects: condition_effects:
no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more" no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more"
@ -633,6 +633,7 @@ en:
previous_property_type: previous_property_type:
property_type_bedsit: "A bedsit cannot have more than 1 bedroom" property_type_bedsit: "A bedsit cannot have more than 1 bedroom"
discounted_ownership_value: "The mortgage, deposit, and grant when added together is %{mortgage_deposit_and_grant_total}, and the purchase purchase price times by the discount is %{value_with_discount}. These figures should be the same" discounted_ownership_value: "The mortgage, deposit, and grant when added together is %{mortgage_deposit_and_grant_total}, and the purchase purchase price times by the discount is %{value_with_discount}. These figures should be the same"
outright_sale_value: "The mortgage and deposit when added together is %{mortgage_and_deposit_total}, and the purchase price is %{value}. These figures should be the same."
monthly_rent: monthly_rent:
higher_than_expected: "Basic monthly rent must be between £0.00 and £9,999.00" higher_than_expected: "Basic monthly rent must be between £0.00 and £9,999.00"
grant: grant:

8
spec/models/form/lettings/questions/reason_renewal_spec.rb

@ -71,10 +71,10 @@ RSpec.describe Form::Lettings::Questions::ReasonRenewal, type: :model do
it "has the correct answer_options" do it "has the correct answer_options" do
expect(question.answer_options).to eq({ expect(question.answer_options).to eq({
"50" => { "value" => "End of social housing tenancy - no fault" }, "50" => { "value" => "End of social or private sector tenancy - no fault" },
"51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, "51" => { "value" => "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)" },
"52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, "52" => { "value" => "End of social or private sector tenancy - evicted due to rent arrears" },
"53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, "53" => { "value" => "End of social or private sector tenancy - evicted for any other reason" },
"20" => { "value" => "Other" }, "20" => { "value" => "Other" },
"47" => { "value" => "Tenant prefers not to say" }, "47" => { "value" => "Tenant prefers not to say" },
"divider" => { "value" => true }, "divider" => { "value" => true },

8
spec/models/form/lettings/questions/reason_spec.rb

@ -105,10 +105,10 @@ RSpec.describe Form::Lettings::Questions::Reason, type: :model do
it "has the correct answer_options" do it "has the correct answer_options" do
expect(question.answer_options).to eq({ expect(question.answer_options).to eq({
"50" => { "value" => "End of social housing tenancy - no fault" }, "50" => { "value" => "End of social or private sector tenancy - no fault" },
"51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, "51" => { "value" => "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)" },
"52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, "52" => { "value" => "End of social or private sector tenancy - evicted due to rent arrears" },
"53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, "53" => { "value" => "End of social or private sector tenancy - evicted for any other reason" },
"1" => { "value" => "Permanently decanted from another property owned by this landlord" }, "1" => { "value" => "Permanently decanted from another property owned by this landlord" },
"2" => { "value" => "Left home country as a refugee" }, "2" => { "value" => "Left home country as a refugee" },
"45" => { "value" => "Discharged from prison" }, "45" => { "value" => "Discharged from prison" },

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

@ -505,6 +505,94 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end end
end end
describe "#validate_outright_sale_value_matches_mortgage_plus_deposit" do
context "with a 2024 outright sale log" do
let(:record) { FactoryBot.build(:sales_log, value: 300_000, ownershipsch: 3, saledate: Time.zone.local(2024, 5, 1)) }
context "when a mortgage is used" do
before do
record.mortgageused = 1
end
context "and the mortgage plus deposit match the value" do
before do
record.mortgage = 200_000
record.deposit = 100_000
end
it "does not add errors" do
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
context "and the mortgage plus deposit don't match the value" do
before do
record.mortgage = 100_000
record.deposit = 100_000
end
it "adds errors" do
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors["mortgageused"]).to include("The mortgage and deposit when added together is £200,000.00, and the purchase price is £300,000.00. These figures should be the same.")
expect(record.errors["mortgage"]).to include("The mortgage and deposit when added together is £200,000.00, and the purchase price is £300,000.00. These figures should be the same.")
expect(record.errors["deposit"]).to include("The mortgage and deposit when added together is £200,000.00, and the purchase price is £300,000.00. These figures should be the same.")
expect(record.errors["value"]).to include("The mortgage and deposit when added together is £200,000.00, and the purchase price is £300,000.00. These figures should be the same.")
expect(record.errors["ownershipsch"]).to include("The mortgage and deposit when added together is £200,000.00, and the purchase price is £300,000.00. These figures should be the same.")
end
end
context "and deposit is not provided" do
before do
record.mortgage = 100_000
record.deposit = nil
end
it "does not add errors" do
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
context "and mortgage is not provided" do
before do
record.mortgage = nil
record.deposit = 100_000
end
it "does not add errors" do
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
end
end
context "with a 2024 log that is not an outright sale" do
let(:record) { FactoryBot.build(:sales_log, value: 300_000, ownershipsch: 2, saledate: Time.zone.local(2024, 5, 1)) }
it "does not add errors" do
record.mortgageused = 1
record.mortgage = 100_000
record.deposit = 100_000
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
context "with a 2023 outright sale log" do
let(:record) { FactoryBot.build(:sales_log, value: 300_000, ownershipsch: 3, saledate: Time.zone.local(2023, 5, 1)) }
it "does not add errors" do
record.mortgageused = 1
record.mortgage = 100_000
record.deposit = 100_000
sale_information_validator.validate_outright_sale_value_matches_mortgage_plus_deposit(record)
expect(record.errors).to be_empty
end
end
end
describe "#validate_basic_monthly_rent" do describe "#validate_basic_monthly_rent" do
context "when within permitted bounds" do context "when within permitted bounds" do
let(:record) { build(:sales_log, mrent: 9998, ownershipsch: 1, type: 2) } let(:record) { build(:sales_log, mrent: 9998, ownershipsch: 1, type: 2) }

104
spec/requests/form_controller_spec.rb

@ -358,6 +358,12 @@ RSpec.describe FormController, type: :request do
created_by: user, created_by: user,
) )
end end
let!(:sales_log) do
create(
:sales_log,
created_by: user,
)
end
before do before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false) allow(user).to receive(:need_two_factor_authentication?).and_return(false)
@ -612,6 +618,104 @@ RSpec.describe FormController, type: :request do
expect(page).to have_content("There is a problem") expect(page).to have_content("There is a problem")
end end
end end
context "when allow_future_form_use? is enabled" do
before do
allow(FeatureToggle).to receive(:allow_future_form_use?).and_return(true)
end
context "when the tenancy start date is out of the editable collection year" do
let(:page_id) { "tenancy_start_date" }
let(:params) do
{
id: lettings_log.id,
lettings_log: {
page: page_id,
"startdate(3i)" => 1,
"startdate(2i)" => 1,
"startdate(1i)" => 1,
},
}
end
it "redirects to the review page for the log" do
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params: params
follow_redirect!
follow_redirect!
follow_redirect!
expect(page).to have_content("Review lettings log")
end
end
context "when the sale date is out of the editable collection year" do
let(:page_id) { "completion_date" }
let(:params) do
{
id: sales_log.id,
sales_log: {
page: page_id,
"saledate(3i)" => 1,
"saledate(2i)" => 1,
"saledate(1i)" => 1,
},
}
end
it "redirects to the review page for the log" do
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params: params
follow_redirect!
follow_redirect!
follow_redirect!
expect(page).to have_content("Review sales log")
end
end
end
context "when allow_future_form_use? is disabled" do
before do
allow(FeatureToggle).to receive(:allow_future_form_use?).and_return(false)
end
context "when the tenancy start date is out of the editable collection year" do
let(:page_id) { "tenancy_start_date" }
let(:params) do
{
id: lettings_log.id,
lettings_log: {
page: page_id,
"startdate(3i)" => 1,
"startdate(2i)" => 1,
"startdate(1i)" => 1,
},
}
end
it "validates the date correctly" do
post "/lettings-logs/#{lettings_log.id}/#{page_id.dasherize}", params: params
expect(page).to have_content("There is a problem")
end
end
context "when the sale date is out of the editable collection year" do
let(:page_id) { "completion_date" }
let(:params) do
{
id: sales_log.id,
sales_log: {
page: page_id,
"saledate(3i)" => 1,
"saledate(2i)" => 1,
"saledate(1i)" => 1,
},
}
end
it "validates the date correctly" do
post "/sales-logs/#{sales_log.id}/#{page_id.dasherize}", params: params
expect(page).to have_content("There is a problem")
end
end
end
end end
context "with invalid organisation answers" do context "with invalid organisation answers" do

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

@ -1038,7 +1038,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
let(:attributes) { { bulk_upload:, field_98: "1", field_7: "1" } } let(:attributes) { { bulk_upload:, field_98: "1", field_7: "1" } }
it "is not permitted" do it "is not permitted" do
expect(parser.errors[:field_98]).to include('The reason for leaving must be "End of social housing tenancy - no fault", "End of social housing tenancy - evicted due to anti-social behaviour (ASB)", "End of social housing tenancy - evicted due to rent arrears" or "End of social housing tenancy - evicted for any other reason"') expect(parser.errors[:field_98]).to include('The reason for leaving must be "End of social or private sector tenancy - no fault", "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)", "End of social or private sector tenancy - evicted due to rent arrears" or "End of social or private sector tenancy - evicted for any other reason"')
end end
end end
end end

Loading…
Cancel
Save