Browse Source

CLDS-1938 Add sales logs importer (#1331)

* Create test fixtures

* Add old id column

* Add sales logs importer

* Save and update completed discounted ownership log without postcode

* Update fixtures to be incomplete

* Import a completed shared ownership example

* Test with a non homebuy shared ownership example

* Add privacynotice

* Update hholdcount and confirmed fields

* Add buyer stilll serving mapping

* Add totadult/totchild and outright sale examples

* Update log fixtures

* Extract shared methods into logs import service and lint

* Add sales logs import rake task

* Update noint, xml examples and some mappings

* Add tests for checking that all required questions are answered

* Update tests, clean up import

* Map mortgage lender and mortgage lender other

* Infer Mscharge known as no for outright sale

* refactor setting default values

* when the armedforcesspouse is not answered set is as don't know

* Refactor tests: change log id names

* set savings to not known if not given

* Refactor tests: change nesting

* Backfill default household characteristics for completed log

* Add more default mapping

* Typo

* Improve logging and refactor tests

* Adjust test data to fit with the mappings that are known so far

* Rename fixture files
CLDC-2019-UPRN-search
kosiakkatrina 2 years ago committed by GitHub
parent
commit
e0e09a22d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 113
      app/services/imports/lettings_logs_import_service.rb
  2. 127
      app/services/imports/logs_import_service.rb
  3. 450
      app/services/imports/sales_logs_import_service.rb
  4. 8
      db/migrate/20230215112932_add_old_id_to_sales_logs.rb
  5. 10
      db/schema.rb
  6. 2
      lib/tasks/data_import.rake
  7. 351
      spec/fixtures/imports/sales_logs/discounted_ownership_sales_log.xml
  8. 333
      spec/fixtures/imports/sales_logs/outright_sale_sales_log.xml
  9. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log.xml
  10. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log2.xml
  11. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log3.xml
  12. 333
      spec/fixtures/imports/sales_logs/shared_ownership_sales_log4.xml
  13. 18
      spec/lib/tasks/data_import_spec.rb
  14. 595
      spec/services/imports/sales_logs_import_service_spec.rb

113
app/services/imports/lettings_logs_import_service.rb

@ -1,5 +1,5 @@
module Imports module Imports
class LettingsLogsImportService < ImportService class LettingsLogsImportService < LogsImportService
def initialize(storage_service, logger = Rails.logger) def initialize(storage_service, logger = Rails.logger)
@logs_with_discrepancies = Set.new @logs_with_discrepancies = Set.new
@logs_overridden = Set.new @logs_overridden = Set.new
@ -318,43 +318,6 @@ module Imports
end end
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) def get_form_name_component(xml_doc, index)
form_name = meta_field_value(xml_doc, "form-name") form_name = meta_field_value(xml_doc, "form-name")
form_type_components = form_name.split("-") form_type_components = form_name.split("-")
@ -399,42 +362,6 @@ module Imports
end end
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) def age_known(xml_doc, index, hhmemb)
return nil if hhmemb.present? && index > hhmemb return nil if hhmemb.present? && index > hhmemb
@ -473,16 +400,6 @@ module Imports
end end
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) def london_affordable_rent(xml_doc)
lar = unsafe_string_as_integer(xml_doc, "LAR") lar = unsafe_string_as_integer(xml_doc, "LAR")
if lar == 1 if lar == 1
@ -502,34 +419,6 @@ module Imports
end end
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 # Letters should be lowercase to match case
def housing_needs(xml_doc, letter) def housing_needs(xml_doc, letter)
housing_need = string_or_nil(xml_doc, "Q10-#{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

450
app/services/imports/sales_logs_import_service.rb

@ -0,0 +1,450 @@
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["mscharge_known"] ||= 0 if attributes["ownershipsch"] == 3
attributes["mscharge"] ||= 0 if attributes["ownershipsch"] == 3
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

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. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -522,16 +522,18 @@ ActiveRecord::Schema[7.0].define(version: 2023_02_13_140932) do
t.integer "old_persons_shared_ownership_value_check" t.integer "old_persons_shared_ownership_value_check"
t.integer "staircase_bought_value_check" t.integer "staircase_bought_value_check"
t.integer "monthly_charges_value_check" t.integer "monthly_charges_value_check"
t.integer "saledate_check"
t.integer "details_known_5" t.integer "details_known_5"
t.integer "details_known_6" t.integer "details_known_6"
t.integer "saledate_check"
t.integer "prevshared"
t.integer "staircasesale"
t.integer "ethnic_group2" t.integer "ethnic_group2"
t.integer "ethnicbuy2" t.integer "ethnicbuy2"
t.integer "proplen_asked" t.integer "proplen_asked"
t.integer "prevshared"
t.integer "staircasesale"
t.string "old_id"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true
t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id"
t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id" t.index ["updated_by_id"], name: "index_sales_logs_on_updated_by_id"
end end

2
lib/tasks/data_import.rake

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

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

@ -0,0 +1,351 @@
<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>
<!-- replace with commented options to test in the future -->
<!-- <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>

18
spec/lib/tasks/data_import_spec.rb

@ -109,6 +109,24 @@ describe "rake core:data_import", type: :task do
end end
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 context "when importing scheme data" do
let(:type) { "scheme" } let(:type) { "scheme" }
let(:import_service) { instance_double(Imports::SchemeImportService) } let(:import_service) { instance_double(Imports::SchemeImportService) }

595
spec/services/imports/sales_logs_import_service_spec.rb

@ -0,0 +1,595 @@
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 "and it's an outright sale" do
let(:sales_log_id) { "outright_sale_sales_log" }
before do
allow(logger).to receive(:warn).and_return(nil)
end
it "infers mscharge_known as no" do
sales_log_service.send(:create_log, sales_log_xml)
sales_log = SalesLog.find_by(old_id: sales_log_id)
expect(sales_log.mscharge_known).to eq(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