Browse Source

Merge branch 'main' into CLDC-1821-wheelchair-conditionally-visible

pull/1343/head
Arthur Campbell 3 years ago committed by GitHub
parent
commit
2974e5ba59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      app/components/bulk_upload_error_summary_table_component.rb
  2. 19
      app/components/check_answers_summary_list_card_component.rb
  3. 8
      app/mailers/bulk_upload_mailer.rb
  4. 9
      app/models/derived_variables/sales_log_variables.rb
  5. 10
      app/models/form/sales/pages/number_of_others_in_property.rb
  6. 12
      app/models/form/sales/questions/buyer1_mortgage.rb
  7. 29
      app/models/form/sales/questions/buyer1_previous_tenure.rb
  8. 12
      app/models/form/sales/questions/buyer2_mortgage.rb
  9. 10
      app/models/form/sales/questions/buyers_organisations.rb
  10. 8
      app/models/form/sales/questions/mortgageused.rb
  11. 18
      app/models/form/sales/questions/number_of_others_in_property.rb
  12. 35
      app/models/form/sales/questions/shared_ownership_type.rb
  13. 11
      app/models/form/sales/subsections/household_characteristics.rb
  14. 5
      app/models/lettings_log.rb
  15. 5
      app/models/log.rb
  16. 16
      app/models/sales_log.rb
  17. 10
      app/models/validations/financial_validations.rb
  18. 2
      app/models/validations/household_validations.rb
  19. 2
      app/models/validations/sales/sale_information_validations.rb
  20. 2
      app/models/validations/sales/soft_validations.rb
  21. 32
      app/services/imports/lettings_logs_import_service.rb
  22. 80
      app/services/imports/sales_logs_import_service.rb
  23. 8
      app/views/bulk_upload_lettings_results/show.html.erb
  24. 1
      app/views/form/headers/_person_6_known_page.erb
  25. 32
      config/sale_range_data/2023.csv
  26. 5
      db/migrate/20230301144555_add_pregblank.rb
  27. 9
      db/schema.rb
  28. 1
      db/seeds.rb
  29. 1
      lib/tasks/full_import.rake
  30. 35
      spec/components/bulk_upload_error_summary_table_component_spec.rb
  31. 333
      spec/fixtures/imports/logs/shared_ownership_sales_log.xml
  32. 2
      spec/fixtures/imports/sales_logs/discounted_ownership_sales_log.xml
  33. 524
      spec/fixtures/imports/sales_logs/lettings_log.xml
  34. 4
      spec/lib/tasks/full_import_spec.rb
  35. 4
      spec/mailers/bulk_upload_mailer_spec.rb
  36. 4
      spec/models/form/sales/pages/buyer1_previous_tenure_spec.rb
  37. 40
      spec/models/form/sales/pages/number_of_others_in_property_spec.rb
  38. 4
      spec/models/form/sales/pages/shared_ownership_type_spec.rb
  39. 13
      spec/models/form/sales/questions/buyer1_mortgage_spec.rb
  40. 10
      spec/models/form/sales/questions/buyer1_previous_tenure_spec.rb
  41. 13
      spec/models/form/sales/questions/buyer2_mortgage_spec.rb
  42. 12
      spec/models/form/sales/questions/buyers_organisations_spec.rb
  43. 9
      spec/models/form/sales/questions/mortgageused_spec.rb
  44. 25
      spec/models/form/sales/questions/number_of_others_in_property_spec.rb
  45. 44
      spec/models/form/sales/questions/shared_ownership_type_spec.rb
  46. 18
      spec/models/form/sales/subsections/household_characteristics_spec.rb
  47. 30
      spec/models/sales_log_spec.rb
  48. 2
      spec/models/validations/financial_validations_spec.rb
  49. 110
      spec/services/imports/lettings_logs_import_service_spec.rb
  50. 199
      spec/services/imports/sales_logs_import_service_spec.rb

13
app/components/bulk_upload_error_summary_table_component.rb

@ -1,4 +1,6 @@
class BulkUploadErrorSummaryTableComponent < ViewComponent::Base class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
DISPLAY_THRESHOLD = 16
attr_reader :bulk_upload attr_reader :bulk_upload
def initialize(bulk_upload:) def initialize(bulk_upload:)
@ -11,7 +13,18 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
@sorted_errors ||= bulk_upload @sorted_errors ||= bulk_upload
.bulk_upload_errors .bulk_upload_errors
.group(:col, :field, :error) .group(:col, :field, :error)
.having("count(*) > ?", display_threshold)
.count .count
.sort_by { |el| el[0][0].rjust(3, "0") } .sort_by { |el| el[0][0].rjust(3, "0") }
end end
def errors?
sorted_errors.present?
end
private
def display_threshold
DISPLAY_THRESHOLD
end
end end

19
app/components/check_answers_summary_list_card_component.rb

@ -18,21 +18,10 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
end end
def check_answers_card_title(question) def check_answers_card_title(question)
if question.form.type == "lettings" return "Lead tenant" if question.form.type == "lettings" && question.check_answers_card_number == 1
case question.check_answers_card_number return "Buyer #{question.check_answers_card_number}" if question.check_answers_card_number <= number_of_buyers
when 1
"Lead tenant" "Person #{question.check_answers_card_number}"
when 2..8
"Person #{question.check_answers_card_number}"
end
else
case question.check_answers_card_number
when 1..number_of_buyers
"Buyer #{question.check_answers_card_number}"
when (number_of_buyers + 1)..(number_of_buyers + 4)
"Person #{question.check_answers_card_number}"
end
end
end end
private private

8
app/mailers/bulk_upload_mailer.rb

@ -46,6 +46,12 @@ class BulkUploadMailer < NotifyMailer
def send_correct_and_upload_again_mail(bulk_upload:) def send_correct_and_upload_again_mail(bulk_upload:)
error_description = "We noticed that you have a lot of similar errors in column #{columns_with_errors(bulk_upload:)}. Please correct your data export and upload again." error_description = "We noticed that you have a lot of similar errors in column #{columns_with_errors(bulk_upload:)}. Please correct your data export and upload again."
summary_report_link = if BulkUploadErrorSummaryTableComponent.new(bulk_upload:).errors?
summary_bulk_upload_lettings_result_url(bulk_upload)
else
bulk_upload_lettings_result_url(bulk_upload)
end
send_email( send_email(
bulk_upload.user.email, bulk_upload.user.email,
BULK_UPLOAD_FAILED_CSV_ERRORS_TEMPLATE_ID, BULK_UPLOAD_FAILED_CSV_ERRORS_TEMPLATE_ID,
@ -55,7 +61,7 @@ class BulkUploadMailer < NotifyMailer
year_combo: bulk_upload.year_combo, year_combo: bulk_upload.year_combo,
lettings_or_sales: bulk_upload.log_type, lettings_or_sales: bulk_upload.log_type,
error_description:, error_description:,
summary_report_link: summary_bulk_upload_lettings_result_url(bulk_upload), summary_report_link:,
}, },
) )
end end

9
app/models/derived_variables/sales_log_variables.rb

@ -21,12 +21,19 @@ module DerivedVariables::SalesLogVariables
self.pcode1, self.pcode2 = postcode_full.split(" ") if postcode_full.present? self.pcode1, self.pcode2 = postcode_full.split(" ") if postcode_full.present?
self.totchild = total_child self.totchild = total_child
self.totadult = total_adult + total_elder self.totadult = total_adult + total_elder
self.hhmemb = totchild + totadult self.hhmemb = number_of_household_members
self.hhtype = household_type self.hhtype = household_type
end end
private private
def number_of_household_members
return unless hholdcount.present? && jointpur.present?
number_of_buyers = joint_purchase? ? 2 : 1
hholdcount + number_of_buyers
end
def total_elder def total_elder
ages = [age1, age2, age3, age4, age5, age6] ages = [age1, age2, age3, age4, age5, age6]
ages.count { |age| age.present? && age >= 60 } ages.count { |age| age.present? && age >= 60 }

10
app/models/form/sales/pages/number_of_others_in_property.rb

@ -1,20 +1,22 @@
class Form::Sales::Pages::NumberOfOthersInProperty < ::Form::Page class Form::Sales::Pages::NumberOfOthersInProperty < ::Form::Page
def initialize(id, hsh, subsection) def initialize(id, hsh, subsection, joint_purchase:)
super super(id, hsh, subsection)
@id = "number_of_others_in_property"
@depends_on = [ @depends_on = [
{ {
"privacynotice" => 1, "privacynotice" => 1,
"jointpur" => joint_purchase ? 1 : 2,
}, },
{ {
"noint" => 1, "noint" => 1,
"jointpur" => joint_purchase ? 1 : 2,
}, },
] ]
@joint_purchase = joint_purchase
end end
def questions def questions
@questions ||= [ @questions ||= [
Form::Sales::Questions::NumberOfOthersInProperty.new(nil, nil, self), Form::Sales::Questions::NumberOfOthersInProperty.new(nil, nil, self, joint_purchase: @joint_purchase),
] ]
end end
end end

12
app/models/form/sales/questions/buyer1_mortgage.rb

@ -2,8 +2,8 @@ class Form::Sales::Questions::Buyer1Mortgage < ::Form::Question
def initialize(id, hsh, page) def initialize(id, hsh, page)
super super
@id = "inc1mort" @id = "inc1mort"
@check_answer_label = "Buyer 1's income used for mortgage application" @check_answer_label = "Buyer 1s income used for mortgage application"
@header = "Was buyer 1's income used for a mortgage application?" @header = "Was buyer 1s income used for a mortgage application?"
@type = "radio" @type = "radio"
@answer_options = ANSWER_OPTIONS @answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1 @check_answers_card_number = 1
@ -12,5 +12,13 @@ class Form::Sales::Questions::Buyer1Mortgage < ::Form::Question
ANSWER_OPTIONS = { ANSWER_OPTIONS = {
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
}.freeze }.freeze
def displayed_answer_options(_log, _user = nil)
{
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}
end
end end

29
app/models/form/sales/questions/buyer1_previous_tenure.rb

@ -2,20 +2,23 @@ class Form::Sales::Questions::Buyer1PreviousTenure < ::Form::Question
def initialize(id, hsh, page) def initialize(id, hsh, page)
super super
@id = "prevten" @id = "prevten"
@check_answer_label = "Buyer 1's previous tenure" @check_answer_label = "Buyer 1s previous tenure"
@header = "What was buyer 1's previous tenure?" @header = "What was buyer 1s previous tenure?"
@type = "radio" @type = "radio"
@answer_options = ANSWER_OPTIONS @answer_options = answer_options
end end
ANSWER_OPTIONS = { def answer_options
"1" => { "value" => "Local Authority" }, {
"2" => { "value" => "Private registered provider or housing association tenant" }, "1" => { "value" => "Local Authority" },
"3" => { "value" => "Private tenant" }, "2" => { "value" => "Private registered provider or housing association tenant" },
"5" => { "value" => "Owner occupier" }, "3" => { "value" => "Private tenant" },
"4" => { "value" => "Tied home or renting with job" }, "5" => { "value" => "Owner occupier" },
"6" => { "value" => "Living with family or friends" }, "4" => { "value" => "Tied home or renting with job" },
"7" => { "value" => "Temporary accomodation" }, "6" => { "value" => "Living with family or friends" },
"9" => { "value" => "Other" }, "7" => { "value" => "Temporary accomodation" },
}.freeze "9" => { "value" => "Other" },
"0" => { "value" => "Don’t know" },
}
end
end end

12
app/models/form/sales/questions/buyer2_mortgage.rb

@ -2,8 +2,8 @@ class Form::Sales::Questions::Buyer2Mortgage < ::Form::Question
def initialize(id, hsh, page) def initialize(id, hsh, page)
super super
@id = "inc2mort" @id = "inc2mort"
@check_answer_label = "Buyer 2's income used for mortgage application" @check_answer_label = "Buyer 2s income used for mortgage application"
@header = "Was buyer 2's income used for a mortgage application?" @header = "Was buyer 2s income used for a mortgage application?"
@type = "radio" @type = "radio"
@answer_options = ANSWER_OPTIONS @answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2 @check_answers_card_number = 2
@ -12,5 +12,13 @@ class Form::Sales::Questions::Buyer2Mortgage < ::Form::Question
ANSWER_OPTIONS = { ANSWER_OPTIONS = {
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
}.freeze }.freeze
def displayed_answer_options(_log, _user = nil)
{
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}
end
end end

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

@ -14,8 +14,18 @@ class Form::Sales::Questions::BuyersOrganisations < ::Form::Question
"pregother" => { "value" => "Other private registered provider (PRP) - housing association" }, "pregother" => { "value" => "Other private registered provider (PRP) - housing association" },
"pregla" => { "value" => "Local Authority" }, "pregla" => { "value" => "Local Authority" },
"pregghb" => { "value" => "Help to Buy Agent" }, "pregghb" => { "value" => "Help to Buy Agent" },
"pregblank" => { "value" => "None of the above" },
}.freeze }.freeze
def displayed_answer_options(_log, _user = nil)
{
"pregyrha" => { "value" => "Their private registered provider (PRP) - housing association" },
"pregother" => { "value" => "Other private registered provider (PRP) - housing association" },
"pregla" => { "value" => "Local Authority" },
"pregghb" => { "value" => "Help to Buy Agent" },
}
end
def unanswered_error_message def unanswered_error_message
"At least one option must be selected of these four" "At least one option must be selected of these four"
end end

8
app/models/form/sales/questions/mortgageused.rb

@ -11,5 +11,13 @@ class Form::Sales::Questions::Mortgageused < ::Form::Question
ANSWER_OPTIONS = { ANSWER_OPTIONS = {
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
}.freeze }.freeze
def displayed_answer_options(_log, _user = nil)
{
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}
end
end end

18
app/models/form/sales/questions/number_of_others_in_property.rb

@ -1,13 +1,23 @@
class Form::Sales::Questions::NumberOfOthersInProperty < ::Form::Question class Form::Sales::Questions::NumberOfOthersInProperty < ::Form::Question
def initialize(id, hsh, page) def initialize(id, hsh, page, joint_purchase:)
super super(id, hsh, page)
@id = "hholdcount" @id = "hholdcount"
@check_answer_label = "Number of other people living in the property" @check_answer_label = "Number of other people living in the property"
@header = "Besides the buyer(s), how many other people live or will live in the property?" @header = "Besides the buyer(s), how many other people live or will live in the property?"
@type = "numeric" @type = "numeric"
@hint_text = "You can provide details for a maximum of 4 other people." @hint_text = hint(joint_purchase)
@width = 2 @width = 2
@min = 0 @min = 0
@max = 4 @max = joint_purchase ? 4 : 5
end
private
def hint(joint_purchase)
if joint_purchase
"You can provide details for a maximum of 4 other people for a joint purchase."
else
"You can provide details for a maximum of 5 other people if there is only one buyer."
end
end end
end end

35
app/models/form/sales/questions/shared_ownership_type.rb

@ -6,16 +6,31 @@ class Form::Sales::Questions::SharedOwnershipType < ::Form::Question
@header = "What is the type of shared ownership sale?" @header = "What is the type of shared ownership sale?"
@hint_text = "A shared ownership sale is when the purchaser buys up to 75% of the property value and pays rent to the Private Registered Provider (PRP) on the remaining portion" @hint_text = "A shared ownership sale is when the purchaser buys up to 75% of the property value and pays rent to the Private Registered Provider (PRP) on the remaining portion"
@type = "radio" @type = "radio"
@answer_options = ANSWER_OPTIONS @answer_options = answer_options
end end
ANSWER_OPTIONS = { def answer_options
"2" => { "value" => "Shared Ownership" }, if form.start_date.year >= 2023
"24" => { "value" => "Old Persons Shared Ownership" }, {
"18" => { "value" => "Social HomeBuy (shared ownership purchase)" }, "2" => { "value" => "Shared Ownership (old model lease)" },
"16" => { "value" => "Home Ownership for people with Long Term Disabilities (HOLD)" }, "30" => { "value" => "Shared Ownership (new model lease)" },
"28" => { "value" => "Rent to Buy - Shared Ownership" }, "18" => { "value" => "Social HomeBuy — shared ownership purchase" },
"31" => { "value" => "Right to Shared Ownership" }, "16" => { "value" => "Home Ownership for people with Long-Term Disabilities (HOLD)" },
"30" => { "value" => "Shared Ownership - 2021 model lease" }, "24" => { "value" => "Older Persons Shared Ownership" },
}.freeze "28" => { "value" => "Rent to Buy — Shared Ownership" },
"31" => { "value" => "Right to Shared Ownership (RtSO)" },
"32" => { "value" => "London Living Rent — Shared Ownership" },
}
else
{
"2" => { "value" => "Shared Ownership" },
"24" => { "value" => "Old Persons Shared Ownership" },
"18" => { "value" => "Social HomeBuy (shared ownership purchase)" },
"16" => { "value" => "Home Ownership for people with Long-Term Disabilities (HOLD)" },
"28" => { "value" => "Rent to Buy - Shared Ownership" },
"31" => { "value" => "Right to Shared Ownership" },
"30" => { "value" => "Shared Ownership - 2021 model lease" },
}
end
end
end end

11
app/models/form/sales/subsections/household_characteristics.rb

@ -37,7 +37,8 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check_joint_purchase", nil, self, person_index: 2), Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check_joint_purchase", nil, self, person_index: 2),
Form::Sales::Pages::Buyer2IncomeValueCheck.new("working_situation_buyer_2_income_value_check", nil, self), Form::Sales::Pages::Buyer2IncomeValueCheck.new("working_situation_buyer_2_income_value_check", nil, self),
Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self), Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self),
Form::Sales::Pages::NumberOfOthersInProperty.new(nil, nil, self), Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property", nil, self, joint_purchase: false),
Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 2), Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 2),
Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_2_relationship_to_buyer_1", nil, self, person_index: 2), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_2_relationship_to_buyer_1", nil, self, person_index: 2),
Form::Sales::Pages::PersonAge.new("person_2_age", nil, self, person_index: 2), Form::Sales::Pages::PersonAge.new("person_2_age", nil, self, person_index: 2),
@ -70,6 +71,14 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::RetirementValueCheck.new("gender_5_retirement_value_check", nil, self, person_index: 5), Form::Sales::Pages::RetirementValueCheck.new("gender_5_retirement_value_check", nil, self, person_index: 5),
Form::Sales::Pages::PersonWorkingSituation.new("person_5_working_situation", nil, self, person_index: 5), Form::Sales::Pages::PersonWorkingSituation.new("person_5_working_situation", nil, self, person_index: 5),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_5_retirement_value_check", nil, self, person_index: 5), Form::Sales::Pages::RetirementValueCheck.new("working_situation_5_retirement_value_check", nil, self, person_index: 5),
Form::Sales::Pages::PersonKnown.new("person_6_known", nil, self, person_index: 6),
Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_6_relationship_to_buyer_1", nil, self, person_index: 6),
Form::Sales::Pages::PersonAge.new("person_6_age", nil, self, person_index: 6),
Form::Sales::Pages::RetirementValueCheck.new("age_6_retirement_value_check", nil, self, person_index: 6),
Form::Sales::Pages::PersonGenderIdentity.new("person_6_gender_identity", nil, self, person_index: 6),
Form::Sales::Pages::RetirementValueCheck.new("gender_6_retirement_value_check", nil, self, person_index: 6),
Form::Sales::Pages::PersonWorkingSituation.new("person_6_working_situation", nil, self, person_index: 6),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_6_retirement_value_check", nil, self, person_index: 6),
].flatten.compact ].flatten.compact
end end

5
app/models/lettings_log.rb

@ -65,11 +65,6 @@ class LettingsLog < Log
FormHandler.instance.get_form(form_name) || FormHandler.instance.current_lettings_form FormHandler.instance.get_form(form_name) || FormHandler.instance.current_lettings_form
end end
def recalculate_start_year!
@start_year = nil
collection_start_year
end
def lettings? def lettings?
true true
end end

5
app/models/log.rb

@ -39,6 +39,11 @@ class Log < ApplicationRecord
@start_year = startdate < window_end_date ? startdate.year - 1 : startdate.year @start_year = startdate < window_end_date ? startdate.year - 1 : startdate.year
end end
def recalculate_start_year!
@start_year = nil
collection_start_year
end
def lettings? def lettings?
false false
end end

16
app/models/sales_log.rb

@ -24,6 +24,7 @@ class SalesLog < Log
has_paper_trail has_paper_trail
validates_with SalesLogValidator validates_with SalesLogValidator
before_validation :recalculate_start_year!, if: :saledate_changed?
before_validation :reset_invalidated_dependent_fields! before_validation :reset_invalidated_dependent_fields!
before_validation :process_postcode_changes!, if: :postcode_full_changed? 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?
@ -65,7 +66,20 @@ class SalesLog < Log
end end
def optional_fields def optional_fields
OPTIONAL_FIELDS OPTIONAL_FIELDS + dynamically_not_required
end
def dynamically_not_required
not_required = []
not_required << "proplen" if proplen_optional?
not_required
end
def proplen_optional?
return false unless collection_start_year
collection_start_year < 2023
end end
def not_started? def not_started?

10
app/models/validations/financial_validations.rb

@ -24,11 +24,11 @@ module Validations::FinancialValidations
def validate_net_income(record) def validate_net_income(record)
if record.ecstat1 && record.weekly_net_income if record.ecstat1 && record.weekly_net_income
if record.weekly_net_income > record.applicable_income_range.hard_max if record.weekly_net_income > record.applicable_income_range.hard_max
record.errors.add :earnings, I18n.t("validations.financial.earnings.over_hard_max", hard_max: record.applicable_income_range.hard_max) record.errors.add :earnings, :over_hard_max, message: I18n.t("validations.financial.earnings.over_hard_max", hard_max: record.applicable_income_range.hard_max)
end end
if record.weekly_net_income < record.applicable_income_range.hard_min if record.weekly_net_income < record.applicable_income_range.hard_min
record.errors.add :earnings, I18n.t("validations.financial.earnings.under_hard_min", hard_min: record.applicable_income_range.hard_min) record.errors.add :earnings, :under_hard_min, message: I18n.t("validations.financial.earnings.under_hard_min", hard_min: record.applicable_income_range.hard_min)
end end
end end
@ -111,9 +111,11 @@ module Validations::FinancialValidations
def validate_care_home_charges(record) def validate_care_home_charges(record)
if record.is_carehome? if record.is_carehome?
period = record.form.get_question("period", record).label_from_value(record.period).downcase period = record.form.get_question("period", record).label_from_value(record.period).downcase
# NOTE: This is a temporary change to allow `ccharge` values despite `is_carehome` being true. This value
# is going to be moved to a soft validation in CLDC-2074, so we can safely do this.
if record.chcharge.blank? if record.chcharge.blank?
record.errors.add :is_carehome, I18n.t("validations.financial.carehome.not_provided", period:) # record.errors.add :is_carehome, I18n.t("validations.financial.carehome.not_provided", period:)
record.errors.add :chcharge, I18n.t("validations.financial.carehome.not_provided", period:) # record.errors.add :chcharge, I18n.t("validations.financial.carehome.not_provided", period:)
elsif !weekly_value_in_range(record, "chcharge", 10, 1000) elsif !weekly_value_in_range(record, "chcharge", 10, 1000)
max_chcharge = record.weekly_to_value_per_period(1000) max_chcharge = record.weekly_to_value_per_period(1000)
min_chcharge = record.weekly_to_value_per_period(10) min_chcharge = record.weekly_to_value_per_period(10)

2
app/models/validations/household_validations.rb

@ -67,7 +67,7 @@ module Validations::HouseholdValidations
end end
if record.age1.present? && record.age1 > 19 && record.previous_tenancy_was_foster_care? if record.age1.present? && record.age1 > 19 && record.previous_tenancy_was_foster_care?
record.errors.add :prevten, I18n.t("validations.household.prevten.over_20_foster_care") record.errors.add :prevten, :over_20_foster_care, message: I18n.t("validations.household.prevten.over_20_foster_care")
record.errors.add :age1, I18n.t("validations.household.age.lead.over_20") record.errors.add :age1, I18n.t("validations.household.age.lead.over_20")
end end

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

@ -46,7 +46,7 @@ module Validations::Sales::SaleInformationValidations
def validate_discounted_ownership_value(record) def validate_discounted_ownership_value(record)
return unless record.value && record.deposit && record.ownershipsch return unless record.value && record.deposit && record.ownershipsch
return unless record.mortgage || record.mortgageused == 2 return unless record.mortgage || record.mortgageused == 2 || record.mortgageused == 3
return unless record.discount || record.grant || record.type == 29 return unless record.discount || record.grant || record.type == 29
discount_amount = record.discount ? record.value * record.discount / 100 : 0 discount_amount = record.discount ? record.value * record.discount / 100 : 0

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

@ -60,7 +60,7 @@ module Validations::Sales::SoftValidations
end end
def shared_ownership_deposit_invalid? def shared_ownership_deposit_invalid?
return unless mortgage || mortgageused == 2 return unless mortgage || mortgageused == 2 || mortgageused == 3
return unless cashdis || !is_type_discount? return unless cashdis || !is_type_discount?
return unless deposit && value && equity return unless deposit && value && equity

32
app/services/imports/lettings_logs_import_service.rb

@ -55,6 +55,8 @@ module Imports
}.freeze }.freeze
def create_log(xml_doc) def create_log(xml_doc)
return if meta_field_value(xml_doc, "form-name").include?("Sales")
attributes = {} attributes = {}
previous_status = meta_field_value(xml_doc, "status") previous_status = meta_field_value(xml_doc, "status")
@ -287,8 +289,38 @@ module Imports
@logs_overridden << lettings_log.old_id @logs_overridden << lettings_log.old_id
attributes.delete("referral") attributes.delete("referral")
save_lettings_log(attributes, previous_status) save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:earnings, :under_hard_min)
@logger.warn("Log #{lettings_log.old_id}: Where the income is 0, set earnings and income to blank and set incref to refused")
@logs_overridden << lettings_log.old_id
attributes.delete("earnings")
attributes.delete("incfreq")
attributes["incref"] = 1
attributes["net_income_known"] = 2
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.include?(:tenancylength) && lettings_log.errors.include?(:tenancy)
@logger.warn("Log #{lettings_log.old_id}: Removing tenancylength as invalid")
@logs_overridden << lettings_log.old_id
attributes.delete("tenancylength")
attributes.delete("tenancy")
save_lettings_log(attributes, previous_status)
elsif lettings_log.errors.of_kind?(:prevten, :over_20_foster_care)
@logger.warn("Log #{lettings_log.old_id}: Removing age1 and prevten as incompatible")
@logs_overridden << lettings_log.old_id
attributes.delete("prevten")
attributes.delete("age1")
save_lettings_log(attributes, previous_status)
else else
@logger.error("Log #{lettings_log.old_id}: Failed to import") @logger.error("Log #{lettings_log.old_id}: Failed to import")
lettings_log.errors.each do |error|
@logger.error("Validation error: Field #{error.attribute}:")
@logger.error("\tOwning Organisation: #{lettings_log.owning_organisation&.name}")
@logger.error("\tManaging Organisation: #{lettings_log.managing_organisation&.name}")
@logger.error("\tOld CORE ID: #{lettings_log.old_id}")
@logger.error("\tOld CORE: #{attributes[error.attribute.to_s]&.inspect}")
@logger.error("\tNew CORE: #{lettings_log.read_attribute(error.attribute)&.inspect}")
@logger.error("\tError message: #{error.type}")
end
raise exception raise exception
end end
end end

80
app/services/imports/sales_logs_import_service.rb

@ -16,6 +16,8 @@ module Imports
private private
def create_log(xml_doc) def create_log(xml_doc)
return unless meta_field_value(xml_doc, "form-name").include?("Sales")
attributes = {} attributes = {}
previous_status = meta_field_value(xml_doc, "status") previous_status = meta_field_value(xml_doc, "status")
@ -31,12 +33,14 @@ module Imports
attributes["updated_at"] = Time.zone.parse(meta_field_value(xml_doc, "modified-date")) attributes["updated_at"] = Time.zone.parse(meta_field_value(xml_doc, "modified-date"))
attributes["purchid"] = string_or_nil(xml_doc, "PurchaserCode") attributes["purchid"] = string_or_nil(xml_doc, "PurchaserCode")
attributes["ownershipsch"] = unsafe_string_as_integer(xml_doc, "Ownership") attributes["ownershipsch"] = unsafe_string_as_integer(xml_doc, "Ownership")
attributes["ownershipsch"] = ownership_from_type(attributes) if attributes["ownershipsch"].blank? # sometimes Ownership is missing, but type is set
attributes["othtype"] = string_or_nil(xml_doc, "Q38OtherSale") attributes["othtype"] = string_or_nil(xml_doc, "Q38OtherSale")
attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore")
attributes["jointpur"] = unsafe_string_as_integer(xml_doc, "joint") attributes["jointpur"] = unsafe_string_as_integer(xml_doc, "joint")
attributes["jointmore"] = unsafe_string_as_integer(xml_doc, "JointMore") if attributes["jointpur"] == 1
attributes["beds"] = safe_string_as_integer(xml_doc, "Q11Bedrooms") attributes["beds"] = safe_string_as_integer(xml_doc, "Q11Bedrooms")
attributes["companybuy"] = unsafe_string_as_integer(xml_doc, "company") if attributes["ownershipsch"] == 3 attributes["companybuy"] = unsafe_string_as_integer(xml_doc, "company") if attributes["ownershipsch"] == 3
attributes["hhmemb"] = safe_string_as_integer(xml_doc, "HHMEMB") attributes["hholdcount"] = other_household_members(xml_doc, attributes)
attributes["hhmemb"] = household_members(xml_doc, attributes)
(1..6).each do |index| (1..6).each do |index|
attributes["age#{index}"] = safe_string_as_integer(xml_doc, "P#{index}Age") attributes["age#{index}"] = safe_string_as_integer(xml_doc, "P#{index}Age")
attributes["sex#{index}"] = sex(xml_doc, index) attributes["sex#{index}"] = sex(xml_doc, index)
@ -59,7 +63,6 @@ module Imports
attributes["noint"] = unsafe_string_as_integer(xml_doc, "PartAPurchaser") attributes["noint"] = unsafe_string_as_integer(xml_doc, "PartAPurchaser")
attributes["buy2livein"] = unsafe_string_as_integer(xml_doc, "LiveInBuyer2") attributes["buy2livein"] = unsafe_string_as_integer(xml_doc, "LiveInBuyer2")
attributes["wheel"] = unsafe_string_as_integer(xml_doc, "Q10Wheelchair") attributes["wheel"] = unsafe_string_as_integer(xml_doc, "Q10Wheelchair")
attributes["hholdcount"] = safe_string_as_integer(xml_doc, "LiveInOther")
attributes["la"] = string_or_nil(xml_doc, "Q14ONSLACode") attributes["la"] = string_or_nil(xml_doc, "Q14ONSLACode")
attributes["income1"] = safe_string_as_integer(xml_doc, "Q2Person1Income") attributes["income1"] = safe_string_as_integer(xml_doc, "Q2Person1Income")
attributes["income1nk"] = income_known(unsafe_string_as_integer(xml_doc, "P1IncKnown")) attributes["income1nk"] = income_known(unsafe_string_as_integer(xml_doc, "P1IncKnown"))
@ -102,10 +105,12 @@ module Imports
attributes["previous_la_known"] = nil attributes["previous_la_known"] = nil
attributes["hhregres"] = unsafe_string_as_integer(xml_doc, "ArmedF") attributes["hhregres"] = unsafe_string_as_integer(xml_doc, "ArmedF")
attributes["hhregresstill"] = still_serving(xml_doc) attributes["hhregresstill"] = still_serving(xml_doc)
attributes["proplen"] = safe_string_as_integer(xml_doc, "Q16aProplen2") attributes["proplen"] = safe_string_as_integer(xml_doc, "Q16aProplen2") || safe_string_as_integer(xml_doc, "Q16aProplensec2")
attributes["mscharge"] = monthly_charges(xml_doc, attributes) attributes["mscharge"] = monthly_charges(xml_doc, attributes)
attributes["mscharge_known"] = 1 if attributes["mscharge"].present? attributes["mscharge_known"] = 1 if attributes["mscharge"].present?
attributes["prevten"] = unsafe_string_as_integer(xml_doc, "Q6PrevTenure") attributes["prevten"] = unsafe_string_as_integer(xml_doc, "Q6PrevTenure")
attributes["mortlen"] = mortgage_length(xml_doc, attributes)
attributes["extrabor"] = borrowing(xml_doc, attributes)
attributes["mortgageused"] = unsafe_string_as_integer(xml_doc, "MORTGAGEUSED") attributes["mortgageused"] = unsafe_string_as_integer(xml_doc, "MORTGAGEUSED")
attributes["wchair"] = unsafe_string_as_integer(xml_doc, "Q15Wheelchair") attributes["wchair"] = unsafe_string_as_integer(xml_doc, "Q15Wheelchair")
attributes["armedforcesspouse"] = unsafe_string_as_integer(xml_doc, "ARMEDFORCESSPOUSE") attributes["armedforcesspouse"] = unsafe_string_as_integer(xml_doc, "ARMEDFORCESSPOUSE")
@ -117,11 +122,6 @@ module Imports
attributes["socprevten"] = unsafe_string_as_integer(xml_doc, "PrevRentType") attributes["socprevten"] = unsafe_string_as_integer(xml_doc, "PrevRentType")
attributes["mortgagelender"] = mortgage_lender(xml_doc, attributes) attributes["mortgagelender"] = mortgage_lender(xml_doc, attributes)
attributes["mortgagelenderother"] = mortgage_lender_other(xml_doc, attributes) attributes["mortgagelenderother"] = mortgage_lender_other(xml_doc, attributes)
attributes["mortlen"] = mortgage_length(xml_doc, attributes)
attributes["extrabor"] = borrowing(xml_doc, attributes)
attributes["totadult"] = safe_string_as_integer(xml_doc, "TOTADULT") # would get overridden
attributes["totchild"] = safe_string_as_integer(xml_doc, "TOTCHILD") # would get overridden
attributes["hhtype"] = unsafe_string_as_integer(xml_doc, "HHTYPE")
attributes["pcode1"] = string_or_nil(xml_doc, "PCODE1") attributes["pcode1"] = string_or_nil(xml_doc, "PCODE1")
attributes["pcode2"] = string_or_nil(xml_doc, "PCODE2") attributes["pcode2"] = string_or_nil(xml_doc, "PCODE2")
attributes["postcode_full"] = compose_postcode(xml_doc, "PCODE1", "PCODE2") attributes["postcode_full"] = compose_postcode(xml_doc, "PCODE1", "PCODE2")
@ -396,6 +396,49 @@ module Imports
end end
end end
def ownership_from_type(attributes)
case attributes["type"]
when 2, 24, 18, 16, 28, 31, 30
1 # shared ownership
when 8, 14, 27, 9, 29, 21, 22
2 # discounted ownership
when 10, 12
3 # outright sale
end
end
def other_household_members(xml_doc, attributes)
hholdcount = safe_string_as_integer(xml_doc, "LiveInOther")
return hholdcount if hholdcount.present?
other_people_with_details(xml_doc, attributes)
end
def other_people_with_details(xml_doc, attributes)
number_of_buyers = attributes["jointpur"] == 1 ? 2 : 1
highest_person_index_with_details = number_of_buyers
(2..6).each do |person_index|
age = string_or_nil(xml_doc, "P#{person_index}Age")
gender = string_or_nil(xml_doc, "P#{person_index}Sex")
relationship = string_or_nil(xml_doc, "P#{person_index}Rel")
economic_status = string_or_nil(xml_doc, "P#{person_index}Eco")
if gender.present? || age.present? || relationship.present? || economic_status.present?
highest_person_index_with_details = person_index
end
end
highest_person_index_with_details - number_of_buyers
end
def household_members(_xml_doc, attributes)
if attributes["jointpur"] == 2
attributes["hholdcount"] + 1
else
attributes["hholdcount"] + 2
end
end
def set_default_values(attributes) def set_default_values(attributes)
attributes["armedforcesspouse"] ||= 7 attributes["armedforcesspouse"] ||= 7
attributes["hhregres"] ||= 8 attributes["hhregres"] ||= 8
@ -404,7 +447,11 @@ module Imports
attributes["hb"] ||= 4 attributes["hb"] ||= 4
attributes["prevown"] ||= 3 attributes["prevown"] ||= 3
attributes["savingsnk"] ||= attributes["savings"].present? ? 0 : 1 attributes["savingsnk"] ||= attributes["savings"].present? ? 0 : 1
# attributes["noint"] = 1 # not interviewed attributes["jointmore"] ||= 3 if attributes["jointpur"] == 1
attributes["inc1mort"] ||= 3
if [attributes["pregyrha"], attributes["pregla"], attributes["pregghb"], attributes["pregother"]].all?(&:blank?)
attributes["pregblank"] = 1
end
# buyer 1 characteristics # buyer 1 characteristics
attributes["age1_known"] ||= 1 attributes["age1_known"] ||= 1
@ -414,7 +461,6 @@ module Imports
attributes["national"] ||= 13 attributes["national"] ||= 13
attributes["ecstat1"] ||= 10 attributes["ecstat1"] ||= 10
attributes["income1nk"] ||= attributes["income1"].present? ? 0 : 1 attributes["income1nk"] ||= attributes["income1"].present? ? 0 : 1
attributes["hholdcount"] ||= default_household_count(attributes) # just for testing, might need to change
# buyer 2 characteristics # buyer 2 characteristics
if attributes["jointpur"] == 1 if attributes["jointpur"] == 1
@ -422,6 +468,9 @@ module Imports
attributes["sex2"] ||= "R" attributes["sex2"] ||= "R"
attributes["ecstat2"] ||= 10 attributes["ecstat2"] ||= 10
attributes["income2nk"] ||= attributes["income2"].present? ? 0 : 1 attributes["income2nk"] ||= attributes["income2"].present? ? 0 : 1
attributes["relat2"] ||= "R"
attributes["inc2mort"] ||= 3
attributes["buy2livein"] ||= 1 unless attributes["ownershipsch"] == 3
end end
# other household members characteristics # other household members characteristics
@ -434,15 +483,8 @@ module Imports
end end
def missing_answers(sales_log) def missing_answers(sales_log)
applicable_questions = sales_log.form.subsections.map { |s| s.applicable_questions(sales_log) }.flatten applicable_questions = sales_log.form.subsections.map { |s| s.applicable_questions(sales_log).select { |q| q.enabled?(sales_log) } }.flatten
applicable_questions.filter { |q| q.unanswered?(sales_log) }.map(&:id) applicable_questions.filter { |q| q.unanswered?(sales_log) }.map(&:id)
end end
# just for testing, logic might need to change
def default_household_count(attributes)
return 0 if attributes["hhmemb"].zero? || attributes["hhmemb"].blank?
attributes["jointpur"] == 1 ? attributes["hhmemb"] - 2 : attributes["hhmemb"] - 1
end
end end
end end

8
app/views/bulk_upload_lettings_results/show.html.erb

@ -1,5 +1,7 @@
<% content_for :before_content do %> <% if BulkUploadErrorSummaryTableComponent.new(bulk_upload: @bulk_upload).errors? %>
<%= govuk_back_link(text: "Back", href: summary_bulk_upload_lettings_result_path(@bulk_upload)) %> <% content_for :before_content do %>
<%= govuk_back_link(text: "Back", href: summary_bulk_upload_lettings_result_path(@bulk_upload)) %>
<% end %>
<% end %> <% end %>
<div class="govuk-grid-row"> <div class="govuk-grid-row">
@ -22,3 +24,5 @@
<% end %> <% end %>
</div> </div>
</div> </div>
<%= govuk_button_link_to "Upload your file again", start_bulk_upload_lettings_logs_path %>

1
app/views/form/headers/_person_6_known_page.erb

@ -0,0 +1 @@
You have given us the details for <%= log.joint_purchase? ? 3 : 4 %> of the <%= log.hholdcount %> other people in the household

32
config/sale_range_data/2023.csv

@ -87,10 +87,10 @@ Boston,E07000136,1,58000,258000
Boston,E07000136,2,58000,258000 Boston,E07000136,2,58000,258000
Boston,E07000136,3,111000,308000 Boston,E07000136,3,111000,308000
Boston,E07000136,4,212000,510000 Boston,E07000136,4,212000,510000
Bournemouth, Christchurch and Poole,E06000058,1,140000,500000 "Bournemouth, Christchurch and Poole",E06000058,1,140000,500000
Bournemouth, Christchurch and Poole,E06000058,2,197000,500000 "Bournemouth, Christchurch and Poole",E06000058,2,197000,500000
Bournemouth, Christchurch and Poole,E06000058,3,285000,657000 "Bournemouth, Christchurch and Poole",E06000058,3,285000,657000
Bournemouth, Christchurch and Poole,E06000058,4,370000,1321000 "Bournemouth, Christchurch and Poole",E06000058,4,370000,1321000
Bracknell Forest,E06000036,1,95000,488000 Bracknell Forest,E06000036,1,95000,488000
Bracknell Forest,E06000036,2,157000,488000 Bracknell Forest,E06000036,2,157000,488000
Bracknell Forest,E06000036,3,341000,654000 Bracknell Forest,E06000036,3,341000,654000
@ -119,10 +119,10 @@ Brighton and Hove,E06000043,1,185000,526000
Brighton and Hove,E06000043,2,270000,610000 Brighton and Hove,E06000043,2,270000,610000
Brighton and Hove,E06000043,3,350000,846000 Brighton and Hove,E06000043,3,350000,846000
Brighton and Hove,E06000043,4,458000,1487000 Brighton and Hove,E06000043,4,458000,1487000
Bristol, City of,E06000023,1,145000,417000 "Bristol, City of",E06000023,1,145000,417000
Bristol, City of,E06000023,2,184000,562000 "Bristol, City of",E06000023,2,184000,562000
Bristol, City of,E06000023,3,242000,685000 "Bristol, City of",E06000023,3,242000,685000
Bristol, City of,E06000023,4,331000,1394000 "Bristol, City of",E06000023,4,331000,1394000
Broadland,E07000144,1,126000,334000 Broadland,E07000144,1,126000,334000
Broadland,E07000144,2,140000,334000 Broadland,E07000144,2,140000,334000
Broadland,E07000144,3,225000,433000 Broadland,E07000144,3,225000,433000
@ -459,10 +459,10 @@ Havering,E09000016,1,137000,472000
Havering,E09000016,2,204000,481000 Havering,E09000016,2,204000,481000
Havering,E09000016,3,336000,657000 Havering,E09000016,3,336000,657000
Havering,E09000016,4,412000,1232000 Havering,E09000016,4,412000,1232000
Herefordshire, County of,E06000019,1,98000,419000 "Herefordshire, County of",E06000019,1,98000,419000
Herefordshire, County of,E06000019,2,105000,419000 "Herefordshire, County of",E06000019,2,105000,419000
Herefordshire, County of,E06000019,3,162000,499000 "Herefordshire, County of",E06000019,3,162000,499000
Herefordshire, County of,E06000019,4,283000,885000 "Herefordshire, County of",E06000019,4,283000,885000
Hertsmere,E07000098,1,178000,666000 Hertsmere,E07000098,1,178000,666000
Hertsmere,E07000098,2,316000,666000 Hertsmere,E07000098,2,316000,666000
Hertsmere,E07000098,3,440000,918000 Hertsmere,E07000098,3,440000,918000
@ -515,10 +515,10 @@ King's Lynn and West Norfolk,E07000146,1,77000,346000
King's Lynn and West Norfolk,E07000146,2,123000,346000 King's Lynn and West Norfolk,E07000146,2,123000,346000
King's Lynn and West Norfolk,E07000146,3,161000,408000 King's Lynn and West Norfolk,E07000146,3,161000,408000
King's Lynn and West Norfolk,E07000146,4,243000,778000 King's Lynn and West Norfolk,E07000146,4,243000,778000
Kingston upon Hull, City of,E06000010,1,63000,189000 "Kingston upon Hull, City of",E06000010,1,63000,189000
Kingston upon Hull, City of,E06000010,2,67000,189000 "Kingston upon Hull, City of",E06000010,2,67000,189000
Kingston upon Hull, City of,E06000010,3,84000,259000 "Kingston upon Hull, City of",E06000010,3,84000,259000
Kingston upon Hull, City of,E06000010,4,110000,415000 "Kingston upon Hull, City of",E06000010,4,110000,415000
Kingston upon Thames,E09000021,1,156000,649000 Kingston upon Thames,E09000021,1,156000,649000
Kingston upon Thames,E09000021,2,325000,708000 Kingston upon Thames,E09000021,2,325000,708000
Kingston upon Thames,E09000021,3,398000,935000 Kingston upon Thames,E09000021,3,398000,935000

Can't render this file because it has a wrong number of fields in line 90.

5
db/migrate/20230301144555_add_pregblank.rb

@ -0,0 +1,5 @@
class AddPregblank < ActiveRecord::Migration[7.0]
def change
add_column :sales_logs, :pregblank, :integer
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_02_15_112932) do ActiveRecord::Schema[7.0].define(version: 2023_03_01_144555) 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"
@ -522,15 +522,16 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_15_112932) do
t.integer "income2_value_check" t.integer "income2_value_check"
t.integer "monthly_charges_value_check" t.integer "monthly_charges_value_check"
t.integer "value_value_check" t.integer "value_value_check"
t.integer "saledate_check"
t.integer "details_known_5" t.integer "details_known_5"
t.integer "details_known_6" t.integer "details_known_6"
t.integer "saledate_check"
t.integer "prevshared"
t.integer "staircasesale"
t.integer "ethnic_group2" t.integer "ethnic_group2"
t.integer "ethnicbuy2" t.integer "ethnicbuy2"
t.integer "proplen_asked" t.integer "proplen_asked"
t.integer "prevshared"
t.integer "staircasesale"
t.string "old_id" t.string "old_id"
t.integer "pregblank"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.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 ["old_id"], name: "index_sales_logs_on_old_id", unique: true t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true

1
db/seeds.rb

@ -324,6 +324,5 @@ unless Rails.env.test?
service.call service.call
end end
end end
puts LaSaleRange.count
end end
# rubocop:enable Rails/Output # rubocop:enable Rails/Output

1
lib/tasks/full_import.rake

@ -18,6 +18,7 @@ namespace :core do
Import.new(Imports::DataProtectionConfirmationImportService, :create_data_protection_confirmations, "dataprotect"), Import.new(Imports::DataProtectionConfirmationImportService, :create_data_protection_confirmations, "dataprotect"),
Import.new(Imports::OrganisationRentPeriodImportService, :create_organisation_rent_periods, "rent-period"), Import.new(Imports::OrganisationRentPeriodImportService, :create_organisation_rent_periods, "rent-period"),
Import.new(Imports::LettingsLogsImportService, :create_logs, "logs"), Import.new(Imports::LettingsLogsImportService, :create_logs, "logs"),
# Import.new(Imports::SalesLogsImportService, :create_logs, "logs"),
] ]
import_list.each do |step| import_list.each do |step|

35
spec/components/bulk_upload_error_summary_table_component_spec.rb

@ -5,6 +5,10 @@ RSpec.describe BulkUploadErrorSummaryTableComponent, type: :component do
let(:bulk_upload) { create(:bulk_upload) } let(:bulk_upload) { create(:bulk_upload) }
before do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 0)
end
context "when no errors" do context "when no errors" do
it "does not renders any rows" do it "does not renders any rows" do
result = render_inline(component) result = render_inline(component)
@ -12,6 +16,19 @@ RSpec.describe BulkUploadErrorSummaryTableComponent, type: :component do
end end
end end
context "when below threshold" do
before do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 16)
create(:bulk_upload_error, bulk_upload:, col: "A", row: 1)
end
it "does not render rows" do
result = render_inline(component)
expect(result).to have_selector("tbody tr", count: 0)
end
end
context "when there are 2 independent errors" do context "when there are 2 independent errors" do
let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) } let!(:error_2) { create(:bulk_upload_error, bulk_upload:, col: "B", row: 2) }
let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) } let!(:error_1) { create(:bulk_upload_error, bulk_upload:, col: "A", row: 1) }
@ -78,4 +95,22 @@ RSpec.describe BulkUploadErrorSummaryTableComponent, type: :component do
]) ])
end end
end end
describe "#errors?" do
context "when there are no errors" do
it "returns false" do
expect(component).not_to be_errors
end
end
context "when there are errors" do
before do
create(:bulk_upload_error, bulk_upload:, col: "A", row: 2, field: "field_1")
end
it "returns true" do
expect(component).to be_errors
end
end
end
end end

333
spec/fixtures/imports/logs/shared_ownership_sales_log.xml vendored

@ -0,0 +1,333 @@
<Group xmlns="http://data.gov.uk/core/logs/2022-CORE-Sales" xmlns:app="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:meta="http://data.gov.uk/core/metadata" xmlns:svc="http://www.w3.org/2007/app" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xfimpl="http://www.w3.org/2002/xforms/implementation" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xxf="http://orbeon.org/oxf/xml/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<meta:metadata xmlns:es="http://www.ecmascript.org/" xmlns:xqx="http://www.w3.org/2005/XQueryX" xmlns:XSLT="http://www.w3.org/1999/XSL/Transform/compile">
<meta:form-name>2022-CORE-Sales</meta:form-name>
<meta:document-id>shared_ownership_sales_log</meta:document-id>
<meta:owner-user-id>c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa</meta:owner-user-id>
<meta:owner-institution-id>7c5bd5fb549c09a2c55d7cb90d7ba84927e64618</meta:owner-institution-id>
<meta:managing-institution-id>7c5bd5fb549c09a2c55d7cb90d7ba84927e64618</meta:managing-institution-id>
<meta:created-date>2023-02-21T11:48:28.255968Z</meta:created-date>
<meta:modified-date>2023-02-22T11:00:06.575832Z</meta:modified-date>
<meta:status>submitted-valid</meta:status>
<meta:reporting-year>2022</meta:reporting-year>
<meta:upload-method>Manual Entry</meta:upload-method>
<meta:schema assert-valid="true"/>
<meta:rules assert-valid="true"/>
</meta:metadata>
<Group>
<Qdp>Yes</Qdp>
<CompletionDate>2023-01-17</CompletionDate>
<PurchaserCode>Shared ownership example</PurchaserCode>
<Ownership>1 Yes - a shared ownership scheme</Ownership>
<Q16SaleType>2 Shared Ownership</Q16SaleType>
<Q30SaleType/>
<Q38SaleType/>
<Q38OtherSale/>
<company>2 No</company>
<LiveInBuyer>1 Yes</LiveInBuyer>
<joint>2 No</joint>
<JointMore/>
<PartAPurchaser>2 Yes</PartAPurchaser>
</Group>
<Group>
<Q11Bedrooms override-field="">2</Q11Bedrooms>
<Q12PropertyType>1 Flat or maisonette</Q12PropertyType>
<Q13BuildingType>1 Purpose built</Q13BuildingType>
<Q14Postcode override-field="">SW1A 1AA</Q14Postcode>
<Q14PropertyLocation>Westminster</Q14PropertyLocation>
<Q14ONSLACode>E09000033</Q14ONSLACode>
<Q15Wheelchair>3 Don&#x2019;t know</Q15Wheelchair>
</Group>
<Group>
<P1Age>30</P1Age>
<P1Sex override-field="">Male</P1Sex>
<P1Eco>1 Full Time - 30 hours or more a week</P1Eco>
<P1Eth>2 White: Irish</P1Eth>
<P1Nat>18 United Kingdom</P1Nat>
<P2Age/>
<P2Sex override-field=""/>
<P2Rel/>
<P2Eco/>
<P3Age/>
<P3Sex override-field=""/>
<P3Rel/>
<P3Eco/>
<P4Age/>
<P4Sex override-field=""/>
<P4Rel/>
<P4Eco/>
<P5Age/>
<P5Sex override-field=""/>
<P5Rel/>
<P5Eco/>
<P6Age/>
<P6Sex override-field=""/>
<P6Rel/>
<P6Eco/>
<P7Age/>
<P7Sex override-field=""/>
<P7Rel/>
<P7Eco/>
<P8Age/>
<P8Sex override-field=""/>
<P8Rel/>
<P8Eco/>
<LiveInBuyer1>1 Yes</LiveInBuyer1>
<LiveInBuyer2/>
<LiveInOther/>
</Group>
<Group>
<P2Partner>0</P2Partner>
<P3Partner>0</P3Partner>
<P4Partner>0</P4Partner>
<P5Partner>0</P5Partner>
<P6Partner>0</P6Partner>
<P7Partner>0</P7Partner>
<P8Partner>0</P8Partner>
<Partner>0</Partner>
<P2AgeT>0</P2AgeT>
<P3AgeT>0</P3AgeT>
<P4AgeT>0</P4AgeT>
<P5AgeT>0</P5AgeT>
<P6AgeT>0</P6AgeT>
<P7AgeT>0</P7AgeT>
<P8AgeT>0</P8AgeT>
<P2SexT>0</P2SexT>
<P3SexT>0</P3SexT>
<P4SexT>0</P4SexT>
<P5SexT>0</P5SexT>
<P6SexT>0</P6SexT>
<P7SexT>0</P7SexT>
<P8SexT>0</P8SexT>
<P2RelT>0</P2RelT>
<P3RelT>0</P3RelT>
<P4RelT>0</P4RelT>
<P5RelT>0</P5RelT>
<P6RelT>0</P6RelT>
<P7RelT>0</P7RelT>
<P8RelT>0</P8RelT>
<P2EcoT>0</P2EcoT>
<P3EcoT>0</P3EcoT>
<P4EcoT>0</P4EcoT>
<P5EcoT>0</P5EcoT>
<P6EcoT>0</P6EcoT>
<P7EcoT>0</P7EcoT>
<P8EcoT>0</P8EcoT>
<P2HHoldT>0</P2HHoldT>
<P3HHoldT>0</P3HHoldT>
<P4HHoldT>0</P4HHoldT>
<P5HHoldT>0</P5HHoldT>
<P6HHoldT>0</P6HHoldT>
<P7HHoldT>0</P7HHoldT>
<P8HHoldT>0</P8HHoldT>
<P2PAge>0</P2PAge>
<P3PAge>0</P3PAge>
<P4PAge>0</P4PAge>
<P5PAge>0</P5PAge>
<P6PAge>0</P6PAge>
<P7PAge>0</P7PAge>
<P8PAge>0</P8PAge>
<PAGE/>
<Q30Answer/>
<P2Other>0</P2Other>
<P3Other>0</P3Other>
<P4Other>0</P4Other>
<P5Other>0</P5Other>
<P6Other>0</P6Other>
<P7Other>0</P7Other>
<P8Other>0</P8Other>
<Other>0</Other>
<P2RRefused>0</P2RRefused>
<P3RRefused>0</P3RRefused>
<P4RRefused>0</P4RRefused>
<P5RRefused>0</P5RRefused>
<P6RRefused>0</P6RRefused>
<P7RRefused>0</P7RRefused>
<P8RRefused>0</P8RRefused>
<TotRRefused>0</TotRRefused>
<CALCMORT>76000</CALCMORT>
<MORTGAGEUSED>1</MORTGAGEUSED>
<IM1>47000</IM1>
<IM2>0</IM2>
<IMT>235000</IMT>
<MortMultiple>0</MortMultiple>
<Form>300204</Form>
</Group>
<Group>
<minmaxP11/>
<minmaxP12/>
<minmaxP13/>
<minmaxP14/>
<minmaxP15/>
<minmaxP16/>
<minmaxP17/>
<minmaxP18/>
<minmaxP1T/>
<minmaxP19/>
<minmaxP10/>
<minmaxP21/>
<minmaxP22/>
<minmaxP23/>
<minmaxP24/>
<minmaxP25/>
<minmaxP26/>
<minmaxP27/>
<minmaxP28/>
<minmaxP2T/>
<minmaxP29/>
<minmaxP20/>
<Q16CHK>1</Q16CHK>
<Q30CHK>0</Q30CHK>
<Q38CHK>0</Q38CHK>
<SalesCHKT>1</SalesCHKT>
<Q23CHK>1</Q23CHK>
<Q16typeCHK>2</Q16typeCHK>
<Q16Q23>3</Q16Q23>
<DAY>17</DAY>
<MONTH>1</MONTH>
<YEAR>2023</YEAR>
<HODAY>6</HODAY>
<HOMONTH>9</HOMONTH>
<HOYEAR>2022</HOYEAR>
<EXDAY>8</EXDAY>
<EXMONTH>1</EXMONTH>
<EXYEAR>2023</EXYEAR>
<PPOSTC1>SW14</PPOSTC1>
<PPOSTC2>7QP</PPOSTC2>
<PCODE1>SW1A</PCODE1>
<PCODE2>1AA</PCODE2>
<NOINT/>
</Group>
<Group>
<Q6PrevTenure>2 Private registered provider (PRP) or housing association tenant</Q6PrevTenure>
<Q7Postcode override-field="">SW14 7QP</Q7Postcode>
<Q7UnknownPostcode/>
<Q7PrevLocation>Richmond-upon-Thames</Q7PrevLocation>
<Q7ONSLACode>E09000027</Q7ONSLACode>
<PREGYRHA>Yes</PREGYRHA>
<PREGORHA/>
<PREGLA/>
<PREGHBA/>
<PREGOTHER/>
</Group>
<Group>
<ArmedF>8 Don&#x2019;t know</ArmedF>
<LeftArmedF/>
<ARMEDFORCESSPOUSE/>
<Disability>2 No</Disability>
<Q10Wheelchair override-field="">2 No</Q10Wheelchair>
</Group>
<Group>
<P1IncKnown>1 Yes</P1IncKnown>
<Q2Person1Income>47000</Q2Person1Income>
<Q2Person1Mortgage>1 Yes</Q2Person1Mortgage>
<P2IncKnown/>
<Q2Person2Income/>
<Q2Person2MortApplication/>
<Q2a>4 Don&#x2019;t know</Q2a>
<savingsKnown>1 Yes</savingsKnown>
<Q3Savings override-field="true">89000</Q3Savings>
<Q4PrevOwnedProperty>1 Yes</Q4PrevOwnedProperty>
</Group>
<Group>
<!-- replace with commented options to test in the future -->
<!-- <Q16aProplen2/> -->
<Q16aProplen2>1</Q16aProplen2>
<Q17aStaircase>2 No</Q17aStaircase>
<PercentBought override-field=""/>
<PercentOwns>30</PercentOwns>
<Q17Resale>2 No</Q17Resale>
<Q18ContractExchange override-field="">2023-01-08</Q18ContractExchange>
<Q18PracticalCompletion override-field="">2022-09-06</Q18PracticalCompletion>
<Q19Rehoused>2 No</Q19Rehoused>
<Q20Bedrooms/>
<Q21PropertyType/>
<PrevRentType/>
<Q22PurchasePrice override-field="true">550000</Q22PurchasePrice>
<Q23Equity override-field="">30</Q23Equity>
<MortgageUsedSO>1 Yes</MortgageUsedSO>
<Q24Mortgage override-field="">76000</Q24Mortgage>
<Q24aMortgageLender>Nationwide</Q24aMortgageLender>
<Q24b>33</Q24b>
<Q25Borrowing>2 No</Q25Borrowing>
<Q26CashDeposit override-field="">89000</Q26CashDeposit>
<Q27SocialHomeBuy/>
<Q28MonthlyRent>912.00</Q28MonthlyRent>
<Q29MonthlyCharges>134.24</Q29MonthlyCharges>
</Group>
<Group>
<Q16aProplensec2/>
<Q31PurchasePrice override-field=""/>
<Q32Reductions override-field=""/>
<Q33Discount override-field=""/>
<MortgageUsedDO/>
<Q34Mortgage override-field=""/>
<Q34a/>
<Q34b/>
<Q35Borrowing/>
<Q36CashDeposit/>
<Q37MonthlyCharges/>
</Group>
<Group>
<Q40PurchasePrice override-field=""/>
<MortgageUsedOS/>
<Q41Mortgage override-field=""/>
<Q41aMortgageLender/>
<Q41b/>
<Q42Borrowing/>
<Q43CashDeposit override-field=""/>
</Group>
<Group>
<HHMEMB>1</HHMEMB>
<TOTADULT>1</TOTADULT>
<TOTCHILD>0</TOTCHILD>
</Group>
<Group>
<HHTYPE>3 = 1 adult</HHTYPE>
</Group>
<Group>
<DerSaleType>2 Shared Ownership</DerSaleType>
</Group>
<Group>
<HHTYPEP1A>1</HHTYPEP1A>
<HHTYPEP2A>0</HHTYPEP2A>
<HHTYPEP3A>0</HHTYPEP3A>
<HHTYPEP4A>0</HHTYPEP4A>
<HHTYPEP5A>0</HHTYPEP5A>
<HHTYPEP6A>0</HHTYPEP6A>
<HHTYPEP7A>0</HHTYPEP7A>
<HHTYPEP8A>0</HHTYPEP8A>
<TADULT>1</TADULT>
<HHTYPEP1E>0</HHTYPEP1E>
<HHTYPEP2E>0</HHTYPEP2E>
<HHTYPEP3E>0</HHTYPEP3E>
<HHTYPEP4E>0</HHTYPEP4E>
<HHTYPEP5E>0</HHTYPEP5E>
<HHTYPEP6E>0</HHTYPEP6E>
<HHTYPEP7E>0</HHTYPEP7E>
<HHTYPEP8E>0</HHTYPEP8E>
<TELDER>0</TELDER>
<HHTYPEP1C>0</HHTYPEP1C>
<HHTYPEP2C>0</HHTYPEP2C>
<HHTYPEP3C>0</HHTYPEP3C>
<HHTYPEP4C>0</HHTYPEP4C>
<HHTYPEP5C>0</HHTYPEP5C>
<HHTYPEP6C>0</HHTYPEP6C>
<HHTYPEP7C>0</HHTYPEP7C>
<HHTYPEP8C>0</HHTYPEP8C>
<TCHILD>0</TCHILD>
<Q8av>1</Q8av>
<Q8bv>0</Q8bv>
<Q8cv>0</Q8cv>
<Q8dv>0</Q8dv>
<Q8ev>0</Q8ev>
<Q8Validate>1</Q8Validate>
</Group>
<Group>
<PLOACODE/>
<OACODE/>
<GOVREG>E12000007</GOVREG>
<OWNINGORGID>1</OWNINGORGID>
<OWNINGORGNAME>1 Test</OWNINGORGNAME>
<HCNUM>655</HCNUM>
</Group>
</Group>

2
spec/fixtures/imports/sales_logs/discounted_ownership_sales_log.xml vendored

@ -292,7 +292,7 @@
<Q43CashDeposit override-field=""/> <Q43CashDeposit override-field=""/>
</Group> </Group>
<Group> <Group>
<HHMEMB>0</HHMEMB> <HHMEMB>1</HHMEMB>
<TOTADULT>0</TOTADULT> <TOTADULT>0</TOTADULT>
<TOTCHILD>0</TOTCHILD> <TOTCHILD>0</TOTCHILD>
</Group> </Group>

524
spec/fixtures/imports/sales_logs/lettings_log.xml vendored

@ -0,0 +1,524 @@
<Group xmlns="http://data.gov.uk/core/logs/2021-CORE-SR-SH" xmlns:app="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:meta="http://data.gov.uk/core/metadata" xmlns:svc="http://www.w3.org/2007/app" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:xfimpl="http://www.w3.org/2002/xforms/implementation" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xxf="http://orbeon.org/oxf/xml/xforms" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<meta:metadata xmlns:es="http://www.ecmascript.org/" xmlns:xqx="http://www.w3.org/2005/XQueryX" xmlns:XSLT="http://www.w3.org/1999/XSL/Transform/compile">
<meta:form-name>2021-CORE-SR-SH</meta:form-name>
<meta:document-id>lettings_log</meta:document-id>
<meta:owner-user-id>c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa</meta:owner-user-id>
<meta:owner-institution-id>7c5bd5fb549c09z2c55d9cb90d7ba84927e64618</meta:owner-institution-id>
<meta:managing-institution-id>7c5bd5fb549c09z2c55d9cb90d7ba84927e64618</meta:managing-institution-id>
<meta:created-date>2022-01-05T12:50:20.39153Z</meta:created-date>
<meta:modified-date>2022-01-05T12:50:20.39153Z</meta:modified-date>
<meta:status>submitted-valid</meta:status>
<meta:reporting-year>2021</meta:reporting-year>
<meta:upload-method>Manual Entry</meta:upload-method>
<meta:schema assert-valid="true"/>
<meta:rules assert-valid="true"/>
</meta:metadata>
<Group>
<Qdp>Yes</Qdp>
<KeyDate>2021-11-05</KeyDate>
<FORM>123456</FORM>
<Landlord source-value="2">2 Local Authority</Landlord>
<Group>
<_1cmangroupcode>0123</_1cmangroupcode>
<_1cschemecode>10</_1cschemecode>
<schPC/>
<Q1e>3 No</Q1e>
</Group>
</Group>
<Group>
<_2a>2 No</_2a>
<Q2b>1 Secure (inc flexible)</Q2b>
<Q2ba/>
<_2bTenCode>14044912001</_2bTenCode>
<_2cYears>2</_2cYears>
</Group>
<Group>
<P1Age override-field="">72</P1Age>
<P1AR/>
<P1Sex override-field="">Female</P1Sex>
<P1Eco>5) Retired</P1Eco>
<P1Eth>1 White: English/Scottish/Welsh/Northern Irish/British</P1Eth>
<P1Nat>1 UK national resident in UK</P1Nat>
<P2Age override-field="">74</P2Age>
<P2AR/>
<P2Sex override-field="">Male</P2Sex>
<P2Rel>Partner</P2Rel>
<P2Eco>5) Retired</P2Eco>
<P3Age override-field=""/>
<P3AR/>
<P3Sex override-field=""/>
<P3Rel/>
<P3Eco/>
<P4Age override-field=""/>
<P4AR/>
<P4Sex override-field=""/>
<P4Rel/>
<P4Eco/>
<P5Age override-field=""/>
<P5AR/>
<P5Sex override-field=""/>
<P5Rel/>
<P5Eco/>
<P6Age override-field=""/>
<P6AR/>
<P6Sex override-field=""/>
<P6Rel/>
<P6Eco/>
<P7Age override-field=""/>
<P7AR/>
<P7Sex override-field=""/>
<P7Rel/>
<P7Eco/>
<P8Age override-field=""/>
<P8AR/>
<P8Sex override-field=""/>
<P8Rel/>
<P8Eco/>
<Group>
<ArmedF>2 No</ArmedF>
<LeftAF/>
<Inj/>
<Preg override-field="">2 No</Preg>
</Group>
<Group>
<Q6Ben>9 Not in receipt of either UC or HB</Q6Ben>
</Group>
<Group>
<Q7Ben>2 Some</Q7Ben>
<Q8Refused>Refused</Q8Refused>
<Q8Money override-field=""/>
<Q8a/>
</Group>
<Group>
<Q9a>13 Property unsuitable because of ill health / disability</Q9a>
<Q9aa/>
</Group>
<Group>
<_9b override-field="">2 No</_9b>
<Q10-a/>
<Q10-b/>
<Q10-c/>
<Q10-f/>
<Q10-g>Yes</Q10-g>
<Q10-h/>
<Q10ia>1 Yes</Q10ia>
<Q10ib-1/>
<Q10ib-2/>
<Q10ib-3>Yes</Q10ib-3>
<Q10ib-4/>
<Q10ib-5/>
<Q10ib-6/>
<Q10ib-7/>
<Q10ib-8/>
<Q10ib-9/>
<Q10ib-10/>
<Q11 override-field="">26 Owner occupation (private)</Q11>
<Q12a>DLUHC</Q12a>
<Q12aONS>E08000035</Q12aONS>
<Q12b override-field="">S80 4DJ</Q12b>
<Q12bnot/>
<Q12c>5 5 years or more</Q12c>
<Q12d>9 3 years but under 4 years</Q12d>
</Group>
<Group>
<Q13>1 Not homeless</Q13>
<Q14a>2 No</Q14a>
<Q14b1/>
<Q14b2/>
<Q14b3/>
<Q14b4/>
<Q14b5/>
</Group>
<Group>
<Q15CBL>1 Yes</Q15CBL>
<Q15CHR>1 Yes</Q15CHR>
<Q15CAP>1 Yes</Q15CAP>
</Group>
<Group>
<Q16>2 Tenant applied direct (no referral or nomination)</Q16>
</Group>
</Group>
<Group>
<Q17>7 Weekly for 48 weeks</Q17>
<Q18ai override-field="true">125.00</Q18ai>
<Q18aii override-field=""/>
<Q18aiii override-field=""/>
<Q18aiv override-field="">7.00</Q18aiv>
<Q18av override-field="">132.00</Q18av>
<Q18b override-field=""/>
<Q18c/>
<Q18d/>
<Q18dyes override-field=""/>
<Q19void>2021-08-24</Q19void>
<Q19repair/>
<Q19supsch/>
<Q20 override-field="">0</Q20>
<Q21a>14044912</Q21a>
</Group>
<Group>
<Q25>1 Yes</Q25>
<Q27>15 First let of newbuild property</Q27>
</Group>
<Group>
<F1Age>0</F1Age>
<F2Age>0</F2Age>
<F3Age>0</F3Age>
<F4Age>0</F4Age>
<F5Age>0</F5Age>
<F6Age>0</F6Age>
<F7Age>0</F7Age>
<F8Age>0</F8Age>
<FAge>0</FAge>
<F1>1</F1>
<F2>0</F2>
<F3>0</F3>
<F4>0</F4>
<F5>0</F5>
<F6>0</F6>
<F7>0</F7>
<F8>0</F8>
<F>1</F>
<P1100>0</P1100>
<P2100>0</P2100>
<P3100>0</P3100>
<P4100>0</P4100>
<P5100>0</P5100>
<P6100>0</P6100>
<P7100>0</P7100>
<P8100>0</P8100>
<_100>0</_100>
<P170>1</P170>
<P270>1</P270>
<P370>0</P370>
<P470>0</P470>
<P570>0</P570>
<P670>0</P670>
<P770>0</P770>
<P870>0</P870>
<_70>1</_70>
<P1PT>0</P1PT>
<P2PT>0</P2PT>
<P3PT>0</P3PT>
<P4PT>0</P4PT>
<P5PT>0</P5PT>
<P6PT>0</P6PT>
<P7PT>0</P7PT>
<P8PT>0</P8PT>
<PT>0</PT>
<P1FT>0</P1FT>
<P2FT>0</P2FT>
<P3FT>0</P3FT>
<P4FT>0</P4FT>
<P5FT>0</P5FT>
<P6FT>0</P6FT>
<P7FT>0</P7FT>
<P8FT>0</P8FT>
<FT>0</FT>
<P1Stud>0</P1Stud>
<P2Stud>0</P2Stud>
<P3Stud>0</P3Stud>
<P4Stud>0</P4Stud>
<P5Stud>0</P5Stud>
<P6Stud>0</P6Stud>
<P7Stud>0</P7Stud>
<P8Stud>0</P8Stud>
<Stud>0</Stud>
<P2Child>0</P2Child>
<P3Child>0</P3Child>
<P4Child>0</P4Child>
<P5Child>0</P5Child>
<P6Child>0</P6Child>
<P7Child>0</P7Child>
<P8Child>0</P8Child>
<Child>0</Child>
<P2Partner>1</P2Partner>
<P3Partner>0</P3Partner>
<P4Partner>0</P4Partner>
<P5Partner>0</P5Partner>
<P6Partner>0</P6Partner>
<P7Partner>0</P7Partner>
<P8Partner>0</P8Partner>
<Partner>1</Partner>
<Q1cV1>1</Q1cV1>
<Q1cV2>1</Q1cV2>
<Q1cVT>2</Q1cVT>
<P1Adult>1</P1Adult>
<P2Adult>1</P2Adult>
<P3Adult>0</P3Adult>
<P4Adult>0</P4Adult>
<P5Adult>0</P5Adult>
<P6Adult>0</P6Adult>
<P7Adult>0</P7Adult>
<P8Adult>0</P8Adult>
<PAdultT>2</PAdultT>
<P2PAge>74</P2PAge>
<P3PAge>0</P3PAge>
<P4PAge>0</P4PAge>
<P5PAge>0</P5PAge>
<P6PAge>0</P6PAge>
<P7PAge>0</P7PAge>
<P8PAge>0</P8PAge>
<PAGE>74</PAGE>
<P2ChildAge>0</P2ChildAge>
<P3ChildAge>0</P3ChildAge>
<P4ChildAge>0</P4ChildAge>
<P5ChildAge>0</P5ChildAge>
<P6ChildAge>0</P6ChildAge>
<P7ChildAge>0</P7ChildAge>
<P8ChildAge>0</P8ChildAge>
<ChildAgeMin>0</ChildAgeMin>
<AgeDiff1>72</AgeDiff1>
<AgeDiff2>0</AgeDiff2>
<AgeDiff3>74</AgeDiff3>
<TODAY>2022-01-05Z</TODAY>
<FutureLimit>2022-01-20Z</FutureLimit>
<minmax1/>
<minmax2/>
<minmax3/>
<minmax4/>
<minmax5/>
<minmax6/>
<minmax7/>
<minmax8/>
<minmax9/>
<minmax0/>
<minmax10/>
<minmaxT/>
<Q10av>0</Q10av>
<Q10bv>0</Q10bv>
<Q10cv>0</Q10cv>
<Q10fv>0</Q10fv>
<Q10gv>20</Q10gv>
<Q10hv>0</Q10hv>
<Q10Validate>20</Q10Validate>
<Q2bv>A</Q2bv>
<P2Agev>1</P2Agev>
<P2Sexv>1</P2Sexv>
<P2Relv>1</P2Relv>
<P2Ecov>1</P2Ecov>
<P2valid>4</P2valid>
<P3Agev>0</P3Agev>
<P3Sexv>0</P3Sexv>
<P3Relv>0</P3Relv>
<P3Ecov>0</P3Ecov>
<P3valid>0</P3valid>
<P4Agev>0</P4Agev>
<P4Sexv>0</P4Sexv>
<P4Relv>0</P4Relv>
<P4Ecov>0</P4Ecov>
<P4valid>0</P4valid>
<P5Agev>0</P5Agev>
<P5Sexv>0</P5Sexv>
<P5Relv>0</P5Relv>
<P5Ecov>0</P5Ecov>
<P5valid>0</P5valid>
<P6Agev>0</P6Agev>
<P6Sexv>0</P6Sexv>
<P6Relv>0</P6Relv>
<P6Ecov>0</P6Ecov>
<P6valid>0</P6valid>
<P7Agev>0</P7Agev>
<P7Sexv>0</P7Sexv>
<P7Relv>0</P7Relv>
<P7Ecov>0</P7Ecov>
<P7valid>0</P7valid>
<P8Agev>0</P8Agev>
<P8Sexv>0</P8Sexv>
<P8Relv>0</P8Relv>
<P8Ecov>0</P8Ecov>
<P8valid>0</P8valid>
<Q14b1v>0</Q14b1v>
<Q14b2v>0</Q14b2v>
<Q14b3v>0</Q14b3v>
<Q14b4v>0</Q14b4v>
<Q14b5v>0</Q14b5v>
<Q14bv>0</Q14bv>
<P2Other>0</P2Other>
<P3Other>0</P3Other>
<P4Other>0</P4Other>
<P5Other>0</P5Other>
<P6Other>0</P6Other>
<P7Other>0</P7Other>
<P8Other>0</P8Other>
<Other>0</Other>
<P2ARefused>0</P2ARefused>
<P3ARefused>0</P3ARefused>
<P4ARefused>0</P4ARefused>
<P5ARefused>0</P5ARefused>
<P6ARefused>0</P6ARefused>
<P7ARefused>0</P7ARefused>
<P8ARefused>0</P8ARefused>
<TAREUSED>0</TAREUSED>
<P2RRefused>0</P2RRefused>
<P3RRefused>0</P3RRefused>
<P4RRefused>0</P4RRefused>
<P5RRefused>0</P5RRefused>
<P6RRefused>0</P6RRefused>
<P7RRefused>0</P7RRefused>
<P8RRefused>0</P8RRefused>
<TotRRefused>0</TotRRefused>
<TOTREFUSED>0</TOTREFUSED>
</Group>
<Group>
<ChildBen>0.00</ChildBen>
<TOTADULT>2</TOTADULT>
<NEW_OLD>1 New Tenant</NEW_OLD>
<WCHCHRG/>
<VACDAYS>73</VACDAYS>
<HHMEMB>2</HHMEMB>
<HHTYPEP1A>0</HHTYPEP1A>
<HHTYPEP2A>0</HHTYPEP2A>
<HHTYPEP3A>0</HHTYPEP3A>
<HHTYPEP4A>0</HHTYPEP4A>
<HHTYPEP5A>0</HHTYPEP5A>
<HHTYPEP6A>0</HHTYPEP6A>
<HHTYPEP7A>0</HHTYPEP7A>
<HHTYPEP8A>0</HHTYPEP8A>
<TADULT>0</TADULT>
<HHTYPEP1E>1</HHTYPEP1E>
<HHTYPEP2E>1</HHTYPEP2E>
<HHTYPEP3E>0</HHTYPEP3E>
<HHTYPEP4E>0</HHTYPEP4E>
<HHTYPEP5E>0</HHTYPEP5E>
<HHTYPEP6E>0</HHTYPEP6E>
<HHTYPEP7E>0</HHTYPEP7E>
<HHTYPEP8E>0</HHTYPEP8E>
<TELDER>2</TELDER>
<HHTYPEP1C>0</HHTYPEP1C>
<HHTYPEP2C>0</HHTYPEP2C>
<HHTYPEP3C>0</HHTYPEP3C>
<HHTYPEP4C>0</HHTYPEP4C>
<HHTYPEP5C>0</HHTYPEP5C>
<HHTYPEP6C>0</HHTYPEP6C>
<HHTYPEP7C>0</HHTYPEP7C>
<HHTYPEP8C>0</HHTYPEP8C>
<TCHILD>0</TCHILD>
<Q18aValid>1</Q18aValid>
<Q18bValid>0</Q18bValid>
<Q18cValid>0</Q18cValid>
<Q18Valid>1</Q18Valid>
<HHTYPE>2 = 2 Adults at least one is an Elder</HHTYPE>
<WEEKLYINC/>
<INCOME/>
<TYPEHB>15.00</TYPEHB>
<AFFRATE/>
<Weekinc/>
<LETTYPE>2 Local Authority</LETTYPE>
<PLOACODE/>
<OACODE/>
<GOVREG>E12000004</GOVREG>
<OWNINGORGID>1</OWNINGORGID>
<OWNINGORGNAME>DLUHC</OWNINGORGNAME>
<MANINGORGNAME>DLUHC</MANINGORGNAME>
<HCNUM>N/A</HCNUM>
<MANHCNUM>N/A</MANHCNUM>
<LAHA/>
<MANINGORGID>2</MANINGORGID>
<Q28same1>false</Q28same1>
<HBTYPE1/>
<HBTYPE2/>
<HBTYPE3/>
<HBTYPE4/>
<HBTYPE5/>
<HBTYPE6/>
<HBTYPE7/>
<HBTYPE8/>
<HBTYPE9/>
<HBTYPE10/>
<HBTYPE11/>
<HBTYPE12/>
<HBTYPE13/>
<HBTYPE14/>
<HBTYPE15>15</HBTYPE15>
<HBTYPE>15</HBTYPE>
<SCHEME>000001005048</SCHEME>
<MANTYPE>D</MANTYPE>
<UNITS>15</UNITS>
<UNITTYPE>6</UNITTYPE>
<SCHTYPE>7</SCHTYPE>
<REGHOME>1</REGHOME>
<SUPPORT>2</SUPPORT>
<MOBSTAND>A</MOBSTAND>
<INTSTAY>P</INTSTAY>
<CLIGRP1>M</CLIGRP1>
<CLIGRP2/>
<Q28Auth>DLUHC</Q28Auth>
<Q28ONS>E08000035</Q28ONS>
<Q28pc override-field="">S80 4QE</Q28pc>
<Q28same/>
<P1R>0</P1R>
<P2R>0</P2R>
<P3R>0</P3R>
<P4R>0</P4R>
<P5R>0</P5R>
<P6R>0</P6R>
<P7R>0</P7R>
<P8R>0</P8R>
<REFUSEDTOT>0</REFUSEDTOT>
<REFUSED/>
<WTSHORTFALL/>
<WTSHORTFALLHB/>
<WTSHORTFALLHE/>
<WRENT>115.38</WRENT>
<WTCHARGE>121.85</WTCHARGE>
<WSCHARGE/>
<WPSCHRGE/>
<WSUPCHRG>6.46</WSUPCHRG>
<WTSHORTFALL1/>
<WRENT1>115.38</WRENT1>
<WTCHARGE1>121.85</WTCHARGE1>
<WSCHARGE1/>
<WPSCHRGE1/>
<WSUPCHRG1>6.46</WSUPCHRG1>
</Group>
<Group>
<BSa>1</BSa>
<BSb>0</BSb>
<BSc>0</BSc>
<BScm>0</BScm>
<BScf>0</BScf>
<BSd>0</BSd>
<BSdm>0</BSdm>
<BSdf>0</BSdf>
<BSe>0</BSe>
<BSem>0</BSem>
<BSef>0</BSef>
<BSf>0</BSf>
<BSfm>0</BSfm>
<BSff>0</BSff>
<BSfmx>0</BSfmx>
<BSffx>0</BSffx>
<BEDROOMSTAND>1</BEDROOMSTAND>
<BEDMINUSBEDS/>
<WRENTreduced>115.38</WRENTreduced>
<NonDepDeduct>0</NonDepDeduct>
<RENTHB/>
<ChildAllowan>0</ChildAllowan>
<PrsnlAllowan>117.4</PrsnlAllowan>
<HousBenDisAl>10</HousBenDisAl>
<PAIDHB/>
<HCNETAF/>
<ChldAlloCat1>0</ChldAlloCat1>
<ChldAlloCat2>0</ChldAlloCat2>
<P2NnDepDedct>0</P2NnDepDedct>
<P3NnDepDedct>0</P3NnDepDedct>
<P4NnDepDedct>0</P4NnDepDedct>
<P5NnDepDedct>0</P5NnDepDedct>
<P6NnDepDedct>0</P6NnDepDedct>
<P7NnDepDedct>0</P7NnDepDedct>
<P8NnDepDedct>0</P8NnDepDedct>
<DAY>5</DAY>
<MONTH>11</MONTH>
<YEAR>2021</YEAR>
<VDAY>24</VDAY>
<VMONTH>8</VMONTH>
<VYEAR>2021</VYEAR>
<MRCDAY/>
<MRCMONTH/>
<MRCYEAR/>
<PPOSTC1>LS16</PPOSTC1>
<PPOSTC2>6FT</PPOSTC2>
<POSTCODE>LS16</POSTCODE>
<POSTCOD2>6FT</POSTCOD2>
</Group>
</Group>

4
spec/lib/tasks/full_import_spec.rb

@ -22,6 +22,7 @@ describe "rake core:full_import", type: :task do
context "when starting a full import" do context "when starting a full import" do
let(:lettings_logs_service) { instance_double(Imports::LettingsLogsImportService) } let(:lettings_logs_service) { instance_double(Imports::LettingsLogsImportService) }
let(:sales_logs_service) { instance_double(Imports::SalesLogsImportService) }
let(:rent_period_service) { instance_double(Imports::OrganisationRentPeriodImportService) } let(:rent_period_service) { instance_double(Imports::OrganisationRentPeriodImportService) }
let(:data_protection_service) { instance_double(Imports::DataProtectionConfirmationImportService) } let(:data_protection_service) { instance_double(Imports::DataProtectionConfirmationImportService) }
let(:user_service) { instance_double(Imports::UserImportService) } let(:user_service) { instance_double(Imports::UserImportService) }
@ -37,6 +38,7 @@ describe "rake core:full_import", type: :task do
allow(Imports::DataProtectionConfirmationImportService).to receive(:new).and_return(data_protection_service) allow(Imports::DataProtectionConfirmationImportService).to receive(:new).and_return(data_protection_service)
allow(Imports::OrganisationRentPeriodImportService).to receive(:new).and_return(rent_period_service) allow(Imports::OrganisationRentPeriodImportService).to receive(:new).and_return(rent_period_service)
allow(Imports::LettingsLogsImportService).to receive(:new).and_return(lettings_logs_service) allow(Imports::LettingsLogsImportService).to receive(:new).and_return(lettings_logs_service)
allow(Imports::SalesLogsImportService).to receive(:new).and_return(sales_logs_service)
end end
it "raises an exception if no parameters are provided" do it "raises an exception if no parameters are provided" do
@ -54,6 +56,7 @@ describe "rake core:full_import", type: :task do
expect(data_protection_service).to receive(:create_data_protection_confirmations).with("dataprotect") expect(data_protection_service).to receive(:create_data_protection_confirmations).with("dataprotect")
expect(rent_period_service).to receive(:create_organisation_rent_periods).with("rent-period") expect(rent_period_service).to receive(:create_organisation_rent_periods).with("rent-period")
expect(lettings_logs_service).to receive(:create_logs).with("logs") expect(lettings_logs_service).to receive(:create_logs).with("logs")
# expect(sales_logs_service).to receive(:create_logs).with("logs")
task.invoke(fixture_path) task.invoke(fixture_path)
end end
@ -73,6 +76,7 @@ describe "rake core:full_import", type: :task do
expect(data_protection_service).to receive(:create_data_protection_confirmations) expect(data_protection_service).to receive(:create_data_protection_confirmations)
expect(rent_period_service).to receive(:create_organisation_rent_periods) expect(rent_period_service).to receive(:create_organisation_rent_periods)
expect(lettings_logs_service).to receive(:create_logs) expect(lettings_logs_service).to receive(:create_logs)
# expect(sales_logs_service).to receive(:create_logs)
expect(scheme_service).not_to receive(:create_schemes) expect(scheme_service).not_to receive(:create_schemes)
expect(location_service).not_to receive(:create_scheme_locations) expect(location_service).not_to receive(:create_scheme_locations)

4
spec/mailers/bulk_upload_mailer_spec.rb

@ -93,7 +93,7 @@ RSpec.describe BulkUploadMailer do
year_combo: bulk_upload.year_combo, year_combo: bulk_upload.year_combo,
lettings_or_sales: bulk_upload.log_type, lettings_or_sales: bulk_upload.log_type,
error_description: "We noticed that you have a lot of similar errors in column A, B. Please correct your data export and upload again.", error_description: "We noticed that you have a lot of similar errors in column A, B. Please correct your data export and upload again.",
summary_report_link: "http://localhost:3000/lettings-logs/bulk-upload-results/#{bulk_upload.id}/summary", summary_report_link: "http://localhost:3000/lettings-logs/bulk-upload-results/#{bulk_upload.id}",
}, },
) )
@ -103,6 +103,8 @@ RSpec.describe BulkUploadMailer do
context "when 4 columns with errors" do context "when 4 columns with errors" do
before do before do
stub_const("BulkUploadErrorSummaryTableComponent::DISPLAY_THRESHOLD", 0)
create(:bulk_upload_error, bulk_upload:, col: "A") create(:bulk_upload_error, bulk_upload:, col: "A")
create(:bulk_upload_error, bulk_upload:, col: "B") create(:bulk_upload_error, bulk_upload:, col: "B")
create(:bulk_upload_error, bulk_upload:, col: "C") create(:bulk_upload_error, bulk_upload:, col: "C")

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

@ -1,10 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer1PreviousTenure, type: :model do RSpec.describe Form::Sales::Pages::Buyer1PreviousTenure, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) } subject(:page) { described_class.new(nil, nil, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) } let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do it "has correct subsection" do

40
spec/models/form/sales/pages/number_of_others_in_property_spec.rb

@ -1,10 +1,11 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) } subject(:page) { described_class.new(page_id, page_definition, subsection, joint_purchase:) }
let(:page_id) { nil } let(:page_id) { "number_of_others_in_property" }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:joint_purchase) { false }
let(:subsection) { instance_double(Form::Subsection) } let(:subsection) { instance_double(Form::Subsection) }
it "has correct subsection" do it "has correct subsection" do
@ -26,4 +27,39 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, 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([
{
"privacynotice" => 1,
"jointpur" => 2,
},
{
"noint" => 1,
"jointpur" => 2,
},
])
end
context "with joint purchase" do
let(:page_id) { "number_of_others_in_property_joint_purchase" }
let(:joint_purchase) { true }
it "has the correct id" do
expect(page.id).to eq("number_of_others_in_property_joint_purchase")
end
it "has the correct depends_on" do
expect(page.depends_on).to eq([
{
"privacynotice" => 1,
"jointpur" => 1,
},
{
"noint" => 1,
"jointpur" => 1,
},
])
end
end
end end

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

@ -5,7 +5,9 @@ RSpec.describe Form::Sales::Pages::SharedOwnershipType, type: :model do
let(:page_id) { nil } let(:page_id) { nil }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) } let(:start_date) { Time.utc(2022, 4, 1) }
let(:form) { instance_double(Form, start_date:) }
let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do it "has correct subsection" do
expect(page.subsection).to eq(subsection) expect(page.subsection).to eq(subsection)

13
spec/models/form/sales/questions/buyer1_mortgage_spec.rb

@ -6,6 +6,7 @@ RSpec.describe Form::Sales::Questions::Buyer1Mortgage, type: :model do
let(:question_id) { nil } let(:question_id) { nil }
let(:question_definition) { nil } let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log) }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -16,11 +17,11 @@ RSpec.describe Form::Sales::Questions::Buyer1Mortgage, type: :model do
end end
it "has the correct header" do it "has the correct header" do
expect(question.header).to eq("Was buyer 1's income used for a mortgage application?") expect(question.header).to eq("Was buyer 1s income used for a mortgage application?")
end end
it "has the correct check_answer_label" do it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Buyer 1's income used for mortgage application") expect(question.check_answer_label).to eq("Buyer 1s income used for mortgage application")
end end
it "has the correct type" do it "has the correct type" do
@ -35,6 +36,14 @@ RSpec.describe Form::Sales::Questions::Buyer1Mortgage, type: :model do
expect(question.answer_options).to eq({ expect(question.answer_options).to eq({
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
})
end
it "has the correct displayed_answer_options" do
expect(question.displayed_answer_options(log)).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}) })
end end

10
spec/models/form/sales/questions/buyer1_previous_tenure_spec.rb

@ -1,11 +1,10 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form::Sales::Questions::Buyer1PreviousTenure, type: :model do RSpec.describe Form::Sales::Questions::Buyer1PreviousTenure, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) } subject(:question) { described_class.new(nil, nil, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log) }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -16,11 +15,11 @@ RSpec.describe Form::Sales::Questions::Buyer1PreviousTenure, type: :model do
end end
it "has the correct header" do it "has the correct header" do
expect(question.header).to eq("What was buyer 1's previous tenure?") expect(question.header).to eq("What was buyer 1s previous tenure?")
end end
it "has the correct check_answer_label" do it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Buyer 1's previous tenure") expect(question.check_answer_label).to eq("Buyer 1s previous tenure")
end end
it "has the correct type" do it "has the correct type" do
@ -41,6 +40,7 @@ RSpec.describe Form::Sales::Questions::Buyer1PreviousTenure, type: :model do
"6" => { "value" => "Living with family or friends" }, "6" => { "value" => "Living with family or friends" },
"7" => { "value" => "Temporary accomodation" }, "7" => { "value" => "Temporary accomodation" },
"9" => { "value" => "Other" }, "9" => { "value" => "Other" },
"0" => { "value" => "Don’t know" },
}) })
end end
end end

13
spec/models/form/sales/questions/buyer2_mortgage_spec.rb

@ -6,6 +6,7 @@ RSpec.describe Form::Sales::Questions::Buyer2Mortgage, type: :model do
let(:question_id) { nil } let(:question_id) { nil }
let(:question_definition) { nil } let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log) }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -16,11 +17,11 @@ RSpec.describe Form::Sales::Questions::Buyer2Mortgage, type: :model do
end end
it "has the correct header" do it "has the correct header" do
expect(question.header).to eq("Was buyer 2's income used for a mortgage application?") expect(question.header).to eq("Was buyer 2s income used for a mortgage application?")
end end
it "has the correct check_answer_label" do it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Buyer 2's income used for mortgage application") expect(question.check_answer_label).to eq("Buyer 2s income used for mortgage application")
end end
it "has the correct type" do it "has the correct type" do
@ -35,6 +36,14 @@ RSpec.describe Form::Sales::Questions::Buyer2Mortgage, type: :model do
expect(question.answer_options).to eq({ expect(question.answer_options).to eq({
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
})
end
it "has the correct displayed_answer_options" do
expect(question.displayed_answer_options(log)).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
}) })
end end

12
spec/models/form/sales/questions/buyers_organisations_spec.rb

@ -41,6 +41,18 @@ RSpec.describe Form::Sales::Questions::BuyersOrganisations, 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(
{
"pregyrha" => { "value" => "Their private registered provider (PRP) - housing association" },
"pregother" => { "value" => "Other private registered provider (PRP) - housing association" },
"pregla" => { "value" => "Local Authority" },
"pregghb" => { "value" => "Help to Buy Agent" },
"pregblank" => { "value" => "None of the above" },
},
)
end
it "has the correct displayed_answer_options" do
expect(question.displayed_answer_options(FactoryBot.create(:sales_log))).to eq(
{ {
"pregyrha" => { "value" => "Their private registered provider (PRP) - housing association" }, "pregyrha" => { "value" => "Their private registered provider (PRP) - housing association" },
"pregother" => { "value" => "Other private registered provider (PRP) - housing association" }, "pregother" => { "value" => "Other private registered provider (PRP) - housing association" },

9
spec/models/form/sales/questions/mortgageused_spec.rb

@ -6,6 +6,7 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
let(:question_id) { nil } let(:question_id) { nil }
let(:question_definition) { nil } let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:page) { instance_double(Form::Page) }
let(:log) { create(:sales_log) }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -35,6 +36,7 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
expect(question.answer_options).to eq({ expect(question.answer_options).to eq({
"1" => { "value" => "Yes" }, "1" => { "value" => "Yes" },
"2" => { "value" => "No" }, "2" => { "value" => "No" },
"3" => { "value" => "Don’t know" },
}) })
end end
@ -45,4 +47,11 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
it "has the correct hint" do it "has the correct hint" do
expect(question.hint_text).to be_nil expect(question.hint_text).to be_nil
end end
it "has the correct displayed_answer_options" do
expect(question.displayed_answer_options(log)).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No" },
})
end
end end

25
spec/models/form/sales/questions/number_of_others_in_property_spec.rb

@ -1,11 +1,12 @@
require "rails_helper" require "rails_helper"
RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page) } subject(:question) { described_class.new(question_id, question_definition, page, joint_purchase:) }
let(:question_id) { nil } let(:question_id) { nil }
let(:question_definition) { nil } let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:page) { instance_double(Form::Page) }
let(:joint_purchase) { true }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -32,6 +33,26 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do
end end
it "has the correct hint" do it "has the correct hint" do
expect(question.hint_text).to eq("You can provide details for a maximum of 4 other people.") expect(question.hint_text).to eq("You can provide details for a maximum of 4 other people for a joint purchase.")
end
it "has the correct min" do
expect(question.min).to eq(0)
end
it "has the correct max" do
expect(question.max).to eq(4)
end
context "with non joint purchase" do
let(:joint_purchase) { false }
it "has the correct hint" do
expect(question.hint_text).to eq("You can provide details for a maximum of 5 other people if there is only one buyer.")
end
it "has the correct max" do
expect(question.max).to eq(5)
end
end end
end end

44
spec/models/form/sales/questions/shared_ownership_type_spec.rb

@ -5,7 +5,10 @@ RSpec.describe Form::Sales::Questions::SharedOwnershipType, type: :model do
let(:question_id) { nil } let(:question_id) { nil }
let(:question_definition) { nil } let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) } let(:start_date) { Time.utc(2022, 4, 1) }
let(:form) { instance_double(Form, start_date:) }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:page) { instance_double(Form::Page, subsection:) }
it "has correct page" do it "has correct page" do
expect(question.page).to eq(page) expect(question.page).to eq(page)
@ -35,15 +38,34 @@ RSpec.describe Form::Sales::Questions::SharedOwnershipType, type: :model do
expect(question.hint_text).to eq("A shared ownership sale is when the purchaser buys up to 75% of the property value and pays rent to the Private Registered Provider (PRP) on the remaining portion") expect(question.hint_text).to eq("A shared ownership sale is when the purchaser buys up to 75% of the property value and pays rent to the Private Registered Provider (PRP) on the remaining portion")
end end
it "has the correct answer_options" do context "when form start date is 2022" do
expect(question.answer_options).to eq({ it "has the correct answer_options" do
"2" => { "value" => "Shared Ownership" }, expect(question.answer_options).to eq({
"24" => { "value" => "Old Persons Shared Ownership" }, "2" => { "value" => "Shared Ownership" },
"18" => { "value" => "Social HomeBuy (shared ownership purchase)" }, "24" => { "value" => "Old Persons Shared Ownership" },
"16" => { "value" => "Home Ownership for people with Long Term Disabilities (HOLD)" }, "18" => { "value" => "Social HomeBuy (shared ownership purchase)" },
"28" => { "value" => "Rent to Buy - Shared Ownership" }, "16" => { "value" => "Home Ownership for people with Long-Term Disabilities (HOLD)" },
"31" => { "value" => "Right to Shared Ownership" }, "28" => { "value" => "Rent to Buy - Shared Ownership" },
"30" => { "value" => "Shared Ownership - 2021 model lease" }, "31" => { "value" => "Right to Shared Ownership" },
}) "30" => { "value" => "Shared Ownership - 2021 model lease" },
})
end
end
context "when form start date is 2023" do
let(:start_date) { Time.utc(2023, 4, 2) }
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"2" => { "value" => "Shared Ownership (old model lease)" },
"30" => { "value" => "Shared Ownership (new model lease)" },
"18" => { "value" => "Social HomeBuy — shared ownership purchase" },
"16" => { "value" => "Home Ownership for people with Long-Term Disabilities (HOLD)" },
"24" => { "value" => "Older Persons Shared Ownership" },
"28" => { "value" => "Rent to Buy — Shared Ownership" },
"31" => { "value" => "Right to Shared Ownership (RtSO)" },
"32" => { "value" => "London Living Rent — Shared Ownership" },
})
end
end end
end end

18
spec/models/form/sales/subsections/household_characteristics_spec.rb

@ -50,6 +50,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_buyer_2_income_value_check working_situation_buyer_2_income_value_check
buyer_2_live_in_property buyer_2_live_in_property
number_of_others_in_property number_of_others_in_property
number_of_others_in_property_joint_purchase
person_2_known person_2_known
person_2_relationship_to_buyer_1 person_2_relationship_to_buyer_1
person_2_age person_2_age
@ -82,6 +83,14 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
gender_5_retirement_value_check gender_5_retirement_value_check
person_5_working_situation person_5_working_situation
working_situation_5_retirement_value_check working_situation_5_retirement_value_check
person_6_known
person_6_relationship_to_buyer_1
person_6_age
age_6_retirement_value_check
person_6_gender_identity
gender_6_retirement_value_check
person_6_working_situation
working_situation_6_retirement_value_check
], ],
) )
end end
@ -131,6 +140,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_buyer_2_income_value_check working_situation_buyer_2_income_value_check
buyer_2_live_in_property buyer_2_live_in_property
number_of_others_in_property number_of_others_in_property
number_of_others_in_property_joint_purchase
person_2_known person_2_known
person_2_relationship_to_buyer_1 person_2_relationship_to_buyer_1
person_2_age person_2_age
@ -163,6 +173,14 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
gender_5_retirement_value_check gender_5_retirement_value_check
person_5_working_situation person_5_working_situation
working_situation_5_retirement_value_check working_situation_5_retirement_value_check
person_6_known
person_6_relationship_to_buyer_1
person_6_age
age_6_retirement_value_check
person_6_gender_identity
gender_6_retirement_value_check
person_6_working_situation
working_situation_6_retirement_value_check
], ],
) )
end end

30
spec/models/sales_log_spec.rb

@ -90,6 +90,30 @@ RSpec.describe SalesLog, type: :model do
expect(completed_sales_log.not_started?).to be(false) expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(true) expect(completed_sales_log.completed?).to be(true)
end end
context "when proplen is not given" do
before do
Timecop.freeze(Time.zone.local(2023, 5, 1))
end
after do
Timecop.unfreeze
end
it "is set to completed for a log with a saledate before 23/24" do
completed_sales_log.update!(proplen: nil, saledate: Time.zone.local(2022, 5, 1))
expect(completed_sales_log.in_progress?).to be(false)
expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(true)
end
it "is set to in_progress for a log with a saledate after 23/24" do
completed_sales_log.update!(proplen: nil, saledate: Time.zone.local(2023, 5, 1))
expect(completed_sales_log.in_progress?).to be(true)
expect(completed_sales_log.not_started?).to be(false)
expect(completed_sales_log.completed?).to be(false)
end
end
end end
context "when filtering by organisation" do context "when filtering by organisation" do
@ -283,6 +307,12 @@ RSpec.describe SalesLog, type: :model do
expect(record_from_db["hhmemb"]).to eq(6) expect(record_from_db["hhmemb"]).to eq(6)
end end
it "correctly derives and saves hhmemb if it's a joint purchase" do
sales_log.update!(jointpur: 2, jointmore: 2)
record_from_db = ActiveRecord::Base.connection.execute("select hhmemb from sales_logs where id=#{sales_log.id}").to_a[0]
expect(record_from_db["hhmemb"]).to eq(5)
end
it "correctly derives and saves totchild" do it "correctly derives and saves totchild" do
record_from_db = ActiveRecord::Base.connection.execute("select totchild from sales_logs where id=#{sales_log.id}").to_a[0] record_from_db = ActiveRecord::Base.connection.execute("select totchild from sales_logs where id=#{sales_log.id}").to_a[0]
expect(record_from_db["totchild"]).to eq(2) expect(record_from_db["totchild"]).to eq(2)

2
spec/models/validations/financial_validations_spec.rb

@ -990,7 +990,7 @@ RSpec.describe Validations::FinancialValidations do
end end
context "and charges are not provided" do context "and charges are not provided" do
it "throws and error" do xit "throws and error" do
record.period = 3 record.period = 3
record.chcharge = nil record.chcharge = nil
financial_validator.validate_care_home_charges(record) financial_validator.validate_care_home_charges(record)

110
spec/services/imports/lettings_logs_import_service_spec.rb

@ -47,11 +47,12 @@ RSpec.describe Imports::LettingsLogsImportService do
let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" } let(:lettings_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" }
let(:lettings_log_id3) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" } let(:lettings_log_id3) { "00d2343e-d5fa-4c89-8400-ec3854b0f2b4" }
let(:lettings_log_id4) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" } let(:lettings_log_id4) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
let(:sales_log) { "shared_ownership_sales_log" }
before do before do
# Stub the S3 file listing and download # Stub the S3 file listing and download
allow(storage_service).to receive(:list_files) allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{lettings_log_id4}.xml]) .and_return(%W[#{remote_folder}/#{lettings_log_id}.xml #{remote_folder}/#{lettings_log_id2}.xml #{remote_folder}/#{lettings_log_id3}.xml #{remote_folder}/#{lettings_log_id4}.xml #{remote_folder}/#{sales_log}.xml])
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id}.xml") .with("#{remote_folder}/#{lettings_log_id}.xml")
.and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id)) .and_return(open_file(fixture_directory, lettings_log_id), open_file(fixture_directory, lettings_log_id))
@ -64,6 +65,9 @@ RSpec.describe Imports::LettingsLogsImportService do
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{lettings_log_id4}.xml") .with("#{remote_folder}/#{lettings_log_id4}.xml")
.and_return(open_file(fixture_directory, lettings_log_id4), open_file(fixture_directory, lettings_log_id4)) .and_return(open_file(fixture_directory, lettings_log_id4), open_file(fixture_directory, lettings_log_id4))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/#{sales_log}.xml")
.and_return(open_file(fixture_directory, sales_log), open_file(fixture_directory, sales_log))
end end
it "successfully create all lettings logs" do it "successfully create all lettings logs" do
@ -205,6 +209,110 @@ RSpec.describe Imports::LettingsLogsImportService do
end end
end end
context "and it has zero earnings" do
before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q8Money").content = 0
end
it "intercepts the relevant validation error" do
expect(logger).to receive(:warn).with(/Where the income is 0, set earnings and income to blank and set incref to refused/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil
expect(lettings_log.earnings).to be_nil
expect(lettings_log.incref).to eq(1)
expect(lettings_log.net_income_known).to eq(2)
end
end
context "and an invalid tenancy length for tenancy type" do
before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:_2cYears").content = "1"
lettings_log_xml.at_xpath("//xmlns:Q2b").content = "4"
end
it "intercepts the relevant validation error" do
expect(logger).to receive(:warn).with(/Removing tenancylength as invalid/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil
expect(lettings_log.tenancylength).to be_nil
expect(lettings_log.tenancy).to be_nil
end
end
context "and an lead tenant must be under 20 if childrens home or foster care" do
before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:Q11").content = "13"
lettings_log_xml.at_xpath("//xmlns:P1Age").content = "22"
end
it "intercepts the relevant validation error" do
expect(logger).to receive(:warn).with(/Removing age1 and prevten as incompatible/)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil
expect(lettings_log.age1).to be_nil
expect(lettings_log.prevten).to be_nil
end
end
context "and is a carehome but missing carehome charge" do
let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
before do
lettings_log_xml.at_xpath("//meta:status").content = "submitted"
lettings_log_xml.at_xpath("//xmlns:_1cmangroupcode").content = scheme2.old_visible_id
scheme2.update!(registered_under_care_act: 2)
lettings_log_xml.at_xpath("//xmlns:Q18b").content = ""
end
it "intercepts the relevant validation error" do
allow(logger).to receive(:warn)
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
it "clears out the invalid answers" do
allow(logger).to receive(:warn)
lettings_log_service.send(:create_log, lettings_log_xml)
lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
expect(lettings_log).not_to be_nil
expect(lettings_log.is_carehome).to be_truthy
expect(lettings_log.chcharge).to be_nil
end
end
context "and this is an internal transfer from a non social housing" do context "and this is an internal transfer from a non social housing" do
before do before do
lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home" lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"

199
spec/services/imports/sales_logs_import_service_spec.rb

@ -38,7 +38,7 @@ RSpec.describe Imports::SalesLogsImportService do
before do before do
# Stub the S3 file listing and download # Stub the S3 file listing and download
allow(storage_service).to receive(:list_files) allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/shared_ownership_sales_log.xml #{remote_folder}/shared_ownership_sales_log2.xml #{remote_folder}/outright_sale_sales_log.xml #{remote_folder}/discounted_ownership_sales_log.xml]) .and_return(%W[#{remote_folder}/shared_ownership_sales_log.xml #{remote_folder}/shared_ownership_sales_log2.xml #{remote_folder}/outright_sale_sales_log.xml #{remote_folder}/discounted_ownership_sales_log.xml #{remote_folder}/lettings_log.xml])
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/shared_ownership_sales_log.xml") .with("#{remote_folder}/shared_ownership_sales_log.xml")
.and_return(open_file(fixture_directory, "shared_ownership_sales_log"), open_file(fixture_directory, "shared_ownership_sales_log")) .and_return(open_file(fixture_directory, "shared_ownership_sales_log"), open_file(fixture_directory, "shared_ownership_sales_log"))
@ -51,6 +51,9 @@ RSpec.describe Imports::SalesLogsImportService do
allow(storage_service).to receive(:get_file_io) allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/discounted_ownership_sales_log.xml") .with("#{remote_folder}/discounted_ownership_sales_log.xml")
.and_return(open_file(fixture_directory, "discounted_ownership_sales_log"), open_file(fixture_directory, "discounted_ownership_sales_log")) .and_return(open_file(fixture_directory, "discounted_ownership_sales_log"), open_file(fixture_directory, "discounted_ownership_sales_log"))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/lettings_log.xml")
.and_return(open_file(fixture_directory, "lettings_log"), open_file(fixture_directory, "lettings_log"))
end end
it "successfully creates all sales logs" do it "successfully creates all sales logs" do
@ -540,40 +543,216 @@ RSpec.describe Imports::SalesLogsImportService do
allow(logger).to receive(:warn).and_return(nil) allow(logger).to receive(:warn).and_return(nil)
end end
it "sets hholdcount to hhmemb - 1 if not answered and not joint purchase" do it "sets hholdcount to last person the information is given for if HHMEMB is not set" do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:joint").content = "2 No" sales_log_xml.at_xpath("//xmlns:joint").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInOther").content = "" sales_log_xml.at_xpath("//xmlns:HHMEMB").content = ""
sales_log_xml.at_xpath("//xmlns:P2Age").content = "20"
sales_log_xml.at_xpath("//xmlns:P3Sex").content = "R"
sales_log_xml.at_xpath("//xmlns:P4Age").content = "23"
sales_log_service.send(:create_log, sales_log_xml) sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id) sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hholdcount).to eq(2) expect(sales_log&.hholdcount).to eq(3)
end end
it "sets hholdcount to hhmemb - 2 if not answered and joint purchase" do it "sets hholdcount to last person the information is given for - buyers if HHMEMB is 0" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes" sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No" sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3" sales_log_xml.at_xpath("//xmlns:HHMEMB").content = ""
sales_log_xml.at_xpath("//xmlns:LiveInOther").content = "" sales_log_xml.at_xpath("//xmlns:P2Age").content = "20"
sales_log_xml.at_xpath("//xmlns:P3Sex").content = "R"
sales_log_xml.at_xpath("//xmlns:P4Age").content = "23"
sales_log_service.send(:create_log, sales_log_xml) sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id) sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hholdcount).to eq(1) expect(sales_log&.hholdcount).to eq(2)
end end
it "sets hholdcount to 0 if HHMEMB is 0" do it "sets hholdcount to 0 no information for people is given and HHMEMB is not set" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes" sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No" sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = ""
sales_log_xml.at_xpath("//xmlns:LiveInOther").content = ""
sales_log_xml.at_xpath("//xmlns:P2Age").content = ""
sales_log_xml.at_xpath("//xmlns:P2Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P3Age").content = ""
sales_log_xml.at_xpath("//xmlns:P3Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P4Age").content = ""
sales_log_xml.at_xpath("//xmlns:P4Sex").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hholdcount).to eq(0)
end
it "sets hholdcount to the 0 if no information for people is given and HHMEMB is 0" do
sales_log_xml.at_xpath("//xmlns:joint").content = "2 No"
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "0" sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "0"
sales_log_xml.at_xpath("//xmlns:LiveInOther").content = "" sales_log_xml.at_xpath("//xmlns:LiveInOther").content = ""
sales_log_xml.at_xpath("//xmlns:P2Age").content = ""
sales_log_xml.at_xpath("//xmlns:P2Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P3Age").content = ""
sales_log_xml.at_xpath("//xmlns:P3Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P4Age").content = ""
sales_log_xml.at_xpath("//xmlns:P4Sex").content = ""
sales_log_service.send(:create_log, sales_log_xml) sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id) sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hholdcount).to eq(0) expect(sales_log&.hholdcount).to eq(0)
end end
it "doesn't hang if jointpur is not given" do
sales_log_xml.at_xpath("//xmlns:joint").content = ""
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "0"
sales_log_service.send(:create_log, sales_log_xml)
end
end
context "when inferring income used" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets inc1mort and inc2mort to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:Q2Person1Mortgage").content = ""
sales_log_xml.at_xpath("//xmlns:Q2Person2MortApplication").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.inc1mort).to eq(3)
expect(sales_log&.inc2mort).to eq(3)
end
it "sets inc1mort and inc2mort correctly if answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:Q2Person1Mortgage").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:Q2Person2MortApplication").content = "2 No"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.inc1mort).to eq(1)
expect(sales_log&.inc2mort).to eq(2)
end
end
context "when inferring buyer organisation" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets pregblank to true if no other organisations are selected" do
sales_log_xml.at_xpath("//xmlns:PREGYRHA").content = ""
sales_log_xml.at_xpath("//xmlns:PREGLA").content = ""
sales_log_xml.at_xpath("//xmlns:PREGHBA").content = ""
sales_log_xml.at_xpath("//xmlns:PREGOTHER").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.pregyrha).to eq(nil)
expect(sales_log&.pregla).to eq(nil)
expect(sales_log&.pregghb).to eq(nil)
expect(sales_log&.pregother).to eq(nil)
expect(sales_log&.pregblank).to eq(1)
end
it "sets pregblank and other organisation fields correctly if answered" do
sales_log_xml.at_xpath("//xmlns:PREGYRHA").content = "Yes"
sales_log_xml.at_xpath("//xmlns:PREGLA").content = "Yes"
sales_log_xml.at_xpath("//xmlns:PREGHBA").content = "Yes"
sales_log_xml.at_xpath("//xmlns:PREGOTHER").content = "Yes"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.pregyrha).to eq(1)
expect(sales_log&.pregla).to eq(1)
expect(sales_log&.pregghb).to eq(1)
expect(sales_log&.pregother).to eq(1)
expect(sales_log&.pregblank).to eq(nil)
end
end
context "when setting default buyer 2 live in for discounted ownership" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets buy2livein to true if it is joint purchase and it's not answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInBuyer2").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.buy2livein).to eq(1)
end
it "sets buy2livein correctly if it's answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInBuyer2").content = "1 Yes"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.buy2livein).to eq(1)
end
end
context "when setting default buyer 2 live in for shared ownership" do
let(:sales_log_id) { "shared_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets buy2livein to true if it is joint purchase and it's not answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInBuyer2").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.buy2livein).to eq(1)
end
it "sets buy2livein correctly if it's answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInBuyer2").content = "2 No"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.buy2livein).to eq(2)
end
end
context "when setting default buyer 2 live in for outright sale" do
let(:sales_log_id) { "outright_sale_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "does not set buy2livein if it is joint purchase and it's not answered" do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
sales_log_xml.at_xpath("//xmlns:LiveInBuyer2").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.buy2livein).to eq(nil)
end
end end
end end
end end

Loading…
Cancel
Save