Browse Source
* add class to create logs from bulk upload * create logs when processing bulk uploads * remove bulk_upload_id from csv output * create bulk upload logs only if all valid - this will be changed later to allow for partial logs - and only to create logs when a threshold has been met * add method to blank invalid non setup fields * bulk upload log creation blanks invalid fields * fix incorrect logic for bulk upload renewal * fix linting * bulk upload log creation fail logs to sentry * fix bulk upload line ending parsing * extract bulk uploading csv parsing to class * use csv parser in log creator * change handle line endings mechanism - we now strip all windows line endings for unix based line endings - this normalises things making it simplerpull/1221/head
Phil Lee
2 years ago
committed by
GitHub
18 changed files with 638 additions and 47 deletions
@ -0,0 +1,54 @@
|
||||
require "csv" |
||||
|
||||
class BulkUpload::Lettings::CsvParser |
||||
attr_reader :path |
||||
|
||||
def initialize(path:) |
||||
@path = path |
||||
end |
||||
|
||||
def row_offset |
||||
5 |
||||
end |
||||
|
||||
def col_offset |
||||
1 |
||||
end |
||||
|
||||
def cols |
||||
@cols ||= ("A".."EE").to_a |
||||
end |
||||
|
||||
def row_parsers |
||||
@row_parsers ||= body_rows.map do |row| |
||||
stripped_row = row[1..] |
||||
headers = ("field_1".."field_134").to_a |
||||
hash = Hash[headers.zip(stripped_row)] |
||||
|
||||
BulkUpload::Lettings::RowParser.new(hash) |
||||
end |
||||
end |
||||
|
||||
def body_rows |
||||
rows[row_offset..] |
||||
end |
||||
|
||||
def rows |
||||
@rows ||= CSV.parse(normalised_string, row_sep:) |
||||
end |
||||
|
||||
private |
||||
|
||||
def row_sep |
||||
"\n" |
||||
end |
||||
|
||||
def normalised_string |
||||
return @normalised_string if @normalised_string |
||||
|
||||
@normalised_string = File.read(path) |
||||
@normalised_string.gsub!("\r\n", "\n") |
||||
|
||||
@normalised_string |
||||
end |
||||
end |
@ -0,0 +1,57 @@
|
||||
class BulkUpload::Lettings::LogCreator |
||||
attr_reader :bulk_upload, :path |
||||
|
||||
def initialize(bulk_upload:, path:) |
||||
@bulk_upload = bulk_upload |
||||
@path = path |
||||
end |
||||
|
||||
def call |
||||
row_parsers.each do |row_parser| |
||||
row_parser.valid? |
||||
|
||||
row_parser.log.blank_invalid_non_setup_fields! |
||||
row_parser.log.bulk_upload = bulk_upload |
||||
|
||||
begin |
||||
row_parser.log.save! |
||||
rescue StandardError => e |
||||
Sentry.capture_exception(e) |
||||
end |
||||
end |
||||
end |
||||
|
||||
private |
||||
|
||||
def csv_parser |
||||
@csv_parser ||= BulkUpload::Lettings::CsvParser.new(path:) |
||||
end |
||||
|
||||
def row_offset |
||||
csv_parser.row_offset |
||||
end |
||||
|
||||
def col_offset |
||||
csv_parser.col_offset |
||||
end |
||||
|
||||
def row_parsers |
||||
return @row_parsers if @row_parsers |
||||
|
||||
@row_parsers = csv_parser.row_parsers |
||||
|
||||
@row_parsers.each do |row_parser| |
||||
row_parser.bulk_upload = bulk_upload |
||||
end |
||||
|
||||
@row_parsers |
||||
end |
||||
|
||||
def body_rows |
||||
csv_parser.body_rows |
||||
end |
||||
|
||||
def rows |
||||
csv_parser.rows |
||||
end |
||||
end |
@ -0,0 +1,6 @@
|
||||
class AddBulkUploadToLogs < ActiveRecord::Migration[7.0] |
||||
def change |
||||
add_reference :lettings_logs, :bulk_upload |
||||
add_reference :sales_logs, :bulk_upload |
||||
end |
||||
end |
Can't render this file because it has a wrong number of fields in line 72.
|
@ -0,0 +1,68 @@
|
||||
require "rails_helper" |
||||
|
||||
RSpec.describe BulkUpload::Lettings::LogCreator do |
||||
subject(:service) { described_class.new(bulk_upload:, path:) } |
||||
|
||||
let(:owning_org) { create(:organisation, old_visible_id: 123) } |
||||
let(:user) { create(:user, organisation: owning_org) } |
||||
|
||||
let(:bulk_upload) { create(:bulk_upload, :lettings, user:) } |
||||
let(:path) { file_fixture("2022_23_lettings_bulk_upload.csv") } |
||||
|
||||
describe "#call" do |
||||
context "when a valid csv with new log" do |
||||
it "creates a new log" do |
||||
expect { service.call }.to change(LettingsLog, :count) |
||||
end |
||||
|
||||
it "associates log with bulk upload" do |
||||
service.call |
||||
|
||||
log = LettingsLog.last |
||||
expect(log.bulk_upload).to eql(bulk_upload) |
||||
expect(bulk_upload.lettings_logs).to include(log) |
||||
end |
||||
end |
||||
|
||||
context "when a valid csv with row with one invalid non setup field" do |
||||
let(:file) { Tempfile.new } |
||||
let(:path) { file.path } |
||||
let(:log) do |
||||
build( |
||||
:lettings_log, |
||||
:completed, |
||||
renttype: 3, |
||||
age1: 5, |
||||
owning_organisation: owning_org, |
||||
managing_organisation: owning_org, |
||||
national: 18, |
||||
waityear: 9, |
||||
joint: 2, |
||||
tenancy: 9, |
||||
ppcodenk: 0, |
||||
) |
||||
end |
||||
|
||||
before do |
||||
5.times { file.write "\n" } |
||||
file.write(BulkUpload::LogToCsv.new(log:).to_csv_row) |
||||
file.rewind |
||||
end |
||||
|
||||
it "creates the log" do |
||||
expect { service.call }.to change(LettingsLog, :count).by(1) |
||||
end |
||||
|
||||
it "blanks invalid field" do |
||||
service.call |
||||
|
||||
record = LettingsLog.last |
||||
expect(record.age1).to be_blank |
||||
end |
||||
end |
||||
|
||||
context "when valid csv with existing log" do |
||||
xit "what should happen?" |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,255 @@
|
||||
class BulkUpload::LogToCsv |
||||
attr_reader :log, :line_ending |
||||
|
||||
def initialize(log:, line_ending: "\n") |
||||
@log = log |
||||
@line_ending = line_ending |
||||
end |
||||
|
||||
def to_csv_row |
||||
[ |
||||
nil, # 0 |
||||
log.renttype, # 1 |
||||
nil, |
||||
nil, |
||||
log.scheme&.old_visible_id, |
||||
log.location&.old_visible_id, |
||||
nil, |
||||
log.tenancycode, |
||||
log.startertenancy, |
||||
log.tenancy, |
||||
log.tenancyother, # 10 |
||||
log.tenancylength, |
||||
log.age1, |
||||
log.age2, |
||||
log.age3, |
||||
log.age4, |
||||
log.age5, |
||||
log.age6, |
||||
log.age7, |
||||
log.age8, |
||||
|
||||
log.sex1, # 20 |
||||
log.sex2, |
||||
log.sex3, |
||||
log.sex4, |
||||
log.sex5, |
||||
log.sex6, |
||||
log.sex7, |
||||
log.sex8, |
||||
|
||||
log.relat2, |
||||
log.relat3, |
||||
log.relat4, # 30 |
||||
log.relat5, |
||||
log.relat6, |
||||
log.relat7, |
||||
log.relat8, |
||||
|
||||
log.ecstat1, |
||||
log.ecstat2, |
||||
log.ecstat3, |
||||
log.ecstat4, |
||||
log.ecstat5, |
||||
log.ecstat6, # 40 |
||||
log.ecstat7, |
||||
log.ecstat8, |
||||
|
||||
log.ethnic, |
||||
log.national, |
||||
log.armedforces, |
||||
log.reservist, |
||||
log.preg_occ, |
||||
log.hb, |
||||
log.benefits, |
||||
log.earnings, # 50 |
||||
net_income_known, |
||||
nil, |
||||
log.reasonother, |
||||
nil, |
||||
nil, |
||||
nil, |
||||
nil, |
||||
nil, |
||||
nil, |
||||
nil, # 60 |
||||
log.prevten, |
||||
log.prevloc, |
||||
((log.ppostcode_full || "").split(" ") || [""]).first, |
||||
((log.ppostcode_full || "").split(" ") || [""]).last, |
||||
previous_postcode_known, |
||||
log.layear, |
||||
log.waityear, |
||||
homeless, |
||||
log.reasonpref, |
||||
log.rp_homeless, # 70 |
||||
log.rp_insan_unsat, |
||||
log.rp_medwel, |
||||
log.rp_hardship, |
||||
log.rp_dontknow, |
||||
cbl, |
||||
chr, |
||||
cap, |
||||
log.referral, |
||||
log.period, |
||||
|
||||
log.brent, # 80 |
||||
log.scharge, |
||||
log.pscharge, |
||||
log.supcharg, |
||||
log.tcharge, |
||||
log.chcharge, |
||||
log.household_charge, |
||||
log.hbrentshortfall, |
||||
log.tshortfall, |
||||
log.voiddate&.day, |
||||
|
||||
log.voiddate&.month, # 90 |
||||
log.voiddate&.strftime("%y"), |
||||
log.mrcdate&.day, |
||||
log.mrcdate&.month, |
||||
log.mrcdate&.strftime("%y"), |
||||
nil, |
||||
log.startdate&.day, |
||||
log.startdate&.month, |
||||
log.startdate&.strftime("%y"), |
||||
log.offered, |
||||
|
||||
log.propcode, # 100 |
||||
log.beds, |
||||
log.unittype_gn, |
||||
log.builtype, |
||||
log.wchair, |
||||
log.unitletas, |
||||
log.rsnvac, |
||||
log.la, |
||||
((log.postcode_full || "").split(" ") || [""]).first, |
||||
((log.postcode_full || "").split(" ") || [""]).last, |
||||
|
||||
nil, # 110 |
||||
log.owning_organisation&.old_visible_id, |
||||
nil, |
||||
log.managing_organisation&.old_visible_id, |
||||
leftreg, |
||||
nil, |
||||
log.incfreq, |
||||
log.sheltered, |
||||
log.illness, |
||||
log.illness_type_1, |
||||
|
||||
log.illness_type_2, # 120 |
||||
log.illness_type_3, |
||||
log.illness_type_4, |
||||
log.illness_type_5, |
||||
log.illness_type_6, |
||||
log.illness_type_7, |
||||
log.illness_type_8, |
||||
log.illness_type_9, |
||||
log.illness_type_10, |
||||
london_affordable_rent, |
||||
|
||||
intermediate_rent_type, # 130 |
||||
log.irproduct_other, |
||||
log.declaration, |
||||
log.joint, |
||||
renewal, |
||||
line_ending, |
||||
].join(",") |
||||
end |
||||
|
||||
def renewal |
||||
case log.renewal |
||||
when 1 |
||||
1 |
||||
when 0 |
||||
2 |
||||
end |
||||
end |
||||
|
||||
def london_affordable_rent |
||||
case log.renttype |
||||
when Imports::LettingsLogsImportService::RENT_TYPE[:london_affordable_rent] |
||||
1 |
||||
end |
||||
end |
||||
|
||||
def intermediate_rent_type |
||||
case log.renttype |
||||
when Imports::LettingsLogsImportService::RENT_TYPE[:rent_to_buy] |
||||
1 |
||||
when Imports::LettingsLogsImportService::RENT_TYPE[:london_living_rent] |
||||
2 |
||||
when Imports::LettingsLogsImportService::RENT_TYPE[:other_intermediate_rent_product] |
||||
3 |
||||
end |
||||
end |
||||
|
||||
def leftreg |
||||
case log.leftreg |
||||
when 3 |
||||
3 |
||||
when 1 |
||||
4 |
||||
when 2 |
||||
5 |
||||
when 0 |
||||
6 |
||||
end |
||||
end |
||||
|
||||
def net_income_known |
||||
case log.net_income_known |
||||
when 0 |
||||
1 |
||||
when 1 |
||||
2 |
||||
when 2 |
||||
4 |
||||
end |
||||
end |
||||
|
||||
def previous_postcode_known |
||||
case log.ppcodenk |
||||
when 1 |
||||
1 |
||||
when 0 |
||||
2 |
||||
end |
||||
end |
||||
|
||||
def homeless |
||||
case log.homeless |
||||
when 1 |
||||
1 |
||||
when 11 |
||||
12 |
||||
end |
||||
end |
||||
|
||||
def cbl |
||||
case log.cbl |
||||
when 0 |
||||
2 |
||||
when 1 |
||||
1 |
||||
end |
||||
end |
||||
|
||||
def chr |
||||
case log.chr |
||||
when 0 |
||||
2 |
||||
when 1 |
||||
1 |
||||
end |
||||
end |
||||
|
||||
def cap |
||||
case log.cap |
||||
when 0 |
||||
2 |
||||
when 1 |
||||
1 |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue