Browse Source

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

pull/1343/head
Arthur Campbell 4 years ago committed by GitHub
parent
commit
de5e48735d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/controllers/form_controller.rb
  2. 5
      app/helpers/collection_time_helper.rb
  3. 1
      app/models/derived_variables/lettings_log_variables.rb
  4. 9
      app/models/form/sales/pages/housing_benefits.rb
  5. 3
      app/models/form/sales/pages/privacy_notice.rb
  6. 6
      app/models/form/sales/questions/housing_benefits.rb
  7. 3
      app/models/form/sales/subsections/income_benefits_and_savings.rb
  8. 10
      app/models/form/sales/subsections/outright_sale.rb
  9. 1
      app/models/lettings_log.rb
  10. 1
      app/services/bulk_upload/lettings/csv_parser.rb
  11. 113
      app/services/imports/lettings_logs_import_service.rb
  12. 127
      app/services/imports/logs_import_service.rb
  13. 448
      app/services/imports/sales_logs_import_service.rb
  14. 2
      app/views/form/_date_question.html.erb
  15. 1
      config/initializers/date_formats.rb
  16. 2
      config/initializers/feature_toggle.rb
  17. 8
      db/migrate/20230215112932_add_old_id_to_sales_logs.rb
  18. 10
      db/schema.rb
  19. 2
      lib/tasks/data_import.rake
  20. 4
      spec/features/sales_log_spec.rb
  21. 350
      spec/fixtures/imports/sales_logs/discounted_ownership_sales_log.xml
  22. 333
      spec/fixtures/imports/sales_logs/outright_sale_sales_log.xml
  23. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log.xml
  24. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log2.xml
  25. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log3.xml
  26. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log4.xml
  27. 41
      spec/helpers/collection_time_helper_spec.rb
  28. 12
      spec/helpers/navigation_items_helper_spec.rb
  29. 18
      spec/lib/tasks/data_import_spec.rb
  30. 21
      spec/models/form/sales/pages/housing_benefits_spec.rb
  31. 2
      spec/models/form/sales/pages/privacy_notice_spec.rb
  32. 17
      spec/models/form/sales/questions/housing_benefits_spec.rb
  33. 6
      spec/models/form/sales/subsections/income_benefits_and_savings_spec.rb
  34. 70
      spec/models/form/sales/subsections/outright_sale_spec.rb
  35. 4
      spec/models/form_handler_spec.rb
  36. 21
      spec/models/lettings_log_spec.rb
  37. 17
      spec/services/bulk_upload/lettings/csv_parser_spec.rb
  38. 580
      spec/services/imports/sales_logs_import_service_spec.rb

2
app/controllers/form_controller.rb

@ -54,7 +54,7 @@ class FormController < ApplicationController
if @page.routed_to?(@log, current_user)
render "form/page"
else
redirect_to lettings_log_path(@log)
redirect_to @log.lettings? ? lettings_log_path(@log) : sales_log_path(@log)
end
else
render_not_found

5
app/helpers/collection_time_helper.rb

@ -12,6 +12,11 @@ module CollectionTimeHelper
Time.zone.local(collection_start_year(date), 4, 1)
end
def date_mid_collection_year_formatted(date)
example_date = date.nil? ? Time.zone.today : collection_start_date(date).to_date + 5.months
example_date.to_formatted_s(:govuk_date_number_month)
end
def current_collection_start_date
Time.zone.local(current_collection_start_year, 4, 1)
end

1
app/models/derived_variables/lettings_log_variables.rb

@ -48,6 +48,7 @@ module DerivedVariables::LettingsLogVariables
self.offered = 0
self.voiddate = startdate
self.first_time_property_let_as_social_housing = 0
self.rsnvac = 14
if is_general_needs?
# fixed term
self.prevten = 32 if managing_organisation&.provider_type == "PRP"

9
app/models/form/sales/pages/housing_benefits.rb

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

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

@ -3,9 +3,6 @@ class Form::Sales::Pages::PrivacyNotice < ::Form::Page
super
@id = "privacy_notice"
@header = "Department for Levelling Up, Housing and Communities privacy notice"
@depends_on = [{
"noint" => 2,
}]
end
def questions

6
app/models/form/sales/questions/housing_benefits.rb

@ -1,9 +1,9 @@
class Form::Sales::Questions::HousingBenefits < ::Form::Question
def initialize(id, hsh, page)
super
def initialize(id, hsh, page, joint_purchase:)
super(id, hsh, page)
@id = "hb"
@check_answer_label = "Housing-related benefits buyer received before buying this property"
@header = "Was the buyer receiving any of these housing-related benefits immediately before buying this property?"
@header = "#{joint_purchase ? 'Were the buyers' : 'Was the buyer'} receiving any of these housing-related benefits immediately before buying this property?"
@type = "radio"
@answer_options = ANSWER_OPTIONS
end

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

@ -18,7 +18,8 @@ class Form::Sales::Subsections::IncomeBenefitsAndSavings < ::Form::Subsection
Form::Sales::Pages::Buyer2IncomeValueCheck.new("buyer_2_income_value_check", nil, self),
Form::Sales::Pages::Buyer2Mortgage.new(nil, nil, self),
Form::Sales::Pages::MortgageValueCheck.new("buyer_2_mortgage_value_check", nil, self, 2),
Form::Sales::Pages::HousingBenefits.new(nil, nil, self),
Form::Sales::Pages::HousingBenefits.new("housing_benefits_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::HousingBenefits.new("housing_benefits_not_joint_purchase", nil, self, joint_purchase: false),
Form::Sales::Pages::Savings.new(nil, nil, self),
Form::Sales::Pages::SavingsValueCheck.new("savings_value_check", nil, self),
Form::Sales::Pages::DepositValueCheck.new("savings_deposit_value_check", nil, self),

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

@ -20,12 +20,18 @@ class Form::Sales::Subsections::OutrightSale < ::Form::Subsection
Form::Sales::Pages::ExtraBorrowing.new("extra_borrowing_outright_sale", nil, self),
Form::Sales::Pages::AboutDepositWithoutDiscount.new("about_deposit_outright_sale", nil, self),
Form::Sales::Pages::DepositValueCheck.new("outright_sale_deposit_value_check", nil, self),
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_outright_sale", nil, self),
leasehold_charge_pages,
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_outright_sale_value_check", nil, self),
]
].compact
end
def displayed_in_tasklist?(log)
log.ownershipsch == 3
end
def leasehold_charge_pages
if form.start_date.year >= 2023
Form::Sales::Pages::LeaseholdCharges.new("leasehold_charges_outright_sale", nil, self)
end
end
end

1
app/models/lettings_log.rb

@ -518,6 +518,7 @@ private
def reset_derived_questions
dependent_questions = { waityear: [{ key: :renewal, value: 0 }],
referral: [{ key: :renewal, value: 0 }],
rsnvac: [{ key: :renewal, value: 0 }],
underoccupation_benefitcap: [{ key: :renewal, value: 0 }],
wchair: [{ key: :needstype, value: 1 }],
location_id: [{ key: :needstype, value: 1 }] }

1
app/services/bulk_upload/lettings/csv_parser.rb

@ -52,6 +52,7 @@ private
@normalised_string = File.read(path, encoding: "bom|utf-8")
@normalised_string.gsub!("\r\n", "\n")
@normalised_string.scrub!("")
@normalised_string
end

113
app/services/imports/lettings_logs_import_service.rb

@ -1,5 +1,5 @@
module Imports
class LettingsLogsImportService < ImportService
class LettingsLogsImportService < LogsImportService
def initialize(storage_service, logger = Rails.logger)
@logs_with_discrepancies = Set.new
@logs_overridden = Set.new
@ -318,43 +318,6 @@ module Imports
end
end
# Safe: A string that represents only an integer (or empty/nil)
def safe_string_as_integer(xml_doc, attribute)
str = field_value(xml_doc, "xmlns", attribute)
Integer(str, exception: false)
end
# Safe: A string that represents only a decimal (or empty/nil)
def safe_string_as_decimal(xml_doc, attribute)
str = string_or_nil(xml_doc, attribute)
if str.nil?
nil
else
BigDecimal(str, exception: false)
end
end
# Unsafe: A string that has more than just the integer value
def unsafe_string_as_integer(xml_doc, attribute)
str = string_or_nil(xml_doc, attribute)
if str.nil?
nil
else
str.to_i
end
end
def compose_date(xml_doc, day_str, month_str, year_str)
day = Integer(field_value(xml_doc, "xmlns", day_str), exception: false)
month = Integer(field_value(xml_doc, "xmlns", month_str), exception: false)
year = Integer(field_value(xml_doc, "xmlns", year_str), exception: false)
if day.nil? || month.nil? || year.nil?
nil
else
Time.zone.local(year, month, day)
end
end
def get_form_name_component(xml_doc, index)
form_name = meta_field_value(xml_doc, "form-name")
form_type_components = form_name.split("-")
@ -399,42 +362,6 @@ module Imports
end
end
def find_organisation_id(xml_doc, id_field)
old_visible_id = string_or_nil(xml_doc, id_field)
organisation = Organisation.find_by(old_visible_id:)
raise "Organisation not found with legacy ID #{old_visible_id}" if organisation.nil?
organisation.id
end
def sex(xml_doc, index)
sex = string_or_nil(xml_doc, "P#{index}Sex")
case sex
when "Male"
"M"
when "Female"
"F"
when "Other", "Non-binary"
"X"
when "Refused"
"R"
end
end
def relat(xml_doc, index)
relat = string_or_nil(xml_doc, "P#{index}Rel")
case relat
when "Child"
"C"
when "Partner"
"P"
when "Other", "Non-binary"
"X"
when "Refused"
"R"
end
end
def age_known(xml_doc, index, hhmemb)
return nil if hhmemb.present? && index > hhmemb
@ -473,16 +400,6 @@ module Imports
end
end
def compose_postcode(xml_doc, outcode, incode)
outcode_value = string_or_nil(xml_doc, outcode)
incode_value = string_or_nil(xml_doc, incode)
if outcode_value.nil? || incode_value.nil? || !"#{outcode_value} #{incode_value}".match(POSTCODE_REGEXP)
nil
else
"#{outcode_value} #{incode_value}"
end
end
def london_affordable_rent(xml_doc)
lar = unsafe_string_as_integer(xml_doc, "LAR")
if lar == 1
@ -502,34 +419,6 @@ module Imports
end
end
def string_or_nil(xml_doc, attribute)
str = field_value(xml_doc, "xmlns", attribute)
str.presence
end
def ethnic_group(ethnic)
case ethnic
when 1, 2, 3, 18
# White
0
when 4, 5, 6, 7
# Mixed
1
when 8, 9, 10, 11, 15
# Asian
2
when 12, 13, 14
# Black
3
when 16, 19
# Others
4
when 17
# Refused
17
end
end
# Letters should be lowercase to match case
def housing_needs(xml_doc, letter)
housing_need = string_or_nil(xml_doc, "Q10-#{letter}")

127
app/services/imports/logs_import_service.rb

@ -0,0 +1,127 @@
module Imports
class LogsImportService < ImportService
private
# Safe: A string that represents only an integer (or empty/nil)
def safe_string_as_integer(xml_doc, attribute)
str = field_value(xml_doc, "xmlns", attribute)
Integer(str, exception: false)
end
# Unsafe: A string that has more than just the integer value
def unsafe_string_as_integer(xml_doc, attribute)
str = string_or_nil(xml_doc, attribute)
if str.nil?
nil
else
str.to_i
end
end
def compose_date(xml_doc, day_str, month_str, year_str)
day = Integer(field_value(xml_doc, "xmlns", day_str), exception: false)
month = Integer(field_value(xml_doc, "xmlns", month_str), exception: false)
year = Integer(field_value(xml_doc, "xmlns", year_str), exception: false)
if day.nil? || month.nil? || year.nil?
nil
else
Time.zone.local(year, month, day)
end
end
def find_organisation_id(xml_doc, id_field)
old_visible_id = string_or_nil(xml_doc, id_field)
organisation = Organisation.find_by(old_visible_id:)
raise "Organisation not found with legacy ID #{old_visible_id}" if organisation.nil?
organisation.id
end
def string_or_nil(xml_doc, attribute)
str = field_value(xml_doc, "xmlns", attribute)
str.presence
end
def ethnic_group(ethnic)
case ethnic
when 1, 2, 3, 18
# White
0
when 4, 5, 6, 7
# Mixed
1
when 8, 9, 10, 11, 15
# Asian
2
when 12, 13, 14
# Black
3
when 16, 19
# Others
4
when 17
# Refused
17
end
end
# Safe: A string that represents only a decimal (or empty/nil)
def safe_string_as_decimal(xml_doc, attribute)
str = string_or_nil(xml_doc, attribute)
if str.nil?
nil
else
BigDecimal(str, exception: false)
end
end
def compose_postcode(xml_doc, outcode, incode)
outcode_value = string_or_nil(xml_doc, outcode)
incode_value = string_or_nil(xml_doc, incode)
if outcode_value.nil? || incode_value.nil? || !"#{outcode_value} #{incode_value}".match(POSTCODE_REGEXP)
nil
else
"#{outcode_value} #{incode_value}"
end
end
def previous_postcode_known(xml_doc, previous_postcode, prevloc)
previous_postcode_known = string_or_nil(xml_doc, "Q7UnknownPostcode")
if previous_postcode_known == "If postcode not known tick" || (previous_postcode.nil? && prevloc.present?)
1
elsif previous_postcode.nil?
nil
else
0
end
end
def sex(xml_doc, index)
sex = string_or_nil(xml_doc, "P#{index}Sex")
case sex
when "Male"
"M"
when "Female"
"F"
when "Other", "Non-binary"
"X"
when "Refused"
"R"
end
end
def relat(xml_doc, index)
relat = string_or_nil(xml_doc, "P#{index}Rel")
case relat
when "Child"
"C"
when "Partner"
"P"
when "Other", "Non-binary"
"X"
when "Refused", "Buyer prefers not to say"
"R"
end
end
end
end

448
app/services/imports/sales_logs_import_service.rb

@ -0,0 +1,448 @@
module Imports
class SalesLogsImportService < LogsImportService
def initialize(storage_service, logger = Rails.logger)
@logs_with_discrepancies = Set.new
@logs_overridden = Set.new
super
end
def create_logs(folder)
import_from(folder, :create_log)
if @logs_with_discrepancies.count.positive?
@logger.warn("The following sales logs had status discrepancies: [#{@logs_with_discrepancies.join(', ')}]")
end
end
private
def create_log(xml_doc)
attributes = {}
previous_status = meta_field_value(xml_doc, "status")
# Required fields for status complete or logic to work
# Note: order matters when we derive from previous values (attributes parameter)
attributes["saledate"] = compose_date(xml_doc, "DAY", "MONTH", "YEAR")
attributes["owning_organisation_id"] = find_organisation_id(xml_doc, "OWNINGORGID")
attributes["type"] = unsafe_string_as_integer(xml_doc, "DerSaleType")
attributes["old_id"] = meta_field_value(xml_doc, "document-id")
attributes["created_at"] = Time.zone.parse(meta_field_value(xml_doc, "created-date"))
attributes["updated_at"] = Time.zone.parse(meta_field_value(xml_doc, "modified-date"))
attributes["purchid"] = string_or_nil(xml_doc, "PurchaserCode")
attributes["ownershipsch"] = unsafe_string_as_integer(xml_doc, "Ownership")
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["beds"] = safe_string_as_integer(xml_doc, "Q11Bedrooms")
attributes["companybuy"] = unsafe_string_as_integer(xml_doc, "company") if attributes["ownershipsch"] == 3
attributes["hhmemb"] = safe_string_as_integer(xml_doc, "HHMEMB")
(1..6).each do |index|
attributes["age#{index}"] = safe_string_as_integer(xml_doc, "P#{index}Age")
attributes["sex#{index}"] = sex(xml_doc, index)
attributes["ecstat#{index}"] = unsafe_string_as_integer(xml_doc, "P#{index}Eco")
attributes["age#{index}_known"] = age_known(xml_doc, index, attributes["hhmemb"], attributes["age#{index}"])
end
(2..6).each do |index|
attributes["relat#{index}"] = relat(xml_doc, index)
attributes["details_known_#{index}"] = details_known(index, attributes)
end
attributes["national"] = unsafe_string_as_integer(xml_doc, "P1Nat")
attributes["othernational"] = nil
attributes["ethnic"] = unsafe_string_as_integer(xml_doc, "P1Eth")
attributes["ethnic_group"] = ethnic_group(attributes["ethnic"])
attributes["buy1livein"] = unsafe_string_as_integer(xml_doc, "LiveInBuyer1")
attributes["buylivein"] = unsafe_string_as_integer(xml_doc, "LiveInBuyer") if attributes["ownershipsch"] == 3
attributes["builtype"] = unsafe_string_as_integer(xml_doc, "Q13BuildingType")
attributes["proptype"] = unsafe_string_as_integer(xml_doc, "Q12PropertyType")
attributes["privacynotice"] = 1 if string_or_nil(xml_doc, "Qdp") == "Yes"
attributes["noint"] = unsafe_string_as_integer(xml_doc, "PartAPurchaser")
attributes["buy2livein"] = unsafe_string_as_integer(xml_doc, "LiveInBuyer2")
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["income1"] = safe_string_as_integer(xml_doc, "Q2Person1Income")
attributes["income1nk"] = income_known(unsafe_string_as_integer(xml_doc, "P1IncKnown"))
attributes["inc1mort"] = unsafe_string_as_integer(xml_doc, "Q2Person1Mortgage")
attributes["income2"] = safe_string_as_integer(xml_doc, "Q2Person2Income")
attributes["income2nk"] = income_known(unsafe_string_as_integer(xml_doc, "P2IncKnown"))
attributes["savings"] = safe_string_as_integer(xml_doc, "Q3Savings")
attributes["savingsnk"] = savings_known(xml_doc)
attributes["prevown"] = unsafe_string_as_integer(xml_doc, "Q4PrevOwnedProperty")
attributes["mortgage"] = safe_string_as_decimal(xml_doc, "CALCMORT")
attributes["inc2mort"] = unsafe_string_as_integer(xml_doc, "Q2Person2MortApplication")
attributes["hb"] = unsafe_string_as_integer(xml_doc, "Q2a")
attributes["frombeds"] = safe_string_as_integer(xml_doc, "Q20Bedrooms")
attributes["staircase"] = unsafe_string_as_integer(xml_doc, "Q17aStaircase")
attributes["stairbought"] = safe_string_as_integer(xml_doc, "PercentBought")
attributes["stairowned"] = safe_string_as_integer(xml_doc, "PercentOwns") if attributes["staircase"] == 1
attributes["mrent"] = safe_string_as_decimal(xml_doc, "Q28MonthlyRent")
attributes["exdate"] = compose_date(xml_doc, "EXDAY", "EXMONTH", "EXYEAR")
attributes["exday"] = safe_string_as_integer(xml_doc, "EXDAY")
attributes["exmonth"] = safe_string_as_integer(xml_doc, "EXMONTH")
attributes["exyear"] = safe_string_as_integer(xml_doc, "EXYEAR")
attributes["resale"] = unsafe_string_as_integer(xml_doc, "Q17Resale")
attributes["deposit"] = deposit(xml_doc, attributes)
attributes["cashdis"] = safe_string_as_decimal(xml_doc, "Q27SocialHomeBuy")
attributes["disabled"] = unsafe_string_as_integer(xml_doc, "Disability")
attributes["lanomagr"] = unsafe_string_as_integer(xml_doc, "Q19Rehoused")
attributes["value"] = purchase_price(xml_doc, attributes)
attributes["equity"] = safe_string_as_decimal(xml_doc, "Q23Equity")
attributes["discount"] = safe_string_as_decimal(xml_doc, "Q33Discount")
attributes["grant"] = safe_string_as_decimal(xml_doc, "Q32Reductions")
attributes["pregyrha"] = 1 if string_or_nil(xml_doc, "PREGYRHA") == "Yes"
attributes["pregla"] = 1 if string_or_nil(xml_doc, "PREGLA") == "Yes"
attributes["pregghb"] = 1 if string_or_nil(xml_doc, "PREGHBA") == "Yes"
attributes["pregother"] = 1 if string_or_nil(xml_doc, "PREGOTHER") == "Yes"
attributes["ppostcode_full"] = compose_postcode(xml_doc, "PPOSTC1", "PPOSTC2")
attributes["prevloc"] = string_or_nil(xml_doc, "Q7ONSLACode")
attributes["ppcodenk"] = previous_postcode_known(xml_doc, attributes["ppostcode_full"], attributes["prevloc"]) # Q7UNKNOWNPOSTCODE check mapping
attributes["ppostc1"] = string_or_nil(xml_doc, "PPOSTC1")
attributes["ppostc2"] = string_or_nil(xml_doc, "PPOSTC2")
attributes["previous_la_known"] = nil
attributes["hhregres"] = unsafe_string_as_integer(xml_doc, "ArmedF")
attributes["hhregresstill"] = still_serving(xml_doc)
attributes["proplen"] = safe_string_as_integer(xml_doc, "Q16aProplen2")
attributes["mscharge"] = monthly_charges(xml_doc, attributes)
attributes["mscharge_known"] = 1 if attributes["mscharge"].present?
attributes["prevten"] = unsafe_string_as_integer(xml_doc, "Q6PrevTenure")
attributes["mortgageused"] = unsafe_string_as_integer(xml_doc, "MORTGAGEUSED")
attributes["wchair"] = unsafe_string_as_integer(xml_doc, "Q15Wheelchair")
attributes["armedforcesspouse"] = unsafe_string_as_integer(xml_doc, "ARMEDFORCESSPOUSE")
attributes["hodate"] = compose_date(xml_doc, "HODAY", "HOMONTH", "HOYEAR")
attributes["hoday"] = safe_string_as_integer(xml_doc, "HODAY")
attributes["homonth"] = safe_string_as_integer(xml_doc, "HOMONTH")
attributes["hoyear"] = safe_string_as_integer(xml_doc, "HOYEAR")
attributes["fromprop"] = unsafe_string_as_integer(xml_doc, "Q21PropertyType")
attributes["socprevten"] = unsafe_string_as_integer(xml_doc, "PrevRentType")
attributes["mortgagelender"] = mortgage_lender(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["pcode2"] = string_or_nil(xml_doc, "PCODE2")
attributes["postcode_full"] = compose_postcode(xml_doc, "PCODE1", "PCODE2")
attributes["pcodenk"] = 0 if attributes["postcode_full"].present? # known if given
attributes["soctenant"] = soctenant(attributes)
attributes["ethnic_group2"] = nil # 23/24 variable
attributes["ethnicbuy2"] = nil # 23/24 variable
attributes["prevshared"] = nil # 23/24 variable
attributes["staircasesale"] = nil # 23/24 variable
# Required for our form invalidated questions (not present in import)
attributes["previous_la_known"] = 1 if attributes["prevloc"].present? && attributes["ppostcode_full"].blank?
attributes["la_known"] = 1 if attributes["la"].present? && attributes["postcode_full"].blank?
# Sets the log creator
owner_id = meta_field_value(xml_doc, "owner-user-id").strip
if owner_id.present?
user = LegacyUser.find_by(old_user_id: owner_id)&.user
@logger.warn "Missing user! We expected to find a legacy user with old_user_id #{owner_id}" unless user
attributes["created_by"] = user
end
set_default_values(attributes) if previous_status.include?("submitted")
sales_log = save_sales_log(attributes, previous_status)
compute_differences(sales_log, attributes)
check_status_completed(sales_log, previous_status) unless @logs_overridden.include?(sales_log.old_id)
end
def save_sales_log(attributes, previous_status)
sales_log = SalesLog.new(attributes)
begin
sales_log.save!
sales_log
rescue ActiveRecord::RecordNotUnique
legacy_id = attributes["old_id"]
record = SalesLog.find_by(old_id: legacy_id)
@logger.info "Updating sales log #{record.id} with legacy ID #{legacy_id}"
record.update!(attributes)
record
rescue ActiveRecord::RecordInvalid => e
rescue_validation_or_raise(sales_log, attributes, previous_status, e)
end
end
def rescue_validation_or_raise(sales_log, _attributes, _previous_status, exception)
@logger.error("Log #{sales_log.old_id}: Failed to import")
raise exception
end
def compute_differences(sales_log, attributes)
differences = []
attributes.each do |key, value|
sales_log_value = sales_log.send(key.to_sym)
next if fields_not_present_in_softwire_data.include?(key)
if value != sales_log_value
differences.push("#{key} #{value.inspect} #{sales_log_value.inspect}")
end
end
@logger.warn "Differences found when saving log #{sales_log.old_id}: #{differences}" unless differences.empty?
end
def fields_not_present_in_softwire_data
%w[created_by
income1_value_check
mortgage_value_check
savings_value_check
deposit_value_check
wheel_value_check
retirement_value_check
extrabor_value_check
deposit_and_mortgage_value_check
shared_ownership_deposit_value_check
grant_value_check
value_value_check
old_persons_shared_ownership_value_check
staircase_bought_value_check
monthly_charges_value_check
hodate_check
saledate_check]
end
def check_status_completed(sales_log, previous_status)
if previous_status.include?("submitted") && sales_log.status != "completed"
@logger.warn "sales log #{sales_log.id} is not completed. The following answers are missing: #{missing_answers(sales_log).join(', ')}"
@logger.warn "sales log with old id:#{sales_log.old_id} is incomplete but status should be complete"
@logs_with_discrepancies << sales_log.old_id
end
end
def age_known(_xml_doc, index, hhmemb, age)
return nil if hhmemb.present? && index > hhmemb
return 0 if age.present?
end
def details_known(index, attributes)
return nil if attributes["hhmemb"].nil? || index > attributes["hhmemb"]
return nil if attributes["jointpur"] == 1 && index == 2
if attributes["age#{index}_known"] != 0 &&
attributes["sex#{index}"] == "R" &&
attributes["relat#{index}"] == "R" &&
attributes["ecstat#{index}"] == 10
2 # No
else
1 # Yes
end
end
MORTGAGE_LENDER_OPTIONS = {
"atom bank" => 1,
"barclays bank plc" => 2,
"bath building society" => 3,
"buckinghamshire building society" => 4,
"cambridge building society" => 5,
"coventry building society" => 6,
"cumberland building society" => 7,
"darlington building society" => 8,
"dudley building society" => 9,
"ecology building society" => 10,
"halifax" => 11,
"hanley economic building society" => 12,
"hinckley and rugby building society" => 13,
"holmesdale building society" => 14,
"ipswich building society" => 15,
"leeds building society" => 16,
"lloyds bank" => 17,
"mansfield building society" => 18,
"market harborough building society" => 19,
"melton mowbray building society" => 20,
"nationwide building society" => 21,
"natwest" => 22,
"nedbank private wealth" => 23,
"newbury building society" => 24,
"oneSavings bank" => 25,
"parity trust" => 26,
"penrith building society" => 27,
"pepper homeloans" => 28,
"royal bank of scotland" => 29,
"santander" => 30,
"skipton building society" => 31,
"teachers building society" => 32,
"the co-operative bank" => 33,
"tipton & coseley building society" => 34,
"tss" => 35,
"ulster bank" => 36,
"virgin money" => 37,
"west bromwich building society" => 38,
"yorkshire building society" => 39,
"other" => 40,
}.freeze
# this comes through as a string, need to map to a corresponding integer
def mortgage_lender(xml_doc, attributes)
lender = case attributes["ownershipsch"]
when 1
string_or_nil(xml_doc, "Q24aMortgageLender")
when 2
string_or_nil(xml_doc, "Q34a")
when 3
string_or_nil(xml_doc, "Q41aMortgageLender")
end
return if lender.blank?
MORTGAGE_LENDER_OPTIONS[lender.downcase] || MORTGAGE_LENDER_OPTIONS["other"]
end
def mortgage_lender_other(xml_doc, attributes)
return unless attributes["mortgagelender"] == MORTGAGE_LENDER_OPTIONS["other"]
case attributes["ownershipsch"]
when 1
string_or_nil(xml_doc, "Q24aMortgageLender")
when 2
string_or_nil(xml_doc, "Q34a")
when 3
string_or_nil(xml_doc, "Q41aMortgageLender")
end
end
def mortgage_length(xml_doc, attributes)
case attributes["ownershipsch"]
when 1
unsafe_string_as_integer(xml_doc, "Q24b")
when 2
unsafe_string_as_integer(xml_doc, "Q34b")
when 3
unsafe_string_as_integer(xml_doc, "Q41b")
end
end
def savings_known(xml_doc)
case unsafe_string_as_integer(xml_doc, "savingsKnown")
when 1 # known
0
when 2 # unknown
1
end
end
def soctenant(attributes)
return nil unless attributes["ownershipsch"] == 1
if attributes["frombeds"].blank? && attributes["fromprop"].blank? && attributes["socprevten"].blank?
2
else
1
end
# NO (2) if FROMBEDS, FROMPROP and socprevten are blank, and YES(1) if they are completed
end
def still_serving(xml_doc)
case unsafe_string_as_integer(xml_doc, "LeftArmedF")
when 4
4
when 5, 6
5
end
end
def income_known(value)
case value
when 1 # known
0
when 2 # unknown
1
end
end
def borrowing(xml_doc, attributes)
case attributes["ownershipsch"]
when 1
unsafe_string_as_integer(xml_doc, "Q25Borrowing")
when 2
unsafe_string_as_integer(xml_doc, "Q35Borrowing")
when 3
unsafe_string_as_integer(xml_doc, "Q42Borrowing")
end
end
def purchase_price(xml_doc, attributes)
case attributes["ownershipsch"]
when 1
safe_string_as_decimal(xml_doc, "Q22PurchasePrice")
when 2
safe_string_as_decimal(xml_doc, "Q31PurchasePrice")
when 3
safe_string_as_decimal(xml_doc, "Q40PurchasePrice")
end
end
def deposit(xml_doc, attributes)
case attributes["ownershipsch"]
when 1
safe_string_as_decimal(xml_doc, "Q26CashDeposit")
when 2
safe_string_as_decimal(xml_doc, "Q36CashDeposit")
when 3
safe_string_as_decimal(xml_doc, "Q43CashDeposit")
end
end
def monthly_charges(xml_doc, attributes)
safe_string_as_decimal(xml_doc, "Q29MonthlyCharges")
case attributes["ownershipsch"]
when 1
safe_string_as_decimal(xml_doc, "Q29MonthlyCharges")
when 2
safe_string_as_decimal(xml_doc, "Q37MonthlyCharges")
end
end
def set_default_values(attributes)
attributes["armedforcesspouse"] ||= 7
attributes["hhregres"] ||= 8
attributes["disabled"] ||= 3
attributes["wheel"] ||= 3
attributes["hb"] ||= 4
attributes["prevown"] ||= 3
attributes["savingsnk"] ||= attributes["savings"].present? ? 0 : 1
# attributes["noint"] = 1 # not interviewed
# buyer 1 characteristics
attributes["age1_known"] ||= 1
attributes["sex1"] ||= "R"
attributes["ethnic_group"] ||= 17
attributes["ethnic"] ||= 17
attributes["national"] ||= 13
attributes["ecstat1"] ||= 10
attributes["income1nk"] ||= attributes["income1"].present? ? 0 : 1
attributes["hholdcount"] ||= default_household_count(attributes) # just for testing, might need to change
# buyer 2 characteristics
if attributes["jointpur"] == 1
attributes["age2_known"] ||= 1
attributes["sex2"] ||= "R"
attributes["ecstat2"] ||= 10
attributes["income2nk"] ||= attributes["income2"].present? ? 0 : 1
end
# other household members characteristics
(2..attributes["hhmemb"]).each do |index|
attributes["age#{index}_known"] ||= 1
attributes["sex#{index}"] ||= "R"
attributes["ecstat#{index}"] ||= 10
attributes["relat#{index}"] ||= "R"
end
end
def missing_answers(sales_log)
applicable_questions = sales_log.form.subsections.map { |s| s.applicable_questions(sales_log) }.flatten
applicable_questions.filter { |q| q.unanswered?(sales_log) }.map(&:id)
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

2
app/views/form/_date_question.html.erb

@ -3,7 +3,7 @@
<%= f.govuk_date_field question.id.to_sym,
caption: caption(caption_text, page_header, conditional),
legend: legend(question, page_header, conditional),
hint: { text: question.hint_text&.html_safe || "For example, 1 9 2022." },
hint: { text: question.hint_text&.html_safe || "For example, #{date_mid_collection_year_formatted(lettings_log.startdate)}" },
width: 20,
**stimulus_html_attributes(question) do %>
<%= govuk_inset_text(text: question.unresolved_hint_text) if question.unresolved_hint_text.present? && @log.unresolved %>

1
config/initializers/date_formats.rb

@ -2,6 +2,7 @@ Time::DATE_FORMATS[:govuk_date] = "%-d %B %Y"
Time::DATE_FORMATS[:govuk_date_short_month] = "%-d %b %Y"
Date::DATE_FORMATS[:govuk_date] = "%-d %B %Y"
Date::DATE_FORMATS[:govuk_date_short_month] = "%-d %b %Y"
Date::DATE_FORMATS[:govuk_date_number_month] = "%-d %-m %Y"
Time::DATE_FORMATS[:month_and_year] = "%B %Y"
Date::DATE_FORMATS[:month_and_year] = "%B %Y"

2
config/initializers/feature_toggle.rb

@ -13,7 +13,7 @@ class FeatureToggle
end
def self.sales_log_enabled?
!Rails.env.production?
true
end
def self.managing_owning_enabled?

8
db/migrate/20230215112932_add_old_id_to_sales_logs.rb

@ -0,0 +1,8 @@
class AddOldIdToSalesLogs < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.column :old_id, :string
end
add_index :sales_logs, :old_id, unique: true
end
end

10
db/schema.rb

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_02_13_140932) do
ActiveRecord::Schema[7.0].define(version: 2023_02_15_112932) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -522,16 +522,18 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_13_140932) do
t.integer "income2_value_check"
t.integer "monthly_charges_value_check"
t.integer "value_value_check"
t.integer "saledate_check"
t.integer "details_known_5"
t.integer "details_known_6"
t.integer "saledate_check"
t.integer "prevshared"
t.integer "staircasesale"
t.integer "ethnic_group2"
t.integer "ethnicbuy2"
t.integer "proplen_asked"
t.integer "prevshared"
t.integer "staircasesale"
t.string "old_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 ["old_id"], name: "index_sales_logs_on_old_id", unique: true
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"
t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id"
end

2
lib/tasks/data_import.rake

@ -22,6 +22,8 @@ namespace :core do
Imports::OrganisationRentPeriodImportService.new(storage_service).create_organisation_rent_periods(path)
when "lettings-logs"
Imports::LettingsLogsImportService.new(storage_service).create_logs(path)
when "sales-logs"
Imports::SalesLogsImportService.new(storage_service).create_logs(path)
else
raise "Type #{type} is not supported by data_import"
end

4
spec/features/sales_log_spec.rb

@ -53,9 +53,9 @@ RSpec.describe "Sales Log Features" do
end
end
context "when the sales log feature flag is toggled" do
context "when the sales log feature flag is disabled" do
before do
allow(Rails.env).to receive(:production?).and_return(true)
allow(FeatureToggle).to receive(:sales_log_enabled?).and_return(false)
end
it "hides the create sales log button in production" do

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

@ -0,0 +1,350 @@
<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>discounted_ownership_sales_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>2023-02-21T11:54:51.786722Z</meta:created-date>
<meta:modified-date>2023-02-22T10:59:45.88188Z</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>
<Qdp/>
<CompletionDate>2023-02-01</CompletionDate>
<PurchaserCode>Discount ownership example</PurchaserCode>
<Ownership>2 Yes - a discount ownership scheme</Ownership>
<Q16SaleType/>
<Q30SaleType>14 Preserved Right to Buy (PRTB)</Q30SaleType>
<Q38SaleType/>
<Q38OtherSale/>
<company/>
<LiveInBuyer/>
<joint>2 No</joint>
<JointMore/>
<PartAPurchaser>1 No</PartAPurchaser>
</Group>
<Group>
<Q11Bedrooms override-field="">3</Q11Bedrooms>
<Q12PropertyType>3 House</Q12PropertyType>
<Q13BuildingType>1 Purpose built</Q13BuildingType>
<Q14Postcode override-field="">SW1A 1AA</Q14Postcode>
<!-- replace with commented options to test in the future -->
<!-- <Q14PropertyLocation>Westminster</Q14PropertyLocation>
<Q14ONSLACode>E09000033</Q14ONSLACode> -->
<Q14PropertyLocation>Cheltenham</Q14PropertyLocation>
<Q14ONSLACode>E07000078</Q14ONSLACode>
<Q15Wheelchair>3 Don&#x2019;t know</Q15Wheelchair>
</Group>
<Group>
<P1Age/>
<P1Sex override-field=""/>
<P1Eco/>
<P1Eth/>
<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>134750</CALCMORT>
<MORTGAGEUSED>1</MORTGAGEUSED>
<IM1>0</IM1>
<IM2>0</IM2>
<IMT>0</IMT>
<MortMultiple>1</MortMultiple>
<Form>300203</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>0</Q16CHK>
<Q30CHK>1</Q30CHK>
<Q38CHK>0</Q38CHK>
<SalesCHKT>1</SalesCHKT>
<Q23CHK>0</Q23CHK>
<Q16typeCHK>0</Q16typeCHK>
<Q16Q23>0</Q16Q23>
<DAY>1</DAY>
<MONTH>2</MONTH>
<YEAR>2023</YEAR>
<HODAY/>
<HOMONTH/>
<HOYEAR/>
<EXDAY/>
<EXMONTH/>
<EXYEAR/>
<PPOSTC1>GL51</PPOSTC1>
<PPOSTC2>9EX</PPOSTC2>
<!-- replace with commented options to test in the future -->
<!-- <PCODE1>SW1A</PCODE1>
<PCODE2>1AA</PCODE2> -->
<PCODE1>GL51</PCODE1>
<PCODE2>9EX</PCODE2>
<NOINT>1</NOINT>
</Group>
<Group>
<!-- replace with commented options to test in the future -->
<!-- <Q6PrevTenure/> -->
<Q6PrevTenure>3 Private tenant</Q6PrevTenure>
<Q7Postcode override-field="">GL51 9EX</Q7Postcode>
<Q7UnknownPostcode/>
<Q7PrevLocation>Cheltenham</Q7PrevLocation>
<Q7ONSLACode>E07000078</Q7ONSLACode>
<!-- replace with commented options to test in the future -->
<!-- <PREGYRHA/> -->
<PREGYRHA>Yes</PREGYRHA>
<PREGORHA/>
<PREGLA/>
<PREGHBA/>
<PREGOTHER/>
</Group>
<Group>
<ArmedF/>
<LeftArmedF/>
<ARMEDFORCESSPOUSE/>
<Disability/>
<Q10Wheelchair override-field=""/>
</Group>
<Group>
<P1IncKnown/>
<Q2Person1Income/>
<Q2Person1Mortgage>1 Yes</Q2Person1Mortgage>
<!-- replace with commented options to test in the future -->
<!-- <Q2Person1Mortgage/> -->
<P2IncKnown/>
<Q2Person2Income/>
<Q2Person2MortApplication/>
<Q2a/>
<savingsKnown/>
<Q3Savings override-field=""/>
<Q4PrevOwnedProperty/>
</Group>
<Group>
<!-- replace with commented options to test in the future -->
<!-- <Q16aProplen2/> -->
<Q16aProplen2>1</Q16aProplen2>
<Q17aStaircase/>
<PercentBought override-field=""/>
<PercentOwns/>
<Q17Resale/>
<Q18ContractExchange override-field=""/>
<Q18PracticalCompletion override-field=""/>
<Q19Rehoused/>
<Q20Bedrooms/>
<Q21PropertyType/>
<PrevRentType/>
<Q22PurchasePrice override-field=""/>
<Q23Equity override-field=""/>
<MortgageUsedSO/>
<Q24Mortgage override-field=""/>
<Q24aMortgageLender/>
<Q24b/>
<Q25Borrowing/>
<Q26CashDeposit override-field=""/>
<Q27SocialHomeBuy/>
<Q28MonthlyRent/>
<Q29MonthlyCharges/>
</Group>
<Group>
<Q16aProplensec2/>
<Q31PurchasePrice override-field="">275000</Q31PurchasePrice>
<Q32Reductions override-field=""/>
<Q33Discount override-field="">51</Q33Discount>
<MortgageUsedDO>1 Yes</MortgageUsedDO>
<Q34Mortgage override-field="true">134750</Q34Mortgage>
<Q34a>Halifax</Q34a>
<!-- replace with commented options to test in the future -->
<!-- <Q34b/> -->
<Q34b>33</Q34b>
<Q35Borrowing>2 No</Q35Borrowing>
<Q36CashDeposit>0</Q36CashDeposit>
<Q37MonthlyCharges>0.00</Q37MonthlyCharges>
</Group>
<Group>
<Q40PurchasePrice override-field=""/>
<MortgageUsedOS/>
<Q41Mortgage override-field=""/>
<Q41aMortgageLender/>
<Q41b/>
<Q42Borrowing/>
<Q43CashDeposit override-field=""/>
</Group>
<Group>
<HHMEMB>0</HHMEMB>
<TOTADULT>0</TOTADULT>
<TOTCHILD>0</TOTCHILD>
</Group>
<Group>
<HHTYPE>9 = other</HHTYPE>
<!-- replace with commented options to test in the future -->
<!-- <HHTYPE>3 = 1 adult</HHTYPE> -->
</Group>
<Group>
<DerSaleType>14 Preserved Right to Buy (PRTB)</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>0</Q8av>
<Q8bv>0</Q8bv>
<Q8cv>0</Q8cv>
<Q8dv>0</Q8dv>
<Q8ev>0</Q8ev>
<Q8Validate>0</Q8Validate>
</Group>
<Group>
<PLOACODE/>
<OACODE/>
<GOVREG>E12000007</GOVREG>
<OWNINGORGID>1</OWNINGORGID>
<OWNINGORGNAME>1 Test</OWNINGORGNAME>
<HCNUM>655</HCNUM>
</Group>
</Group>

333
spec/fixtures/imports/sales_logs/outright_sale_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>outright_sale_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-21T12:09:45.809134Z</meta:created-date>
<meta:modified-date>2023-02-22T10:59:01.709949Z</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-16</CompletionDate>
<PurchaserCode>Outright ownership example</PurchaserCode>
<Ownership>3 No - this is an outright or other sale</Ownership>
<Q16SaleType/>
<Q30SaleType/>
<Q38SaleType>10 Outright</Q38SaleType>
<Q38OtherSale/>
<company>2 No</company>
<LiveInBuyer>1 Yes</LiveInBuyer>
<joint>2 No</joint>
<JointMore/>
<PartAPurchaser>2 Yes</PartAPurchaser>
</Group>
<Group>
<Q11Bedrooms override-field="">1</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>2 No</Q15Wheelchair>
</Group>
<Group>
<P1Age>75</P1Age>
<P1Sex override-field="">Female</P1Sex>
<P1Eco>5 Retired</P1Eco>
<P1Eth>1 White: English/Scottish/Welsh/Northern Irish/British</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>0</CALCMORT>
<MORTGAGEUSED>2</MORTGAGEUSED>
<IM1>0</IM1>
<IM2>0</IM2>
<IMT>0</IMT>
<MortMultiple>0</MortMultiple>
<Form>300202</Form>
</Group>
<Group>
<minmaxP11/>
<minmaxP12/>
<minmaxP13/>
<minmaxP14/>
<minmaxP15>B</minmaxP15>
<minmaxP16/>
<minmaxP17/>
<minmaxP18/>
<minmaxP1T>B</minmaxP1T>
<minmaxP19/>
<minmaxP10/>
<minmaxP21/>
<minmaxP22/>
<minmaxP23/>
<minmaxP24/>
<minmaxP25/>
<minmaxP26/>
<minmaxP27/>
<minmaxP28/>
<minmaxP2T/>
<minmaxP29/>
<minmaxP20/>
<Q16CHK>0</Q16CHK>
<Q30CHK>0</Q30CHK>
<Q38CHK>1</Q38CHK>
<SalesCHKT>1</SalesCHKT>
<Q23CHK>0</Q23CHK>
<Q16typeCHK>0</Q16typeCHK>
<Q16Q23>0</Q16Q23>
<DAY>16</DAY>
<MONTH>1</MONTH>
<YEAR>2023</YEAR>
<HODAY/>
<HOMONTH/>
<HOYEAR/>
<EXDAY/>
<EXMONTH/>
<EXYEAR/>
<PPOSTC1>B95</PPOSTC1>
<PPOSTC2>5HZ</PPOSTC2>
<PCODE1>SW1A</PCODE1>
<PCODE2>1AA</PCODE2>
<NOINT/>
</Group>
<Group>
<Q6PrevTenure>3 Private tenant</Q6PrevTenure>
<Q7Postcode override-field="">B95 5HZ</Q7Postcode>
<Q7UnknownPostcode/>
<Q7PrevLocation>Stratford-on-Avon</Q7PrevLocation>
<Q7ONSLACode>E07000221</Q7ONSLACode>
<PREGYRHA/>
<PREGORHA/>
<PREGLA>Yes</PREGLA>
<PREGHBA/>
<PREGOTHER/>
</Group>
<Group>
<ArmedF>7 No</ArmedF>
<LeftArmedF/>
<ARMEDFORCESSPOUSE/>
<Disability>2 No</Disability>
<Q10Wheelchair override-field="">2 No</Q10Wheelchair>
</Group>
<Group>
<P1IncKnown>2 No</P1IncKnown>
<Q2Person1Income/>
<!-- replace with commented options to test in the future -->
<!-- <Q2Person1Mortgage/> -->
<Q2Person1Mortgage>2 No</Q2Person1Mortgage>
<P2IncKnown/>
<Q2Person2Income/>
<Q2Person2MortApplication/>
<Q2a>4 Don&#x2019;t know</Q2a>
<savingsKnown/>
<Q3Savings override-field=""/>
<Q4PrevOwnedProperty>2 No</Q4PrevOwnedProperty>
</Group>
<Group>
<Q16aProplen2/>
<Q17aStaircase/>
<PercentBought override-field=""/>
<PercentOwns/>
<Q17Resale/>
<Q18ContractExchange override-field=""/>
<Q18PracticalCompletion override-field=""/>
<Q19Rehoused/>
<Q20Bedrooms/>
<Q21PropertyType/>
<PrevRentType/>
<Q22PurchasePrice override-field=""/>
<Q23Equity override-field=""/>
<MortgageUsedSO/>
<Q24Mortgage override-field=""/>
<Q24aMortgageLender/>
<Q24b/>
<Q25Borrowing/>
<Q26CashDeposit override-field=""/>
<Q27SocialHomeBuy/>
<Q28MonthlyRent/>
<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="">300000</Q40PurchasePrice>
<MortgageUsedOS>2 No</MortgageUsedOS>
<Q41Mortgage override-field=""/>
<Q41aMortgageLender/>
<Q41b/>
<Q42Borrowing/>
<Q43CashDeposit override-field="">300000</Q43CashDeposit>
</Group>
<Group>
<HHMEMB>1</HHMEMB>
<TOTADULT>1</TOTADULT>
<TOTCHILD>0</TOTCHILD>
</Group>
<Group>
<HHTYPE>1 = 1 elder</HHTYPE>
</Group>
<Group>
<DerSaleType>10 Outright</DerSaleType>
</Group>
<Group>
<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>0</HHTYPEP2E>
<HHTYPEP3E>0</HHTYPEP3E>
<HHTYPEP4E>0</HHTYPEP4E>
<HHTYPEP5E>0</HHTYPEP5E>
<HHTYPEP6E>0</HHTYPEP6E>
<HHTYPEP7E>0</HHTYPEP7E>
<HHTYPEP8E>0</HHTYPEP8E>
<TELDER>1</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>0</Q8av>
<Q8bv>0</Q8bv>
<Q8cv>1</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>

333
spec/fixtures/imports/sales_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>

333
spec/fixtures/imports/sales_logs/shared_ownership_sales_log2.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_log2</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>

333
spec/fixtures/imports/sales_logs/shared_ownership_sales_log3.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_log3</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></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>

333
spec/fixtures/imports/sales_logs/shared_ownership_sales_log4.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_log4</meta:document-id>
<meta:owner-user-id>e29c492473446dca4d50224f2bb7cf965a261d6f</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></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>

41
spec/helpers/collection_time_helper_spec.rb

@ -4,13 +4,13 @@ RSpec.describe CollectionTimeHelper do
let(:current_user) { create(:user, :data_coordinator) }
let(:user) { create(:user, :data_coordinator) }
around do |example|
Timecop.freeze(now) do
example.run
describe "Current collection start year" do
around do |example|
Timecop.freeze(now) do
example.run
end
end
end
describe "Current collection start year" do
context "when the date is after 1st of April" do
let(:now) { Time.utc(2022, 8, 3) }
@ -77,4 +77,35 @@ RSpec.describe CollectionTimeHelper do
end
end
end
describe "#date_mid_collection_year_formatted" do
subject(:result) { date_mid_collection_year_formatted(input) }
context "when called with nil" do
let(:input) { nil }
it "returns the current date" do
today = Time.zone.today
expect(result).to eq("#{today.day} #{today.month} #{today.year}")
end
end
context "when called with a date after the first of April" do
calendar_year = 2030
let(:input) { Date.new(calendar_year, 7, 7) }
it "returns the first of September from that year" do
expect(result).to eq("1 9 #{calendar_year}")
end
end
context "when called with a date before April" do
calendar_year = 2040
let(:input) { Date.new(calendar_year, 2, 7) }
it "returns the first of September from the previous year" do
expect(result).to eq("1 9 #{calendar_year - 1}")
end
end
end
end

12
spec/helpers/navigation_items_helper_spec.rb

@ -7,9 +7,10 @@ RSpec.describe NavigationItemsHelper do
let(:organisation_path) { "/organisations/#{current_user.organisation.id}" }
describe "#primary items" do
context "when the sales log feature flag is enabled" do
context "when the sales log feature flag is disabled" do
before do
allow(Rails.env).to receive(:production?).and_return(true)
allow(FeatureToggle).to receive(:sales_log_enabled?).and_return(false)
allow(FeatureToggle).to receive(:managing_owning_enabled?).and_return(false)
end
context "when the user is a data coordinator" do
@ -336,7 +337,12 @@ RSpec.describe NavigationItemsHelper do
end
end
context "when the sales log feature flag is disabled" do
context "when the sales log feature flag is enabled" do
before do
allow(FeatureToggle).to receive(:sales_log_enabled?).and_return(true)
allow(FeatureToggle).to receive(:managing_owning_enabled?).and_return(true)
end
context "when the user is a data coordinator" do
context "when the user is on the lettings logs page" do
let(:expected_navigation_items) do

18
spec/lib/tasks/data_import_spec.rb

@ -109,6 +109,24 @@ describe "rake core:data_import", type: :task do
end
end
context "when importing sales logs" do
let(:type) { "sales-logs" }
let(:import_service) { instance_double(Imports::SalesLogsImportService) }
let(:fixture_path) { "spec/fixtures/imports/sales_logs" }
before do
allow(Imports::SalesLogsImportService).to receive(:new).and_return(import_service)
end
it "creates sales logs from the given XML file" do
expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name)
expect(Imports::SalesLogsImportService).to receive(:new).with(storage_service)
expect(import_service).to receive(:create_logs).with(fixture_path)
task.invoke(type, fixture_path)
end
end
context "when importing scheme data" do
let(:type) { "scheme" }
let(:import_service) { instance_double(Imports::SchemeImportService) }

21
spec/models/form/sales/pages/housing_benefits_spec.rb

@ -1,11 +1,12 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::HousingBenefits, 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) { "provided_id" }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:joint_purchase) { false }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@ -16,7 +17,7 @@ RSpec.describe Form::Sales::Pages::HousingBenefits, type: :model do
end
it "has the correct id" do
expect(page.id).to eq("housing_benefits")
expect(page.id).to eq(page_id)
end
it "has the correct header" do
@ -27,7 +28,17 @@ RSpec.describe Form::Sales::Pages::HousingBenefits, type: :model do
expect(page.description).to be_nil
end
it "has correct depends_on" do
expect(page.depends_on).to be_nil
context "when joint_purchase is false" do
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "jointpur" => 2 }])
end
end
context "when joint_purchase is true" do
let(:joint_purchase) { true }
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "jointpur" => 1 }])
end
end
end

2
spec/models/form/sales/pages/privacy_notice_spec.rb

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

17
spec/models/form/sales/questions/housing_benefits_spec.rb

@ -1,11 +1,12 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::HousingBenefits, 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_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:joint_purchase) { false }
it "has correct page" do
expect(question.page).to eq(page)
@ -15,8 +16,18 @@ RSpec.describe Form::Sales::Questions::HousingBenefits, type: :model do
expect(question.id).to eq("hb")
end
it "has the correct header" do
expect(question.header).to eq("Was the buyer receiving any of these housing-related benefits immediately before buying this property?")
context "when joint purchase is false" do
it "has the correct header" do
expect(question.header).to eq("Was the buyer receiving any of these housing-related benefits immediately before buying this property?")
end
end
context "when joint purchase is true" do
let(:joint_purchase) { true }
it "has the correct header" do
expect(question.header).to eq("Were the buyers receiving any of these housing-related benefits immediately before buying this property?")
end
end
it "has the correct check_answer_label" do

6
spec/models/form/sales/subsections/income_benefits_and_savings_spec.rb

@ -30,7 +30,8 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
buyer_2_income_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
housing_benefits
housing_benefits_joint_purchase
housing_benefits_not_joint_purchase
savings
savings_value_check
savings_deposit_value_check
@ -56,7 +57,8 @@ RSpec.describe Form::Sales::Subsections::IncomeBenefitsAndSavings, type: :model
buyer_2_income_value_check
buyer_2_mortgage
buyer_2_mortgage_value_check
housing_benefits
housing_benefits_joint_purchase
housing_benefits_not_joint_purchase
savings
savings_value_check
savings_deposit_value_check

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

@ -11,25 +11,57 @@ RSpec.describe Form::Sales::Subsections::OutrightSale, type: :model do
expect(outright_sale.section).to eq(section)
end
it "has correct pages" do
expect(outright_sale.pages.map(&:id)).to eq(
%w[
purchase_price_outright_sale
about_price_outright_sale_value_check
mortgage_used_outright_sale
outright_sale_mortgage_used_mortgage_value_check
mortgage_amount_outright_sale
outright_sale_mortgage_amount_mortgage_value_check
mortgage_lender_outright_sale
mortgage_lender_other_outright_sale
mortgage_length_outright_sale
extra_borrowing_outright_sale
about_deposit_outright_sale
outright_sale_deposit_value_check
leasehold_charges_outright_sale
monthly_charges_outright_sale_value_check
],
)
describe "pages" do
let(:section) { instance_double(described_class, form: instance_double(Form, start_date:)) }
context "when 2022" do
let(:start_date) { Time.utc(2022, 2, 8) }
it "has correct pages" do
expect(outright_sale.pages.compact.map(&:id)).to eq(
%w[
purchase_price_outright_sale
about_price_outright_sale_value_check
mortgage_used_outright_sale
outright_sale_mortgage_used_mortgage_value_check
mortgage_amount_outright_sale
outright_sale_mortgage_amount_mortgage_value_check
mortgage_lender_outright_sale
mortgage_lender_other_outright_sale
mortgage_length_outright_sale
extra_borrowing_outright_sale
about_deposit_outright_sale
outright_sale_deposit_value_check
monthly_charges_outright_sale_value_check
],
)
end
end
context "when 2023" do
let(:start_date) { Time.utc(2023, 2, 8) }
it "has correct pages" do
expect(outright_sale.pages.map(&:id)).to eq(
%w[
purchase_price_outright_sale
about_price_outright_sale_value_check
mortgage_used_outright_sale
outright_sale_mortgage_used_mortgage_value_check
mortgage_amount_outright_sale
outright_sale_mortgage_amount_mortgage_value_check
mortgage_lender_outright_sale
mortgage_lender_other_outright_sale
mortgage_length_outright_sale
extra_borrowing_outright_sale
about_deposit_outright_sale
outright_sale_deposit_value_check
leasehold_charges_outright_sale
monthly_charges_outright_sale_value_check
],
)
end
end
end
it "has the correct id" do

4
spec/models/form_handler_spec.rb

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

21
spec/models/lettings_log_spec.rb

@ -1468,6 +1468,12 @@ RSpec.describe LettingsLog do
expect(record_from_db["first_time_property_let_as_social_housing"]).to eq(0)
expect(lettings_log["first_time_property_let_as_social_housing"]).to eq(0)
end
it "derives vacancy reason as relet" do
record_from_db = ActiveRecord::Base.connection.execute("select rsnvac from lettings_logs where id=#{lettings_log.id}").to_a[0]
expect(record_from_db["rsnvac"]).to eq(14)
expect(lettings_log["rsnvac"]).to eq(14)
end
end
context "when answering the household characteristics questions" do
@ -1992,6 +1998,21 @@ RSpec.describe LettingsLog do
expect(record_from_db["waityear"]).to eq(nil)
expect(lettings_log["waityear"]).to eq(nil)
end
it "resets inferred vacancy reason value" do
vacancy_reason = "rsnvac"
lettings_log.update!({ renewal: 1 })
record_from_db = ActiveRecord::Base.connection.execute("select #{vacancy_reason} from lettings_logs where id=#{lettings_log.id}").to_a[0]
expect(record_from_db[vacancy_reason]).to eq(14)
expect(lettings_log[vacancy_reason]).to eq(14)
lettings_log.update!({ renewal: 0 })
record_from_db = ActiveRecord::Base.connection.execute("select #{vacancy_reason} from lettings_logs where id=#{lettings_log.id}").to_a[0]
expect(record_from_db[vacancy_reason]).to eq(nil)
expect(lettings_log[vacancy_reason]).to eq(nil)
end
end
context "when it changes from a supported housing to not a supported housing" do

17
spec/services/bulk_upload/lettings/csv_parser_spec.rb

@ -52,4 +52,21 @@ RSpec.describe BulkUpload::Lettings::CsvParser do
expect(service.row_parsers[0].field_12).to eql(log.age1)
end
end
context "when an invalid byte sequence" do
let(:file) { Tempfile.new }
let(:path) { file.path }
let(:log) { build(:lettings_log, :completed) }
let(:invalid_sequence) { "\x81" }
before do
file.write(invalid_sequence)
file.write(BulkUpload::LogToCsv.new(log:, col_offset: 0).to_csv_row)
file.close
end
it "parses csv correctly" do
expect(service.row_parsers[0].field_12).to eql(log.age1)
end
end
end

580
spec/services/imports/sales_logs_import_service_spec.rb

@ -0,0 +1,580 @@
require "rails_helper"
RSpec.describe Imports::SalesLogsImportService do
subject(:sales_log_service) { described_class.new(storage_service, logger) }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:logger) { instance_double(ActiveSupport::Logger) }
let(:fixture_directory) { "spec/fixtures/imports/sales_logs" }
let(:organisation) { FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") }
let(:managing_organisation) { FactoryBot.create(:organisation, old_visible_id: "2", provider_type: "PRP") }
let(:remote_folder) { "sales_logs" }
def open_file(directory, filename)
File.open("#{directory}/#{filename}.xml")
end
before do
{ "GL519EX" => "E07000078",
"SW1A2AA" => "E09000033",
"SW1A1AA" => "E09000033",
"SW147QP" => "E09000027",
"B955HZ" => "E07000221" }.each do |postcode, district_code|
WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/#{postcode}/).to_return(status: 200, body: "{\"status\":200,\"result\":{\"admin_district\":\"#{district_code}\",\"codes\":{\"admin_district\":\"#{district_code}\"}}}", headers: {})
end
allow(Organisation).to receive(:find_by).and_return(nil)
allow(Organisation).to receive(:find_by).with(old_visible_id: organisation.old_visible_id).and_return(organisation)
allow(Organisation).to receive(:find_by).with(old_visible_id: managing_organisation.old_visible_id).and_return(managing_organisation)
# Created by users
FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa", organisation:)
FactoryBot.create(:user, old_user_id: "e29c492473446dca4d50224f2bb7cf965a261d6f", organisation:)
end
context "when importing sales logs" do
before do
# Stub the S3 file listing and download
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])
allow(storage_service).to receive(:get_file_io)
.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"))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/shared_ownership_sales_log2.xml")
.and_return(open_file(fixture_directory, "shared_ownership_sales_log2"), open_file(fixture_directory, "shared_ownership_sales_log2"))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/outright_sale_sales_log.xml")
.and_return(open_file(fixture_directory, "outright_sale_sales_log"), open_file(fixture_directory, "outright_sale_sales_log"))
allow(storage_service).to receive(:get_file_io)
.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"))
end
it "successfully creates all sales logs" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
expect { sales_log_service.create_logs(remote_folder) }
.to change(SalesLog, :count).by(4)
end
it "only updates existing sales logs" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).to receive(:info).with(/Updating sales log/).exactly(4).times
expect { 2.times { sales_log_service.create_logs(remote_folder) } }
.to change(SalesLog, :count).by(4)
end
context "when there are status discrepancies" do
let(:sales_log_file) { open_file(fixture_directory, "shared_ownership_sales_log3") }
let(:sales_log_xml) { Nokogiri::XML(sales_log_file) }
before do
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/shared_ownership_sales_log3.xml")
.and_return(open_file(fixture_directory, "shared_ownership_sales_log3"), open_file(fixture_directory, "shared_ownership_sales_log3"))
allow(storage_service).to receive(:get_file_io)
.with("#{remote_folder}/shared_ownership_sales_log4.xml")
.and_return(open_file(fixture_directory, "shared_ownership_sales_log4"), open_file(fixture_directory, "shared_ownership_sales_log4"))
end
it "the logger logs a warning with the sales log's old id/filename" do
expect(logger).to receive(:warn).with(/is not completed/).once
expect(logger).to receive(:warn).with(/sales log with old id:shared_ownership_sales_log3 is incomplete but status should be complete/).once
sales_log_service.send(:create_log, sales_log_xml)
end
it "on completion the ids of all logs with status discrepancies are logged in a warning" do
allow(storage_service).to receive(:list_files)
.and_return(%W[#{remote_folder}/shared_ownership_sales_log3.xml #{remote_folder}/shared_ownership_sales_log4.xml])
expect(logger).to receive(:warn).with(/is not completed/).twice
expect(logger).to receive(:warn).with(/is incomplete but status should be complete/).twice
expect(logger).to receive(:warn).with(/The following sales logs had status discrepancies: \[shared_ownership_sales_log3, shared_ownership_sales_log4\]/)
sales_log_service.create_logs(remote_folder)
end
end
end
context "when importing a specific log" do
let(:sales_log_file) { open_file(fixture_directory, sales_log_id) }
let(:sales_log_xml) { Nokogiri::XML(sales_log_file) }
context "and the organisation legacy ID does not exist" do
let(:sales_log_id) { "shared_ownership_sales_log" }
before { sales_log_xml.at_xpath("//xmlns:OWNINGORGID").content = 99_999 }
it "raises an exception" do
expect { sales_log_service.send(:create_log, sales_log_xml) }
.to raise_error(RuntimeError, "Organisation not found with legacy ID 99999")
end
end
context "when the mortgage lender is set to an existing option" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:Q34a").content = "halifax"
allow(logger).to receive(:warn).and_return(nil)
end
it "correctly sets mortgage lender" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.mortgagelender).to be(11)
end
end
context "when the mortgage lender is set to a non existing option" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:Q34a").content = "something else"
allow(logger).to receive(:warn).and_return(nil)
end
it "correctly sets mortgage lender and mortgage lender other" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.mortgagelender).to be(40)
expect(sales_log&.mortgagelenderother).to eq("something else")
end
end
context "with shared ownership type" do
let(:sales_log_id) { "shared_ownership_sales_log" }
it "successfully creates a completed shared ownership log" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.to change(SalesLog, :count).by(1)
end
end
context "with discounted ownership type" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
it "successfully creates a completed discounted ownership log" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.to change(SalesLog, :count).by(1)
end
end
context "with outright sale type" do
let(:sales_log_id) { "outright_sale_sales_log" }
it "successfully creates a completed outright sale log" do
expect(logger).not_to receive(:error)
expect(logger).not_to receive(:warn)
expect(logger).not_to receive(:info)
expect { sales_log_service.send(:create_log, sales_log_xml) }
.to change(SalesLog, :count).by(1)
end
end
context "when inferring default answers for completed sales logs" do
context "when the armedforcesspouse is not answered" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:ARMEDFORCESSPOUSE").content = ""
allow(logger).to receive(:warn).and_return(nil)
end
it "sets armedforcesspouse to don't know" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.armedforcesspouse).to be(7)
end
end
context "when the savings not known is not answered and savings is not given" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:savingsKnown").content = ""
allow(logger).to receive(:warn).and_return(nil)
end
it "sets savingsnk to not know" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.savingsnk).to be(1)
end
end
context "when the savings not known is not answered and savings is given" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:Q3Savings").content = "10000"
sales_log_xml.at_xpath("//xmlns:savingsKnown").content = ""
allow(logger).to receive(:warn).and_return(nil)
end
it "sets savingsnk to know" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.savingsnk).to be(0)
end
end
context "when inferring age known" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:P1Age").content = ""
sales_log_xml.at_xpath("//xmlns:P2Age").content = ""
sales_log_xml.at_xpath("//xmlns:P3Age").content = "22"
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets age known to no if age not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.age1_known).to be(1) # unknown
expect(sales_log&.age2_known).to be(1) # unknown
end
it "sets age known to yes if age answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.age3_known).to be(0) # known
end
end
context "when inferring gender" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:P1Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P2Sex").content = ""
sales_log_xml.at_xpath("//xmlns:P3Sex").content = "Female"
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets gender to prefers not to say if not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.sex1).to eq("R")
expect(sales_log&.sex2).to eq("R")
end
it "sets the gender correctly if answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.sex3).to eq("F")
end
end
context "when inferring ethnic group" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "1"
sales_log_xml.at_xpath("//xmlns:P1Eth").content = ""
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets ethnic group to prefers not to say if not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.ethnic_group).to eq(17)
end
end
context "when inferring nationality" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "1"
sales_log_xml.at_xpath("//xmlns:P1Nat").content = ""
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets nationality to prefers not to say if not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.national).to eq(13)
end
end
context "when inferring economic status" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:P1Eco").content = ""
sales_log_xml.at_xpath("//xmlns:P2Eco").content = ""
sales_log_xml.at_xpath("//xmlns:P3Eco").content = "3"
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets economic status to prefers not to say if not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.ecstat1).to eq(10)
expect(sales_log&.ecstat2).to eq(10)
end
it "sets the economic status correctly if answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.ecstat3).to eq(3)
end
end
context "when inferring relationship" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:P2Rel").content = ""
sales_log_xml.at_xpath("//xmlns:P3Rel").content = "Partner"
allow(logger).to receive(:warn).and_return(nil)
sales_log_service.send(:create_log, sales_log_xml)
end
it "sets relationship to prefers not to say if not answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.relat2).to eq("R")
end
it "sets the relationship correctly if answered" do
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.relat3).to eq("P")
end
end
context "when inferring armed forces" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets hhregres to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:ArmedF").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hhregres).to eq(8)
end
it "sets hhregres correctly if answered" do
sales_log_xml.at_xpath("//xmlns:ArmedF").content = "7 No"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hhregres).to eq(7)
end
end
context "when inferring disability" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets disabled to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:Disability").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.disabled).to eq(3)
end
it "sets disabled correctly if answered" do
sales_log_xml.at_xpath("//xmlns:Disability").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&.disabled).to eq(2)
end
end
context "when inferring wheelchair" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets wheel to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:Q10Wheelchair").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.wheel).to eq(3)
end
it "sets wheel correctly if answered" do
sales_log_xml.at_xpath("//xmlns:Q10Wheelchair").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&.wheel).to eq(2)
end
end
context "when inferring housing benefit" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets hb to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:Q2a").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hb).to eq(4)
end
it "sets hb correctly if answered" do
sales_log_xml.at_xpath("//xmlns:Q2a").content = "2 Housing Benefit"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.hb).to eq(2)
end
end
context "when inferring income not known" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
sales_log_xml.at_xpath("//xmlns:joint").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:JointMore").content = "2 No"
allow(logger).to receive(:warn).and_return(nil)
end
it "sets income to not known if not answered and income is not given" do
sales_log_xml.at_xpath("//xmlns:P1IncKnown").content = ""
sales_log_xml.at_xpath("//xmlns:Q2Person1Income").content = ""
sales_log_xml.at_xpath("//xmlns:P2IncKnown").content = ""
sales_log_xml.at_xpath("//xmlns:Q2Person2Income").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.income1nk).to eq(1)
expect(sales_log&.income2nk).to eq(1)
end
it "sets income to known if not answered but the income is given" do
sales_log_xml.at_xpath("//xmlns:P1IncKnown").content = ""
sales_log_xml.at_xpath("//xmlns:Q2Person1Income").content = "30000"
sales_log_xml.at_xpath("//xmlns:P2IncKnown").content = ""
sales_log_xml.at_xpath("//xmlns:Q2Person2Income").content = "40000"
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.income1nk).to eq(0)
expect(sales_log&.income2nk).to eq(0)
end
it "sets income known correctly if answered" do
sales_log_xml.at_xpath("//xmlns:P1IncKnown").content = "1 Yes"
sales_log_xml.at_xpath("//xmlns:P2IncKnown").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&.income1nk).to eq(0)
expect(sales_log&.income2nk).to eq(1)
end
end
context "when inferring prevown" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets prevown to don't know if not answered" do
sales_log_xml.at_xpath("//xmlns:Q4PrevOwnedProperty").content = ""
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log&.prevown).to eq(3)
end
it "sets prevown correctly if answered" do
sales_log_xml.at_xpath("//xmlns:Q4PrevOwnedProperty").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&.prevown).to eq(2)
end
end
context "when inferring household count" do
let(:sales_log_id) { "discounted_ownership_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "sets hholdcount to hhmemb - 1 if not answered and not joint purchase" 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:LiveInOther").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(2)
end
it "sets hholdcount to hhmemb - 2 if not answered and joint purchase" 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:HHMEMB").content = "3"
sales_log_xml.at_xpath("//xmlns:LiveInOther").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(1)
end
it "sets hholdcount to 0 if HHMEMB is 0" 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:HHMEMB").content = "0"
sales_log_xml.at_xpath("//xmlns:LiveInOther").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
end
end
end
end
Loading…
Cancel
Save