From f57b1b12959761d28e79026bf273f037d74b8add Mon Sep 17 00:00:00 2001 From: Nat Dean-Lewis Date: Fri, 6 Feb 2026 17:42:55 +0000 Subject: [PATCH] CLDC-4177: csv parser updates --- app/helpers/bulk_upload/sales_log_to_csv.rb | 10 +- .../bulk_upload/sales/year2026/csv_parser.rb | 2 +- spec/fixtures/exports/sales_log.xml | 6 + .../sales_download_26_27.csv | 281 ++++++++++++++++++ .../tasks/log_variable_definitions_spec.rb | 5 +- 5 files changed, 300 insertions(+), 4 deletions(-) create mode 100644 spec/fixtures/variable_definitions/sales_download_26_27.csv diff --git a/app/helpers/bulk_upload/sales_log_to_csv.rb b/app/helpers/bulk_upload/sales_log_to_csv.rb index 18e58655b..db0310f67 100644 --- a/app/helpers/bulk_upload/sales_log_to_csv.rb +++ b/app/helpers/bulk_upload/sales_log_to_csv.rb @@ -537,7 +537,15 @@ class BulkUpload::SalesLogToCsv def to_2026_row # TODO: CLDC-4162: Implement when 2026 template is available - to_2025_row + to_2025_row + + [ + log.sexrab1, + log.sexrab2, + log.sexrab3, + log.sexrab4, + log.sexrab5, + log.sexrab6, # 127 + ] end def custom_field_numbers_row(seed: nil, field_numbers: nil) diff --git a/app/services/bulk_upload/sales/year2026/csv_parser.rb b/app/services/bulk_upload/sales/year2026/csv_parser.rb index 069ead551..e6a6fa9c0 100644 --- a/app/services/bulk_upload/sales/year2026/csv_parser.rb +++ b/app/services/bulk_upload/sales/year2026/csv_parser.rb @@ -5,7 +5,7 @@ class BulkUpload::Sales::Year2026::CsvParser # TODO: CLDC-4162: Update when 2026 format is known FIELDS = 127 - MAX_COLUMNS = FIELDS + MAX_COLUMNS = FIELDS + 1 FORM_YEAR = 2026 attr_reader :path diff --git a/spec/fixtures/exports/sales_log.xml b/spec/fixtures/exports/sales_log.xml index 37dc6dda5..601c75be9 100644 --- a/spec/fixtures/exports/sales_log.xml +++ b/spec/fixtures/exports/sales_log.xml @@ -8,12 +8,14 @@ 1 2 27 + F F 17 1 1 33 P + X X 2 1 @@ -32,6 +34,7 @@ 1 1 + F F 20000.0 1 @@ -44,8 +47,11 @@ R R 4 + X X + M M + X X diff --git a/spec/fixtures/variable_definitions/sales_download_26_27.csv b/spec/fixtures/variable_definitions/sales_download_26_27.csv new file mode 100644 index 000000000..cf5641921 --- /dev/null +++ b/spec/fixtures/variable_definitions/sales_download_26_27.csv @@ -0,0 +1,281 @@ +ID,Log ID +STATUS,Status of log +DUPLICATESET,ID of a set of duplicate logs +CREATEDDATE,Time and date the log was created +UPLOADDATE,Time and date the log was last updated +COLLECTIONYEAR,Year collection period opened +CREATIONMETHOD,Was the log submitted in-service or via bulk upload? +BULKUPLOADID,ID of a set of bulk uploaded logs +DATAPROTECT,Is the user in the created_by column the data protection officer? +OWNINGORGNAME,Which organisation owned this property before the sale? +MANINGORGNAME,Which organisation reported the sale? +CREATEDBY,User that created the log +USERNAME,User the log is assigned to +DAY,Day of sale completion date +MONTH,Month of sale completion date +YEAR,Year of sale completion date +PURCHID,What is the purchaser code? +OWNERSHIP,Was this purchase made through an ownership scheme? +TYPE,What is the type of shared ownership/discounted ownership/outright sale? +OTHTYPE,If type = 'Other', what is the type of outright sale? +COMPANY,Is the buyer a company? +LIVEINBUYER,Will the buyer(s) live in the property? +JOINT,Is this a joint purchase? +JOINTMORE,Are there more than 2 joint buyers of this property? +NOINT,Did you interview the buyer to answer these questions? +PRIVACYNOTICE,Has the buyer seen the MHCLG privacy notice? +UPRN,What is the UPRN of the property? +ADDRESS1,Address line 1 +ADDRESS2,Address line 2 +TOWNCITY,Town/City +COUNTY,County +POSTCODE,Postcode +ISLAINFERRED,The internal value to indicate if the LA was inferred from the postcode +LANAME,LA name +LA,LA code +UPRNSELECTED,UPRN of the address selected +ADDRESS_SEARCH_VALUE_CHECK,Was the 'No address found' page seen? +ADDRESS1INPUT,Address line 1 input from address matching feature +POSTCODEINPUT,Postcode input from address matching feature +BULKADDRESS1,Address line 1 entered in bulk upload file +BULKADDRESS2,Address line 2 entered in bulk upload file +BULKTOWNCITY,Town or city entered in bulk upload file +BULKCOUNTY,County entered in bulk upload file +BULKPOSTCODE,Postcode entered in bulk upload file +BULKLA,Local authority entered in bulk upload file +BEDS,How many bedrooms does the property have? +PROPTYPE,What type of unit is the property? +BUILTYPE,Which type of building is the property? +WCHAIR,Is the property built or adapted to wheelchair-user standards? +AGE1,What is buyer 1's age? +SEX1,Which of these best describes buyer 1's gender identity? +ETHNICGROUP1,What is buyer 1's ethnic group? +ETHNIC,Which of the following best describes buyer 1's ethnic background? +NATIONALITYALL1,What is buyer 1's nationality? +ECSTAT1,Which of these best describes buyer 1's working situation? +LIVEINBUYER1,Will buyer 1 live in the property? +RELAT2,What is buyer 2 or person 2's relationship to buyer 1? +AGE2,What is buyer 2 or person 2's age? +SEX2,Which of these best describes buyer 2 or person 2's gender identity? +ETHNICGROUP2,What is buyer 2's ethnic group? +ETHNIC2,Which of the following best describes buyer 2's ethnic background? +NATIONALITYALL2,What is buyer 2's nationality? +ECSTAT2,What is buyer 2 or person 2's working situation? +LIVEINBUYER2,Will buyer 2 live in the property? +HHTYPE,Besides the buyer(s), how many other people live or will live in the property? +RELAT3,What is person 3's relationship to buyer 1? +AGE3,What is person 3's age? +SEX3,What is person 3's gender identity? +ECSTAT3,What is person 3's working situation? +RELAT4,What is person 4's relationship to buyer 1? +AGE4,What is person 4's age? +SEX4,What is person 4's gender identity? +ECSTAT4,What is person 4's working situation? +RELAT5,What is person 5's relationship to buyer 1? +AGE5,What is person 5's age? +SEX5,What is person 5's gender identity? +ECSTAT5,What is person 5's working situation? +RELAT6,What is person 6's relationship to buyer 1? +AGE6,What is person 6's age? +SEX6,What is person 6's gender identity? +ECSTAT6,What is person 6's working situation? +PREVTEN,What was buyer 1's previous tenure? +PPCODENK,Do you know the postcode of buyer 1's last settled accommodation? +PPOSTC1,Part 1 of postcode of buyer 1's last settled accommodation +PPOSTC2,Part 2 of postcode of buyer 1's last settled accommodation +PREVIOUSLAKNOWN,Do you know the local authority of buyer 1's last settled accommodation? +PREVLOC,The local authority code of buyer 1's last settled accommodation +PREVLOCNAME,The local authority name of buyer 1's last settled accommodation +PREGYRHA,Was the buyer registered with their PRP (HA)? +PREGOTHER,Was the buyer registered with another PRP (HA)? +PREGLA,Was the buyer registered with the local authority? +PREGGHB,Was the buyer registered with a Help to Buy agent? +PREGBLANK,Populated if pregyrha, pregother, pregla and pregghb are blank +BUY2LIVING,At the time of purchase, was buyer 2 living at the same address as buyer 1? +PREVTEN2,What was buyer 2's previous tenure? +HHREGRES,Have any of the buyers ever served as a regular in the UK armed forces? +HHREGRESSTILL,Is the buyer still serving in the UK armed forces? +ARMEDFORCESSPOUSE,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years? +DISABLED,Does anyone in the household consider themselves to have a disability? +WHEEL,Does anyone in the household use a wheelchair? +INC1NK,Is buyer 1's annual income known? +INCOME1,What is buyer 1's annual income? +INC1MORT,Was buyer 1's income used for a mortgage application? +INC2NK,Is buyer 1's annual income known? +INCOME2,What is buyer 2's annual income? +INC2MORT,Was buyer 2's income used for a mortgage application? +HB,Were the buyers receiving any of these housing-related benefits immediately before buying this property? +SAVINGSNK,Is the the total amount the buyers had in savings known? +SAVINGS,What is the total amount the buyers had in savings before they paid any deposit for the property? +PREVOWN,Have any of the buyers previously owned a property? +PREVSHARED,Was the previous property under shared ownership? +PROPLEN,How long did the buyer(s) live in the property before purchasing it? +STAIRCASE,Is this a staircasing transaction? +STAIRBOUGHT,What percentage of the property has been bought in this staircasing transaction? +STAIROWNED,What percentage of the property do the buyers now own in total? +STAIRCASETOSALE,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market? +RESALE,Is this a resale? +EXDAY,Day of the exchange of contracts +EXMONTH,Month of the exchange of contracts +EXYEAR,Year of the exchange of contracts +HODAY,Day of the practical completion or handover date +HOMONTH,Month of the practical completion or handover date +HOYEAR,Year of the practical completion or handover date +LANOMAGR,Was the household rehoused under a local authority nominations agreement? +SOCTEN,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale? +FROMBEDS,How many bedrooms did the buyer's previous property have? +FROMPROP,What was the previous property type? +SOCPREVTEN,What was the rent type of buyer's previous tenure? +VALUE,What is the full purchase price? +VALUE_VALUE_CHECK,Populated if a soft validation is confirmed. +EQUITY,What was the initial percentage equity stake purchased? +MORTGAGEUSED,Was a mortgage used to buy this property? +MORTGAGE,What is the mortgage amount? +MORTGAGELENDER,What is the name of the mortgage lender? +MORTGAGELENDEROTHER,If mortgagelender = 'Other', what is the name of the mortgage lender? +MORTLEN1,What is the length of the mortgage in years? +EXTRABOR,Does this include any extra borrowing? +DEPOSIT,How much was the cash deposit paid on the property? +CASHDIS,How much cash discount was given through Social Homebuy? +MRENT,What is the basic monthly rent? +HASMSCHARGE,Does the property have any monthly leasehold charges? +MSCHARGE,What are the total monthly leasehold charges for the property? +MSCHARGE_VALUE_CHECK,Populated if a soft validation is confirmed. +DISCOUNT,What was the percentage discount? +GRANT,What was the amount of any loan, grant, discount or subsidy given? +id,Log ID +status,Status of log +duplicate_set_id,ID of a set of duplicate logs +created_at,Time and date the log was created +updated_at,Time and date the log was last updated +old_form_id,The ID on the old service +collection_start_year,Year collection period opened +creation_method,Was the log submitted in-service or via bulk upload? +is_dpo,Is the user in the assigned_to column the data protection officer? +owning_organisation_name,Which organisation owned this property before the sale? +managing_organisation_name,Which organisation reported the sale? +assigned_to,User the log is assigned to +day,Day of sale completion date +month,Month of sale completion date +year,Year of sale completion date +purchid,What is the purchaser code? +ownershipsch,Was this purchase made through an ownership scheme? +type,What is the type of shared ownership/discounted ownership/outright sale? +othtype,If type = 'Other', what is the type of outright sale? +companybuy,Is the buyer a company? +buylivein,Will the buyer(s) live in the property? +jointpur,Is this a joint purchase? +jointmore,Are there more than 2 joint buyers of this property? +beds,How many bedrooms does the property have? +proptype,What type of unit is the property? +builtype,Which type of building is the property? +uprn,What is the UPRN of the property? +uprn_confirmed,We found an address that might be this property. Is this the property address? +address_line1_input,Address line 1 input from address matching feature +postcode_full_input,Postcode input from address matching feature +uprn_selection,UPRN of the address selected +address_line1,Address line 1 +address_line2,Address line 2 +town_or_city,Town/City +county,County +pcode1,Part 1 of the property's postcode +pcode2,Part 2 of the property's postcode +la,LA code +la_label,LA name +wchair,Is the property built or adapted to wheelchair-user standards? +noint,Did you interview the buyer to answer these questions? +privacynotice,Has the buyer seen the MHCLG privacy notice? +age1,What is buyer 1's age? +sex1,Which of these best describes buyer 1's gender identity? +ethnic_group,What is buyer 1's ethnic group? +ethnic,Which of the following best describes buyer 1's ethnic background? +nationality_all,What is buyer 1's nationality? +ecstat1,Which of these best describes buyer 1's working situation? +buy1livein,Will buyer 1 live in the property? +relat2,What is buyer 2 or person 2's relationship to buyer 1? +age2,What is buyer 2 or person 2's age? +sex2,Which of these best describes buyer 2 or person 2's gender identity? +ethnic_group2,What is buyer 2's ethnic group? +ethnicbuy2,Which of the following best describes buyer 2's ethnic background? +nationality_all_buyer2,What is buyer 2's nationality? +ecstat2,What is buyer 2 or person 2's working situation? +buy2livein,Will buyer 2 live in the property? +hholdcount,Besides the buyer(s), how many other people live or will live in the property? +relat3,What is person 3's relationship to buyer 1? +age3,What is person 3's age? +sex3,What is person 3's gender identity? +ecstat3,What is person 3's working situation? +relat4,What is person 4's relationship to buyer 1? +age4,What is person 4's age? +sex4,What is person 4's gender identity? +ecstat4,What is person 4's working situation? +relat5,What is person 5's relationship to buyer 1? +age5,What is person 5's age? +sex5,What is person 5's gender identity? +ecstat5,What is person 5's working situation? +relat6,What is person 6's relationship to buyer 1? +age6,What is person 6's age? +sex6,What is person 6's gender identity? +ecstat6,What is person 6's working situation? +prevten,What was buyer 1's previous tenure? +ppcodenk,Do you know the postcode of buyer 1's last settled accommodation? +ppostc1,Part 1 of postcode of buyer 1's last settled accommodation +ppostc2,Part 2 of postcode of buyer 1's last settled accommodation +previous_la_known,Do you know the local authority of buyer 1's last settled accommodation? +prevloc,The local authority code of buyer 1's last settled accommodation +prevloc_label,The local authority name of buyer 1's last settled accommodation +pregyrha,Was the buyer registered with their PRP (HA)? +pregother,Was the buyer registered with another PRP (HA)? +pregla,Was the buyer registered with the local authority? +pregghb,Was the buyer registered with a Help to Buy agent? +pregblank,Populated if pregyrha, pregother, pregla and pregghb are blank +buy2living,At the time of purchase, was buyer 2 living at the same address as buyer 1? +prevtenbuy2,What was buyer 2's previous tenure? +hhregres,Have any of the buyers ever served as a regular in the UK armed forces? +hhregresstill,Is the buyer still serving in the UK armed forces? +armedforcesspouse,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years? +disabled,Does anyone in the household consider themselves to have a disability? +wheel,Does anyone in the household use a wheelchair? +income1nk,Is buyer 1's annual income known? +income1,What is buyer 1's annual income? +inc1mort,Was buyer 1's income used for a mortgage application? +income2nk,Is buyer 2's annual income known? +income2,What is buyer 2's annual income? +inc2mort,Was buyer 2's income used for a mortgage application? +hb,Were the buyers receiving any of these housing-related benefits immediately before buying this property? +savingsnk,Is the the total amount the buyers had in savings known? +savings,What is the total amount the buyers had in savings before they paid any deposit for the property? +prevown,Have any of the buyers previously owned a property? +prevshared,Was the previous property under shared ownership? +proplen,How long did the buyer(s) live in the property before purchasing it? +staircase,Is this a staircasing transaction? +stairbought,What percentage of the property has been bought in this staircasing transaction? +stairowned,What percentage of the property do the buyers now own in total? +staircasesale,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market? +resale,Is this a resale? +exday,Day of the exchange of contracts +exmonth,Month of the exchange of contracts +exyear,Year of the exchange of contracts +hoday,Day of the practical completion or handover date +homonth,Month of the practical completion or handover date +hoyear,Year of the practical completion or handover date +lanomagr,Was the household rehoused under a local authority nominations agreement? +soctenant,Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale? +frombeds,How many bedrooms did the buyer's previous property have? +fromprop,What was the previous property type? +socprevten,What was the rent type of buyer's previous tenure? +value,What is the full purchase price? +equity,What was the initial percentage equity stake purchased? +mortgageused,Was a mortgage used to buy this property? +mortgage,What is the mortgage amount? +mortgagelender,What is the name of the mortgage lender? +mortgagelenderother,If mortgagelender = 'Other', what is the name of the mortgage lender? +mortlen,What is the length of the mortgage in years? +extrabor,Does this include any extra borrowing? +deposit,How much was the cash deposit paid on the property? +cashdis,How much cash discount was given through Social Homebuy? +mrent,What is the basic monthly rent? +has_mscharge,Does the property have any monthly leasehold charges? +mscharge,What are the total monthly leasehold charges for the property? +discount,What was the percentage discount? +grant,What was the amount of any loan, grant, discount or subsidy given? diff --git a/spec/lib/tasks/log_variable_definitions_spec.rb b/spec/lib/tasks/log_variable_definitions_spec.rb index 8bae5a4d0..4320b0014 100644 --- a/spec/lib/tasks/log_variable_definitions_spec.rb +++ b/spec/lib/tasks/log_variable_definitions_spec.rb @@ -6,6 +6,7 @@ RSpec.describe "log_variable_definitions" do subject(:task) { Rake::Task["data_import:add_variable_definitions"] } let(:path) { "spec/fixtures/variable_definitions" } + let(:total_variable_definitions_count) { 417 } before do Rake.application.rake_require("tasks/log_variable_definitions") @@ -14,7 +15,7 @@ RSpec.describe "log_variable_definitions" do end it "adds CsvVariableDefinition records from each file in the specified directory" do - expect { task.invoke(path) }.to change(CsvVariableDefinition, :count).by(417) + expect { task.invoke(path) }.to change(CsvVariableDefinition, :count).by(total_variable_definitions_count) end it "handles an empty directory without errors" do @@ -34,7 +35,7 @@ RSpec.describe "log_variable_definitions" do task.invoke(path) second_run_count = CsvVariableDefinition.count - expect(first_run_count).to eq(initial_count + 417) + expect(first_run_count).to eq(initial_count + total_variable_definitions_count) expect(second_run_count).to eq(first_run_count) end end