Browse Source

Merge branch 'main' into CLDC-850-demographic-details-relationship-validation

# Conflicts:
#	db/schema.rb
pull/1178/head
natdeanlewissoftwire 3 years ago
parent
commit
1b92694b36
  1. 8
      app/components/bulk_upload_error_row_component.rb
  2. 2
      app/components/log_summary_component.html.erb
  3. 4
      app/controllers/organisations_controller.rb
  4. 5
      app/helpers/filters_helper.rb
  5. 1
      app/models/derived_variables/sales_log_variables.rb
  6. 4
      app/models/form/sales/pages/about_deposit_without_discount.rb
  7. 1
      app/models/form/sales/pages/about_price_not_rtb.rb
  8. 17
      app/models/form/sales/pages/mortgage_lender.rb
  9. 17
      app/models/form/sales/pages/mortgage_lender_other.rb
  10. 7
      app/models/form/sales/pages/mortgage_length.rb
  11. 13
      app/models/form/sales/pages/postcode.rb
  12. 3
      app/models/form/sales/pages/property_local_authority.rb
  13. 5
      app/models/form/sales/pages/purchase_price.rb
  14. 5
      app/models/form/sales/questions/deposit_amount.rb
  15. 58
      app/models/form/sales/questions/mortgage_lender.rb
  16. 10
      app/models/form/sales/questions/mortgage_lender_other.rb
  17. 21
      app/models/form/sales/questions/postcode.rb
  18. 28
      app/models/form/sales/questions/postcode_known.rb
  19. 3
      app/models/form/sales/subsections/discounted_ownership_scheme.rb
  20. 4
      app/models/form/sales/subsections/outright_sale.rb
  21. 1
      app/models/form/sales/subsections/property_information.rb
  22. 2
      app/models/form/sales/subsections/shared_ownership_scheme.rb
  23. 4
      app/models/lettings_log.rb
  24. 4
      app/models/log.rb
  25. 4
      app/models/organisation.rb
  26. 23
      app/models/sales_log.rb
  27. 2
      app/models/user.rb
  28. 6
      app/models/validations/financial_validations.rb
  29. 8
      app/models/validations/property_validations.rb
  30. 8
      app/models/validations/shared_validations.rb
  31. 4
      app/services/bulk_upload/lettings/validator.rb
  32. 7
      app/views/form/guidance/_mortgage_lender.html.erb
  33. 4
      app/views/logs/_log_filters.erb
  34. 8
      db/migrate/20230109144039_add_mortgage_lender.rb
  35. 11
      db/migrate/20230113125117_add_postcode_fields_to_sales.rb
  36. 9
      db/schema.rb
  37. 16
      spec/components/bulk_upload_error_row_component_spec.rb
  38. 5
      spec/factories/sales_log.rb
  39. 35
      spec/helpers/filters_helper_spec.rb
  40. 4
      spec/models/form/sales/pages/about_deposit_without_discount_spec.rb
  41. 1
      spec/models/form/sales/pages/about_price_not_rtb_spec.rb
  42. 35
      spec/models/form/sales/pages/mortgage_lender_other_spec.rb
  43. 35
      spec/models/form/sales/pages/mortgage_lender_spec.rb
  44. 4
      spec/models/form/sales/pages/mortgage_length_spec.rb
  45. 33
      spec/models/form/sales/pages/postcode_spec.rb
  46. 6
      spec/models/form/sales/pages/property_local_authority_spec.rb
  47. 7
      spec/models/form/sales/pages/purchase_price_spec.rb
  48. 4
      spec/models/form/sales/questions/deposit_amount_spec.rb
  49. 37
      spec/models/form/sales/questions/mortgage_lender_other_spec.rb
  50. 88
      spec/models/form/sales/questions/mortgage_lender_spec.rb
  51. 59
      spec/models/form/sales/questions/postcode_known_spec.rb
  52. 58
      spec/models/form/sales/questions/postcode_spec.rb
  53. 3
      spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
  54. 4
      spec/models/form/sales/subsections/outright_sale_spec.rb
  55. 1
      spec/models/form/sales/subsections/property_information_spec.rb
  56. 2
      spec/models/form/sales/subsections/shared_ownership_scheme_spec.rb
  57. 4
      spec/models/form_handler_spec.rb
  58. 103
      spec/models/sales_log_spec.rb
  59. 20
      spec/models/user_spec.rb
  60. 6
      spec/models/validations/financial_validations_spec.rb
  61. 9
      spec/services/bulk_upload/lettings/validator_spec.rb

8
app/components/bulk_upload_error_row_component.rb

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

2
app/components/log_summary_component.html.erb

@ -36,7 +36,7 @@
</p> </p>
<% end %> <% end %>
<% if current_user.support? %> <% if current_user.support? || current_user.organisation.has_managing_agents? %>
<% if log.owning_organisation or log.managing_organisation %> <% if log.owning_organisation or log.managing_organisation %>
<dl class="app-metadata"> <dl class="app-metadata">
<div class="app-metadata__item"> <div class="app-metadata__item">

4
app/controllers/organisations_controller.rb

@ -6,8 +6,8 @@ class OrganisationsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :find_resource, except: %i[index new create] before_action :find_resource, except: %i[index new create]
before_action :authenticate_scope!, except: [:index] before_action :authenticate_scope!, except: [:index]
before_action -> { session_filters(specific_org: true) }, if: -> { current_user.support? } before_action -> { session_filters(specific_org: true) }, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }
before_action :set_session_filters, if: -> { current_user.support? } before_action :set_session_filters, if: -> { current_user.support? || current_user.organisation.has_managing_agents? }
def index def index
redirect_to organisation_path(current_user.organisation) unless current_user.support? redirect_to organisation_path(current_user.organisation) unless current_user.support?

5
app/helpers/filters_helper.rb

@ -22,4 +22,9 @@ module FiltersHelper
JSON.parse(session[:logs_filters])[filter] || "" JSON.parse(session[:logs_filters])[filter] || ""
end end
def organisations_filter_options(user)
organisation_options = user.support? ? Organisation.all : [user.organisation] + user.organisation.managing_agents
[OpenStruct.new(id: "", name: "Select an option")] + organisation_options.map { |org| OpenStruct.new(id: org.id, name: org.name) }
end
end end

1
app/models/derived_variables/sales_log_variables.rb

@ -15,5 +15,6 @@ module DerivedVariables::SalesLogVariables
if mscharge_known.present? && mscharge_known.zero? if mscharge_known.present? && mscharge_known.zero?
self.mscharge = 0 self.mscharge = 0
end end
self.pcode1, self.pcode2 = postcode_full.split(" ") if postcode_full.present?
end end
end end

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

@ -2,7 +2,9 @@ class Form::Sales::Pages::AboutDepositWithoutDiscount < ::Form::Page
def initialize(id, hsh, subsection) def initialize(id, hsh, subsection)
super super
@header = "About the deposit" @header = "About the deposit"
@depends_on = [{ "is_type_discount?" => false }] @depends_on = [{ "is_type_discount?" => false, "ownershipsch" => 1 },
{ "ownershipsch" => 2 },
{ "ownershipsch" => 3, "mortgageused" => 1 }]
end end
def questions def questions

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

@ -5,6 +5,7 @@ class Form::Sales::Pages::AboutPriceNotRtb < ::Form::Page
@header = "About the price of the property" @header = "About the price of the property"
@depends_on = [{ @depends_on = [{
"right_to_buy?" => false, "right_to_buy?" => false,
"rent_to_buy_full_ownership?" => false,
}] }]
end end

17
app/models/form/sales/pages/mortgage_lender.rb

@ -0,0 +1,17 @@
class Form::Sales::Pages::MortgageLender < ::Form::Page
def initialize(id, hsh, subsection)
super
@header = ""
@description = ""
@subsection = subsection
@depends_on = [{
"mortgageused" => 1,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::MortgageLender.new(nil, nil, self),
]
end
end

17
app/models/form/sales/pages/mortgage_lender_other.rb

@ -0,0 +1,17 @@
class Form::Sales::Pages::MortgageLenderOther < ::Form::Page
def initialize(id, hsh, subsection)
super
@header = ""
@description = ""
@subsection = subsection
@depends_on = [{
"mortgagelender" => 40,
}]
end
def questions
@questions ||= [
Form::Sales::Questions::MortgageLenderOther.new(nil, nil, self),
]
end
end

7
app/models/form/sales/pages/mortgage_length.rb

@ -1,4 +1,11 @@
class Form::Sales::Pages::MortgageLength < ::Form::Page class Form::Sales::Pages::MortgageLength < ::Form::Page
def initialize(id, hsh, subsection)
super
@depends_on = [{
"mortgageused" => 1,
}]
end
def questions def questions
@questions ||= [ @questions ||= [
Form::Sales::Questions::MortgageLength.new(nil, nil, self), Form::Sales::Questions::MortgageLength.new(nil, nil, self),

13
app/models/form/sales/pages/postcode.rb

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

3
app/models/form/sales/pages/property_local_authority.rb

@ -2,6 +2,9 @@ class Form::Sales::Pages::PropertyLocalAuthority < ::Form::Page
def initialize(id, hsh, subsection) def initialize(id, hsh, subsection)
super super
@id = "property_local_authority" @id = "property_local_authority"
@depends_on = [{
"is_la_inferred" => false,
}]
end end
def questions def questions

5
app/models/form/sales/pages/purchase_price.rb

@ -1,7 +1,10 @@
class Form::Sales::Pages::PurchasePrice < ::Form::Page class Form::Sales::Pages::PurchasePrice < ::Form::Page
def initialize(id, hsh, subsection) def initialize(id, hsh, subsection)
super super
@id = "purchase_price" @depends_on = [
{ "ownershipsch" => 3 },
{ "rent_to_buy_full_ownership?" => true },
]
end end
def questions def questions

5
app/models/form/sales/questions/deposit_amount.rb

@ -9,5 +9,10 @@ class Form::Sales::Questions::DepositAmount < ::Form::Question
@width = 5 @width = 5
@prefix = "£" @prefix = "£"
@hint_text = "Enter the total cash sum paid by the buyer towards the property that was not funded by the mortgage" @hint_text = "Enter the total cash sum paid by the buyer towards the property that was not funded by the mortgage"
@derived = true
end
def selected_answer_option_is_derived?(_log)
true
end end
end end

58
app/models/form/sales/questions/mortgage_lender.rb

@ -0,0 +1,58 @@
class Form::Sales::Questions::MortgageLender < ::Form::Question
def initialize(id, hsh, page)
super
@id = "mortgagelender"
@check_answer_label = "Mortgage Lender"
@header = "What is the name of the mortgage lender?"
@type = "select"
@hint_text = ""
@page = page
@answer_options = ANSWER_OPTIONS
@guidance_position = GuidancePosition::BOTTOM
@guidance_partial = "mortgage_lender"
end
ANSWER_OPTIONS = {
"" => "Select an option",
"1" => "Atom Bank",
"2" => "Barclays Bank PLC",
"3" => "Bath Building Society",
"4" => "Buckinghamshire Building Society",
"5" => "Cambridge Building Society",
"6" => "Coventry Building Society",
"7" => "Cumberland Building Society",
"8" => "Darlington Building Society",
"9" => "Dudley Building Society",
"10" => "Ecology Building Society",
"11" => "Halifax",
"12" => "Hanley Economic Building Society",
"13" => "Hinckley and Rugby Building Society",
"14" => "Holmesdale Building Society",
"15" => "Ipswich Building Society",
"16" => "Leeds Building Society",
"17" => "Lloyds Bank",
"18" => "Mansfield Building Society",
"19" => "Market Harborough Building Society",
"20" => "Melton Mowbray Building Society",
"21" => "Nationwide Building Society",
"22" => "Natwest",
"23" => "Nedbank Private Wealth",
"24" => "Newbury Building Society",
"25" => "OneSavings Bank",
"26" => "Parity Trust",
"27" => "Penrith Building Society",
"28" => "Pepper Homeloans",
"29" => "Royal Bank of Scotland",
"30" => "Santander",
"31" => "Skipton Building Society",
"32" => "Teachers Building Society",
"33" => "The Co-operative Bank",
"34" => "Tipton & Coseley Building Society",
"35" => "TSB",
"36" => "Ulster Bank",
"37" => "Virgin Money",
"38" => "West Bromwich Building Society",
"39" => "Yorkshire Building Society",
"40" => "Other",
}.freeze
end

10
app/models/form/sales/questions/mortgage_lender_other.rb

@ -0,0 +1,10 @@
class Form::Sales::Questions::MortgageLenderOther < ::Form::Question
def initialize(id, hsh, page)
super
@id = "mortgagelenderother"
@check_answer_label = "Other Mortgage Lender"
@header = "What is the other mortgage lender?"
@type = "text"
@page = page
end
end

21
app/models/form/sales/questions/postcode.rb

@ -0,0 +1,21 @@
class Form::Sales::Questions::Postcode < ::Form::Question
def initialize(id, hsh, page)
super
@id = "postcode_full"
@check_answer_label = "Property’s postcode"
@header = "Postcode"
@type = "text"
@width = 5
@inferred_check_answers_value = {
"condition" => {
"pcodenk" => 1,
},
"value" => "Not known",
}
@inferred_answers = {
"la" => {
"is_la_inferred" => true,
},
}
end
end

28
app/models/form/sales/questions/postcode_known.rb

@ -0,0 +1,28 @@
class Form::Sales::Questions::PostcodeKnown < ::Form::Question
def initialize(id, hsh, page)
super
@id = "pcodenk"
@check_answer_label = "Property’s postcode"
@header = "Do you know the property’s postcode?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@conditional_for = {
"postcode_full" => [0],
}
@hidden_in_check_answers = {
"depends_on" => [
{
"pcodenk" => 0,
},
{
"pcodenk" => 1,
},
],
}
end
ANSWER_OPTIONS = {
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
}.freeze
end

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

@ -11,8 +11,11 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::LivingBeforePurchase.new("living_before_purchase_discounted_ownership", nil, self), Form::Sales::Pages::LivingBeforePurchase.new("living_before_purchase_discounted_ownership", nil, self),
Form::Sales::Pages::AboutPriceRtb.new(nil, nil, self), Form::Sales::Pages::AboutPriceRtb.new(nil, nil, self),
Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self), Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self),
Form::Sales::Pages::PurchasePrice.new("purchase_price_discounted_ownership", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_discounted_ownership", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_discounted_ownership", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_discounted_ownership", nil, self),
Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_discounted_ownership", nil, self),
Form::Sales::Pages::MortgageLength.new("mortgage_length_discounted_ownership", nil, self), Form::Sales::Pages::MortgageLength.new("mortgage_length_discounted_ownership", nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_discounted_ownership", nil, self), Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_discounted_ownership", nil, self),
Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("discounted_ownership_deposit_value_check", nil, self),

4
app/models/form/sales/subsections/outright_sale.rb

@ -8,9 +8,11 @@ class Form::Sales::Subsections::OutrightSale < ::Form::Subsection
def pages def pages
@pages ||= [ @pages ||= [
Form::Sales::Pages::PurchasePrice.new(nil, nil, self), Form::Sales::Pages::PurchasePrice.new("purchase_price_outright_sale", nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_outright_sale", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_outright_sale", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_outright_sale", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_outright_sale", nil, self),
Form::Sales::Pages::MortgageLender.new("mortgage_lender_outright_sale", nil, self),
Form::Sales::Pages::MortgageLenderOther.new("mortgage_lender_other_outright_sale", nil, self),
Form::Sales::Pages::MortgageLength.new("mortgage_length_outright_sale", nil, self), Form::Sales::Pages::MortgageLength.new("mortgage_length_outright_sale", nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_outright_sale", nil, self), Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_outright_sale", nil, self),
Form::Sales::Pages::DepositValueCheck.new("outright_sale_deposit_value_check", nil, self), Form::Sales::Pages::DepositValueCheck.new("outright_sale_deposit_value_check", nil, self),

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

@ -11,6 +11,7 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
Form::Sales::Pages::PropertyNumberOfBedrooms.new(nil, nil, self), Form::Sales::Pages::PropertyNumberOfBedrooms.new(nil, nil, self),
Form::Sales::Pages::PropertyUnitType.new(nil, nil, self), Form::Sales::Pages::PropertyUnitType.new(nil, nil, self),
Form::Sales::Pages::PropertyBuildingType.new(nil, nil, self), Form::Sales::Pages::PropertyBuildingType.new(nil, nil, self),
Form::Sales::Pages::Postcode.new(nil, nil, self),
Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self), Form::Sales::Pages::PropertyLocalAuthority.new(nil, nil, self),
Form::Sales::Pages::PropertyWheelchairAccessible.new(nil, nil, self), Form::Sales::Pages::PropertyWheelchairAccessible.new(nil, nil, self),
] ]

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

@ -22,6 +22,8 @@ class Form::Sales::Subsections::SharedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self), Form::Sales::Pages::AboutPriceSharedOwnership.new(nil, nil, self),
Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self), Form::Sales::Pages::Mortgageused.new("mortgage_used_shared_ownership", nil, self),
Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self), Form::Sales::Pages::MortgageAmount.new("mortgage_amount_shared_ownership", nil, self),
Form::Sales::Pages::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::MortgageLength.new("mortgage_length_shared_ownership", nil, self),
Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self), Form::Sales::Pages::AboutDepositWithDiscount.new(nil, nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self), Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_shared_ownership", nil, self),

4
app/models/lettings_log.rb

@ -608,10 +608,6 @@ private
self[la_key] = inferred_la if inferred_la.present? self[la_key] = inferred_la if inferred_la.present?
end end
def reset_location_fields!
reset_location(is_la_inferred, "la", "is_la_inferred", "postcode_full", 1)
end
def get_has_benefits def get_has_benefits
HAS_BENEFITS_OPTIONS.include?(hb) ? 1 : 0 HAS_BENEFITS_OPTIONS.include?(hb) ? 1 : 0
end end

4
app/models/log.rb

@ -105,6 +105,10 @@ private
string.present? ? string.upcase.gsub(/\s+/, "") : string string.present? ? string.upcase.gsub(/\s+/, "") : string
end end
def reset_location_fields!
reset_location(is_la_inferred, "la", "is_la_inferred", "postcode_full", 1)
end
def reset_previous_location_fields! def reset_previous_location_fields!
reset_location(is_previous_la_inferred, "prevloc", "is_previous_la_inferred", "ppostcode_full", previous_la_known) reset_location(is_previous_la_inferred, "prevloc", "is_previous_la_inferred", "ppostcode_full", previous_la_known)
end end

4
app/models/organisation.rb

@ -92,4 +92,8 @@ class Organisation < ApplicationRecord
{ name: "Data protection agreement", value: data_protection_agreement_string, editable: false }, { name: "Data protection agreement", value: data_protection_agreement_string, editable: false },
].compact ].compact
end end
def has_managing_agents?
managing_agents.count.positive?
end
end end

23
app/models/sales_log.rb

@ -21,7 +21,9 @@ class SalesLog < Log
validates_with SalesLogValidator validates_with SalesLogValidator
before_validation :set_derived_fields! before_validation :set_derived_fields!
before_validation :reset_invalidated_dependent_fields! before_validation :reset_invalidated_dependent_fields!
before_validation :process_postcode_changes!, if: :postcode_full_changed?
before_validation :process_previous_postcode_changes!, if: :ppostcode_full_changed? before_validation :process_previous_postcode_changes!, if: :ppostcode_full_changed?
before_validation :reset_location_fields!, unless: :postcode_known?
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known? before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
scope :filter_by_year, ->(year) { where(saledate: Time.zone.local(year.to_i, 4, 1)...Time.zone.local(year.to_i + 1, 4, 1)) } scope :filter_by_year, ->(year) { where(saledate: Time.zone.local(year.to_i, 4, 1)...Time.zone.local(year.to_i + 1, 4, 1)) }
@ -119,6 +121,10 @@ class SalesLog < Log
[9, 14, 27].include?(type) [9, 14, 27].include?(type)
end end
def rent_to_buy_full_ownership?
type == 29
end
def is_type_discount? def is_type_discount?
type == 18 type == 18
end end
@ -135,6 +141,18 @@ class SalesLog < Log
ppcodenk&.zero? ppcodenk&.zero?
end end
def postcode_known?
pcodenk&.zero?
end
def postcode_full=(postcode)
if postcode
super UKPostcode.parse(postcode).to_s
else
super nil
end
end
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key) def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
return if postcode.blank? return if postcode.blank?
@ -151,4 +169,9 @@ class SalesLog < Log
def mortgage_not_used? def mortgage_not_used?
mortgageused == 2 mortgageused == 2
end end
def process_postcode_changes!
self.postcode_full = upcase_and_remove_whitespace(postcode_full)
process_postcode(postcode_full, "pcodenk", "is_la_inferred", "la")
end
end end

2
app/models/user.rb

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

6
app/models/validations/financial_validations.rb

@ -98,11 +98,11 @@ module Validations::FinancialValidations
end end
def validate_rent_period(record) def validate_rent_period(record)
if record.owning_organisation.present? && record.owning_organisation.rent_periods.present? && if record.managing_organisation.present? && record.managing_organisation.rent_periods.present? &&
record.period && !record.owning_organisation.rent_periods.include?(record.period) record.period && !record.managing_organisation.rent_periods.include?(record.period)
record.errors.add :period, I18n.t( record.errors.add :period, I18n.t(
"validations.financial.rent_period.invalid_for_org", "validations.financial.rent_period.invalid_for_org",
org_name: record.owning_organisation.name, org_name: record.managing_organisation.name,
rent_period: record.form.get_question("period", record).label_from_value(record.period).downcase, rent_period: record.form.get_question("period", record).label_from_value(record.period).downcase,
) )
end end

8
app/models/validations/property_validations.rb

@ -50,14 +50,6 @@ module Validations::PropertyValidations
end end
end end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.postcode")
record.errors.add :postcode_full, error_message
end
end
def validate_shared_housing_rooms(record) def validate_shared_housing_rooms(record)
if record.beds.present? && record.beds <= 0 if record.beds.present? && record.beds <= 0
record.errors.add :beds, I18n.t("validations.property.beds.non_positive") record.errors.add :beds, I18n.t("validations.property.beds.non_positive")

8
app/models/validations/shared_validations.rb

@ -34,6 +34,14 @@ module Validations::SharedValidations
end end
end end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.postcode")
record.errors.add :postcode_full, error_message
end
end
def location_during_startdate_validation(record, field) def location_during_startdate_validation(record, field)
location_inactive_status = inactive_status(record.startdate, record.location) location_inactive_status = inactive_status(record.startdate, record.location)

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

@ -154,7 +154,7 @@ class BulkUpload::Lettings::Validator
row_parsers.each_with_index do |row_parser, index| row_parsers.each_with_index do |row_parser, index|
row_parser.valid? row_parser.valid?
row = index + row_offset row = index + row_offset + 1
row_parser.errors.each do |error| row_parser.errors.each do |error|
bulk_upload.bulk_upload_errors.create!( bulk_upload.bulk_upload_errors.create!(
@ -163,7 +163,7 @@ class BulkUpload::Lettings::Validator
tenant_code: row_parser.field_7, tenant_code: row_parser.field_7,
property_ref: row_parser.field_100, property_ref: row_parser.field_100,
row:, row:,
cell: "#{cols[field_number_for_attribute(error.attribute) - col_offset + 1]}#{row + 1}", cell: "#{cols[field_number_for_attribute(error.attribute) - col_offset + 1]}#{row}",
) )
end end
end end

7
app/views/form/guidance/_mortgage_lender.html.erb

@ -0,0 +1,7 @@
<%= govuk_details(summary_text: "Can’t find the mortgage lender you’re looking for?") do %>
<ul class="govuk-list govuk-list--bullet">
<li>Double check the spelling and try again</li>
<li>Type the first few letters to see the suggestions</li>
<li>Type Other and continue - we’ll ask you to type in your answer in the next question</li>
</ul>
<% end %>

4
app/views/logs/_log_filters.erb

@ -10,7 +10,7 @@
<%= render partial: "filters/checkbox_filter", locals: { f: f, options: years, label: "Collection year", category: "years" } %> <%= 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/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", } %> <%= render partial: "filters/radio_filter", locals: { f: f, options: all_or_yours, label: "Logs", category: "user", } %>
<% if @current_user.support? && request.path == "/lettings-logs" %> <% if (@current_user.support? || @current_user.organisation.has_managing_agents?) && request.path == "/lettings-logs" %>
<%= render partial: "filters/radio_filter", locals: { <%= render partial: "filters/radio_filter", locals: {
f: f, f: f,
options: { options: {
@ -21,7 +21,7 @@
type: "select", type: "select",
label: "Organisation", label: "Organisation",
category: "organisation", category: "organisation",
options: [OpenStruct.new(id: "", name: "Select an option")] + Organisation.all.map { |org| OpenStruct.new(id: org.id, name: org.name) } options: organisations_filter_options(@current_user)
} }
} }
}, },

8
db/migrate/20230109144039_add_mortgage_lender.rb

@ -0,0 +1,8 @@
class AddMortgageLender < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :mortgagelender, :integer
t.column :mortgagelenderother, :string
end
end
end

11
db/migrate/20230113125117_add_postcode_fields_to_sales.rb

@ -0,0 +1,11 @@
class AddPostcodeFieldsToSales < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :pcode1, :string
t.column :pcode2, :string
t.column :pcodenk, :integer
t.column :postcode_full, :string
t.column :is_la_inferred, :boolean
end
end
end

9
db/schema.rb

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_01_12_093524) do ActiveRecord::Schema[7.0].define(version: 2023_01_13_125117) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -486,6 +486,13 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_12_093524) do
t.integer "fromprop" t.integer "fromprop"
t.integer "socprevten" t.integer "socprevten"
t.integer "mortlen" t.integer "mortlen"
t.string "pcode1"
t.string "pcode2"
t.integer "pcodenk"
t.string "postcode_full"
t.boolean "is_la_inferred"
t.integer "mortgagelender"
t.string "mortgagelenderother"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id" t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id"
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"

16
spec/components/bulk_upload_error_row_component_spec.rb

@ -49,6 +49,22 @@ RSpec.describe BulkUploadErrorRowComponent, type: :component do
expect(result).to have_content(expected) expect(result).to have_content(expected)
end end
context "when multiple errors for a row" do
subject(:component) { described_class.new(bulk_upload_errors:) }
let(:bulk_upload_errors) do
[
build(:bulk_upload_error, cell: "Z1"),
build(:bulk_upload_error, cell: "AB1"),
build(:bulk_upload_error, cell: "A1"),
]
end
it "is sorted by cell" do
expect(component.bulk_upload_errors.map(&:cell)).to eql(%w[A1 Z1 AB1])
end
end
context "when a sales bulk upload" do context "when a sales bulk upload" do
let(:bulk_upload) { create(:bulk_upload, :sales) } let(:bulk_upload) { create(:bulk_upload, :sales) }
let(:field) { :field_87 } let(:field) { :field_87 }

5
spec/factories/sales_log.rb

@ -57,7 +57,7 @@ FactoryBot.define do
income2nk { 0 } income2nk { 0 }
income2 { 10_000 } income2 { 10_000 }
inc2mort { 1 } inc2mort { 1 }
la_known { "1" } la_known { 1 }
la { "E09000003" } la { "E09000003" }
savingsnk { 1 } savingsnk { 1 }
prevown { 1 } prevown { 1 }
@ -96,6 +96,9 @@ FactoryBot.define do
mscharge_known { 1 } mscharge_known { 1 }
mscharge { 100 } mscharge { 100 }
mortlen { 10 } mortlen { 10 }
pcodenk { 1 }
is_la_inferred { false }
mortgagelender { 5 }
end end
end end
end end

35
spec/helpers/filters_helper_spec.rb

@ -81,4 +81,39 @@ RSpec.describe FiltersHelper do
end end
end end
end end
describe "#organisations_filter_options" do
let(:parent_organisation) { FactoryBot.create(:organisation, name: "Parent organisation") }
let(:child_organisation) { FactoryBot.create(:organisation, name: "Child organisation") }
before do
FactoryBot.create(:organisation_relationship, parent_organisation:, child_organisation:)
FactoryBot.create(:organisation, name: "Other organisation", id: 99)
end
context "with a support user" do
let(:user) { FactoryBot.create(:user, :support, organisation: parent_organisation) }
it "returns a list of all organisations" do
expect(organisations_filter_options(user)).to eq([
OpenStruct.new(id: "", name: "Select an option"),
OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"),
OpenStruct.new(id: child_organisation.id, name: "Child organisation"),
OpenStruct.new(id: 99, name: "Other organisation"),
])
end
end
context "with a data coordinator user" do
let(:user) { FactoryBot.create(:user, :data_coordinator, organisation: parent_organisation) }
it "returns a list of managing agents and your own organisation" do
expect(organisations_filter_options(user)).to eq([
OpenStruct.new(id: "", name: "Select an option"),
OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"),
OpenStruct.new(id: child_organisation.id, name: "Child organisation"),
])
end
end
end
end end

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

@ -29,7 +29,9 @@ RSpec.describe Form::Sales::Pages::AboutDepositWithoutDiscount, type: :model do
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to eq( expect(page.depends_on).to eq(
[{ "is_type_discount?" => false }], [{ "is_type_discount?" => false, "ownershipsch" => 1 },
{ "ownershipsch" => 2 },
{ "ownershipsch" => 3, "mortgageused" => 1 }],
) )
end end
end end

1
spec/models/form/sales/pages/about_price_not_rtb_spec.rb

@ -30,6 +30,7 @@ RSpec.describe Form::Sales::Pages::AboutPriceNotRtb, type: :model do
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to eq([{ expect(page.depends_on).to eq([{
"right_to_buy?" => false, "right_to_buy?" => false,
"rent_to_buy_full_ownership?" => false,
}]) }])
end end
end end

35
spec/models/form/sales/pages/mortgage_lender_other_spec.rb

@ -0,0 +1,35 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MortgageLenderOther, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "mortgage_lender_other" }
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[mortgagelenderother])
end
it "has the correct id" do
expect(page.id).to eq("mortgage_lender_other")
end
it "has the correct header" do
expect(page.header).to eq("")
end
it "has the correct description" do
expect(page.description).to eq("")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{
"mortgagelender" => 40,
}])
end
end

35
spec/models/form/sales/pages/mortgage_lender_spec.rb

@ -0,0 +1,35 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MortgageLender, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { "mortgage_lender" }
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[mortgagelender])
end
it "has the correct id" do
expect(page.id).to eq("mortgage_lender")
end
it "has the correct header" do
expect(page.header).to eq("")
end
it "has the correct description" do
expect(page.description).to eq("")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{
"mortgageused" => 1,
}])
end
end

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

@ -28,6 +28,8 @@ RSpec.describe Form::Sales::Pages::MortgageLength, type: :model do
end end
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to be_nil expect(page.depends_on).to eq([{
"mortgageused" => 1,
}])
end end
end end

33
spec/models/form/sales/pages/postcode_spec.rb

@ -0,0 +1,33 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Postcode, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
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[pcodenk postcode_full])
end
it "has the correct id" do
expect(page.id).to eq("property_postcode")
end
it "has the correct header" do
expect(page.header).to be_nil
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to be_nil
end
end

6
spec/models/form/sales/pages/property_local_authority_spec.rb

@ -31,4 +31,10 @@ RSpec.describe Form::Sales::Pages::PropertyLocalAuthority, type: :model do
it "has the correct description" do it "has the correct description" do
expect(page.description).to be_nil expect(page.description).to be_nil
end end
it "has the correct depends_on" do
expect(page.depends_on).to eq([{
"is_la_inferred" => false,
}])
end
end end

7
spec/models/form/sales/pages/purchase_price_spec.rb

@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::PurchasePrice, type: :model do RSpec.describe Form::Sales::Pages::PurchasePrice, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) } subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil } let(:page_id) { "purchase_price" }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) } let(:subsection) { instance_double(Form::Subsection) }
@ -28,6 +28,9 @@ RSpec.describe Form::Sales::Pages::PurchasePrice, type: :model do
end end
it "has correct depends_on" do it "has correct depends_on" do
expect(page.depends_on).to be_nil expect(page.depends_on).to eq([
{ "ownershipsch" => 3 },
{ "rent_to_buy_full_ownership?" => true },
])
end end
end end

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

@ -27,8 +27,8 @@ RSpec.describe Form::Sales::Questions::DepositAmount, type: :model do
expect(question.type).to eq("numeric") expect(question.type).to eq("numeric")
end end
it "is not marked as derived" do it "is marked as derived" do
expect(question.derived?).to be false expect(question.derived?).to be true
end end
it "has the correct hint" do it "has the correct hint" do

37
spec/models/form/sales/questions/mortgage_lender_other_spec.rb

@ -0,0 +1,37 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::MortgageLenderOther, 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("mortgagelenderother")
end
it "has the correct header" do
expect(question.header).to eq("What is the other mortgage lender?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Other Mortgage Lender")
end
it "has the correct type" do
expect(question.type).to eq("text")
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
end

88
spec/models/form/sales/questions/mortgage_lender_spec.rb

@ -0,0 +1,88 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::MortgageLender, 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("mortgagelender")
end
it "has the correct header" do
expect(question.header).to eq("What is the name of the mortgage lender?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Mortgage Lender")
end
it "has the correct type" do
expect(question.type).to eq("select")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "is has correct guidance_position" do
expect(question.top_guidance?).to be false
expect(question.bottom_guidance?).to be true
end
it "is has correct guidance_partial" do
expect(question.guidance_partial).to eq("mortgage_lender")
end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"" => "Select an option",
"1" => "Atom Bank",
"2" => "Barclays Bank PLC",
"3" => "Bath Building Society",
"4" => "Buckinghamshire Building Society",
"5" => "Cambridge Building Society",
"6" => "Coventry Building Society",
"7" => "Cumberland Building Society",
"8" => "Darlington Building Society",
"9" => "Dudley Building Society",
"10" => "Ecology Building Society",
"11" => "Halifax",
"12" => "Hanley Economic Building Society",
"13" => "Hinckley and Rugby Building Society",
"14" => "Holmesdale Building Society",
"15" => "Ipswich Building Society",
"16" => "Leeds Building Society",
"17" => "Lloyds Bank",
"18" => "Mansfield Building Society",
"19" => "Market Harborough Building Society",
"20" => "Melton Mowbray Building Society",
"21" => "Nationwide Building Society",
"22" => "Natwest",
"23" => "Nedbank Private Wealth",
"24" => "Newbury Building Society",
"25" => "OneSavings Bank",
"26" => "Parity Trust",
"27" => "Penrith Building Society",
"28" => "Pepper Homeloans",
"29" => "Royal Bank of Scotland",
"30" => "Santander",
"31" => "Skipton Building Society",
"32" => "Teachers Building Society",
"33" => "The Co-operative Bank",
"34" => "Tipton & Coseley Building Society",
"35" => "TSB",
"36" => "Ulster Bank",
"37" => "Virgin Money",
"38" => "West Bromwich Building Society",
"39" => "Yorkshire Building Society",
"40" => "Other",
})
end
end

59
spec/models/form/sales/questions/postcode_known_spec.rb

@ -0,0 +1,59 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::PostcodeKnown, 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("pcodenk")
end
it "has the correct header" do
expect(question.header).to eq("Do you know the property’s postcode?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Property’s postcode")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"0" => { "value" => "Yes" },
"1" => { "value" => "No" },
})
end
it "has correct conditional for" do
expect(question.conditional_for).to eq({
"postcode_full" => [0],
})
end
it "has the correct hint" do
expect(question.hint_text).to be_nil
end
it "has the correct hidden_in_check_answers" do
expect(question.hidden_in_check_answers).to eq({
"depends_on" => [
{ "pcodenk" => 0 },
{ "pcodenk" => 1 },
],
})
end
end

58
spec/models/form/sales/questions/postcode_spec.rb

@ -0,0 +1,58 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::Postcode, 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("postcode_full")
end
it "has the correct header" do
expect(question.header).to eq("Postcode")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Property’s postcode")
end
it "has the correct type" do
expect(question.type).to eq("text")
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 the correct width" do
expect(question.width).to eq(5)
end
it "has the correct inferred_answers" do
expect(question.inferred_answers).to eq({
"la" => {
"is_la_inferred" => true,
},
})
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq({
"condition" => {
"pcodenk" => 1,
},
"value" => "Not known",
})
end
end

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

@ -17,8 +17,11 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model
living_before_purchase_discounted_ownership living_before_purchase_discounted_ownership
about_price_rtb about_price_rtb
about_price_not_rtb about_price_not_rtb
purchase_price_discounted_ownership
mortgage_used_discounted_ownership mortgage_used_discounted_ownership
mortgage_amount_discounted_ownership mortgage_amount_discounted_ownership
mortgage_lender_discounted_ownership
mortgage_lender_other_discounted_ownership
mortgage_length_discounted_ownership mortgage_length_discounted_ownership
about_deposit_discounted_ownership about_deposit_discounted_ownership
discounted_ownership_deposit_value_check discounted_ownership_deposit_value_check

4
spec/models/form/sales/subsections/outright_sale_spec.rb

@ -14,9 +14,11 @@ RSpec.describe Form::Sales::Subsections::OutrightSale, type: :model do
it "has correct pages" do it "has correct pages" do
expect(outright_sale.pages.map(&:id)).to eq( expect(outright_sale.pages.map(&:id)).to eq(
%w[ %w[
purchase_price purchase_price_outright_sale
mortgage_used_outright_sale mortgage_used_outright_sale
mortgage_amount_outright_sale mortgage_amount_outright_sale
mortgage_lender_outright_sale
mortgage_lender_other_outright_sale
mortgage_length_outright_sale mortgage_length_outright_sale
about_deposit_outright_sale about_deposit_outright_sale
outright_sale_deposit_value_check outright_sale_deposit_value_check

1
spec/models/form/sales/subsections/property_information_spec.rb

@ -17,6 +17,7 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
property_number_of_bedrooms property_number_of_bedrooms
property_unit_type property_unit_type
property_building_type property_building_type
property_postcode
property_local_authority property_local_authority
property_wheelchair_accessible property_wheelchair_accessible
], ],

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

@ -28,6 +28,8 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipScheme, type: :model do
about_price_shared_ownership about_price_shared_ownership
mortgage_used_shared_ownership mortgage_used_shared_ownership
mortgage_amount_shared_ownership mortgage_amount_shared_ownership
mortgage_lender_shared_ownership
mortgage_lender_other_shared_ownership
mortgage_length_shared_ownership mortgage_length_shared_ownership
about_deposit_with_discount about_deposit_with_discount
about_deposit_shared_ownership about_deposit_shared_ownership

4
spec/models/form_handler_spec.rb

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

103
spec/models/sales_log_spec.rb

@ -140,6 +140,109 @@ RSpec.describe SalesLog, type: :model do
record_from_db = ActiveRecord::Base.connection.execute("select deposit from sales_logs where id=#{sales_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select deposit from sales_logs where id=#{sales_log.id}").to_a[0]
expect(record_from_db["deposit"]).to eq(nil) expect(record_from_db["deposit"]).to eq(nil)
end end
it "correctly derives and saves pcode1 and pcode1 and pcode2" do
sales_log.update!(postcode_full: "W6 0SP")
record_from_db = ActiveRecord::Base.connection.execute("select pcode1, pcode2 from sales_logs where id=#{sales_log.id}").to_a[0]
expect(record_from_db["pcode1"]).to eq("W6")
expect(record_from_db["pcode2"]).to eq("0SP")
end
end
context "when saving addresses" do
before do
stub_request(:get, /api.postcodes.io/)
.to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"Manchester\",\"codes\":{\"admin_district\": \"E08000003\"}}}", headers: {})
end
def check_postcode_fields(postcode_field)
record_from_db = ActiveRecord::Base.connection.execute("select #{postcode_field} from sales_logs where id=#{address_sales_log.id}").to_a[0]
expect(address_sales_log[postcode_field]).to eq("M1 1AE")
expect(record_from_db[postcode_field]).to eq("M1 1AE")
end
let!(:address_sales_log) do
FactoryBot.create(
:sales_log,
:completed,
managing_organisation: owning_organisation,
owning_organisation:,
created_by: created_by_user,
pcodenk: 0,
postcode_full: "M1 1AE",
)
end
def check_property_postcode_fields
check_postcode_fields("postcode_full")
end
it "correctly formats previous postcode" do
address_sales_log.update!(postcode_full: "M1 1AE")
check_property_postcode_fields
address_sales_log.update!(postcode_full: "m1 1ae")
check_property_postcode_fields
address_sales_log.update!(postcode_full: "m11Ae")
check_property_postcode_fields
address_sales_log.update!(postcode_full: "m11ae")
check_property_postcode_fields
end
it "correctly infers la" do
record_from_db = ActiveRecord::Base.connection.execute("select la from sales_logs where id=#{address_sales_log.id}").to_a[0]
expect(address_sales_log.la).to eq("E08000003")
expect(record_from_db["la"]).to eq("E08000003")
end
it "errors if the property postcode is emptied" do
expect { address_sales_log.update!({ postcode_full: "" }) }
.to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t("validations.postcode")}/)
end
it "errors if the property postcode is not valid" do
expect { address_sales_log.update!({ postcode_full: "invalid_postcode" }) }
.to raise_error(ActiveRecord::RecordInvalid, /#{I18n.t("validations.postcode")}/)
end
context "when the local authority lookup times out" do
before do
allow(Timeout).to receive(:timeout).and_raise(Timeout::Error)
end
it "logs a warning" do
expect(Rails.logger).to receive(:warn).with("Postcodes.io lookup timed out")
address_sales_log.update!({ pcodenk: 1, postcode_full: "M1 1AD" })
end
end
it "correctly resets all fields if property postcode not known" do
address_sales_log.update!({ pcodenk: 1 })
record_from_db = ActiveRecord::Base.connection.execute("select la, postcode_full from sales_logs where id=#{address_sales_log.id}").to_a[0]
expect(record_from_db["postcode_full"]).to eq(nil)
expect(address_sales_log.la).to eq(nil)
expect(record_from_db["la"]).to eq(nil)
end
it "changes the LA if property postcode changes from not known to known and provided" do
address_sales_log.update!({ pcodenk: 1 })
address_sales_log.update!({ la: "E09000033" })
record_from_db = ActiveRecord::Base.connection.execute("select la, postcode_full from sales_logs where id=#{address_sales_log.id}").to_a[0]
expect(record_from_db["postcode_full"]).to eq(nil)
expect(address_sales_log.la).to eq("E09000033")
expect(record_from_db["la"]).to eq("E09000033")
address_sales_log.update!({ pcodenk: 0, postcode_full: "M1 1AD" })
record_from_db = ActiveRecord::Base.connection.execute("select la, postcode_full from sales_logs where id=#{address_sales_log.id}").to_a[0]
expect(record_from_db["postcode_full"]).to eq("M1 1AD")
expect(address_sales_log.la).to eq("E08000003")
expect(record_from_db["la"]).to eq("E08000003")
end
end end
context "when saving previous address" do context "when saving previous address" do

20
spec/models/user_spec.rb

@ -117,8 +117,24 @@ RSpec.describe User, type: :model do
}) })
end end
it "can filter lettings logs by user, year and status" do context "and their organisation does not have managing agents" do
expect(user.logs_filters).to eq(%w[status years user]) before do
user.organisation.update(holds_own_stock: false)
end
it "can filter lettings logs by user, year and status" do
expect(user.logs_filters).to eq(%w[status years user])
end
end
context "and their organisation has managing agents" do
before do
FactoryBot.create(:organisation_relationship, parent_organisation: user.organisation)
end
it "can filter lettings logs by user, year, status and organisation" do
expect(user.logs_filters).to eq(%w[status years user organisation])
end
end end
end end

6
spec/models/validations/financial_validations_spec.rb

@ -126,14 +126,16 @@ RSpec.describe Validations::FinancialValidations do
describe "rent period validations" do describe "rent period validations" do
let(:organisation) { FactoryBot.create(:organisation) } let(:organisation) { FactoryBot.create(:organisation) }
let(:record) { FactoryBot.create(:lettings_log, owning_organisation: organisation) } let(:user) { FactoryBot.create(:user) }
let(:record) { FactoryBot.create(:lettings_log, owning_organisation: user.organisation, managing_organisation: organisation, created_by: user) }
before do before do
FactoryBot.create(:organisation_relationship, parent_organisation: user.organisation, child_organisation: organisation)
FactoryBot.create(:organisation_rent_period, organisation:, rent_period: 2) FactoryBot.create(:organisation_rent_period, organisation:, rent_period: 2)
end end
context "when the organisation only uses specific rent periods" do context "when the organisation only uses specific rent periods" do
it "validates that the selected rent period is used by the organisation" do it "validates that the selected rent period is used by the managing organisation" do
record.period = 3 record.period = 3
financial_validator.validate_rent_period(record) financial_validator.validate_rent_period(record)
expect(record.errors["period"]) expect(record.errors["period"])

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

@ -32,8 +32,15 @@ RSpec.describe BulkUpload::Lettings::Validator do
context "when a valid csv" do context "when a valid csv" do
let(:path) { file_fixture("2022_23_lettings_bulk_upload.csv") } let(:path) { file_fixture("2022_23_lettings_bulk_upload.csv") }
it do it "creates validation errors" do
expect { validator.call }.to change(BulkUploadError, :count)
end
it "create validation error with correct values" do
validator.call validator.call
error = BulkUploadError.first
expect(error.row).to eq("6")
end end
end end
end end

Loading…
Cancel
Save