diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index 3cab1fe23..7933ac204 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -2,7 +2,10 @@ class BulkUpload < ApplicationRecord enum log_type: { lettings: "lettings", sales: "sales" } belongs_to :user + has_many :bulk_upload_errors + has_many :lettings_logs + has_many :sales_logs after_initialize :generate_identifier, unless: :identifier diff --git a/app/models/log.rb b/app/models/log.rb index 0d0df6451..63612326a 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -5,6 +5,8 @@ class Log < ApplicationRecord belongs_to :managing_organisation, class_name: "Organisation", optional: true belongs_to :created_by, class_name: "User", optional: true belongs_to :updated_by, class_name: "User", optional: true + belongs_to :bulk_upload, optional: true + before_save :update_status! STATUS = { "not_started" => 0, "in_progress" => 1, "completed" => 2 }.freeze diff --git a/app/services/bulk_upload/lettings/log_creator.rb b/app/services/bulk_upload/lettings/log_creator.rb new file mode 100644 index 000000000..64d7f6cc7 --- /dev/null +++ b/app/services/bulk_upload/lettings/log_creator.rb @@ -0,0 +1,66 @@ +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| + next unless row_parser.valid? + + row_parser.log.bulk_upload = bulk_upload + row_parser.log.save + end + end + +private + + def row_offset + 5 + end + + def col_offset + 1 + end + + def row_parsers + @row_parsers ||= body_rows.map do |row| + stripped_row = row[col_offset..] + headers = ("field_1".."field_134").to_a + hash = Hash[headers.zip(stripped_row)] + hash[:bulk_upload] = bulk_upload + + BulkUpload::Lettings::RowParser.new(hash) + end + end + + def body_rows + rows[row_offset..] + end + + def rows + @rows ||= CSV.read(path, row_sep:) + end + + # determine the row seperator from CSV + # Windows will use \r\n + def row_sep + contents = "" + + File.open(path, "r") do |f| + f.seek(9900) + contents = f.read + end + + rn_count = contents.scan("\r\n").count + n_count = contents.scan(/[^\r]\n/).count + + if rn_count > n_count + "\r\n" + else + "\n" + end + end +end diff --git a/db/migrate/20230113154518_add_bulk_upload_to_logs.rb b/db/migrate/20230113154518_add_bulk_upload_to_logs.rb new file mode 100644 index 000000000..ceff40fc9 --- /dev/null +++ b/db/migrate/20230113154518_add_bulk_upload_to_logs.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 9e02d77e4..ca526f253 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -265,6 +265,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_16_151942) do t.integer "housingneeds_other" t.boolean "unresolved" t.bigint "updated_by_id" + t.bigint "bulk_upload_id" + t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id" t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id" t.index ["location_id"], name: "index_lettings_logs_on_location_id" t.index ["managing_organisation_id"], name: "index_lettings_logs_on_managing_organisation_id" diff --git a/spec/fixtures/files/2022_23_lettings_bulk_upload.csv b/spec/fixtures/files/2022_23_lettings_bulk_upload.csv index b767b6e64..4a6b8c843 100644 --- a/spec/fixtures/files/2022_23_lettings_bulk_upload.csv +++ b/spec/fixtures/files/2022_23_lettings_bulk_upload.csv @@ -70,3 +70,4 @@ or 106 = 15 - 17",No,"Only if 1 = 2, 4, 6, 8, 10 or 12",,,,No,,No,"Yes, if 45 = Bulk upload format and duplicate check,All lettings,Question removed from 22/23 onwards,,Supported housing only,,Question Removed from 2020/21,,,,,,Duplicate check field,,,,,,,,Duplicate check field,,,,,,,,,,,,,,,Duplicate check field,,,,,,,,,,,,,,,,,,,Question removed from 22/23 onwards,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Duplicate check field,,,,,,,,,,,Question removed from 22/23 onwards,Duplicate check fields,,,,Duplicate check field,General Needs lettings only,,,All lettings,General Needs lettings only,All lettings,General Needs lettings only,,,Question removed from 2020/21,Duplicate check field, “Username does not exist”. ,,,Question removed from 21/22 onwards,,Supported Housing lettings only.,,,,,,,,,,,,Affordable Rent Lettings only,Intermediate Rent Lettings only,,All lettings,All lettings,, Bulk upload field number,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134, ,1,,,,,,123,1,2,,6,55,54,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,1,,,,,,123,1,2,,,55,54,,,,,,,"A",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,1,23,,,,,,,,,,,,,123,,123,,,,,,,,,,,,,,,,,,,,,2, diff --git a/spec/services/bulk_upload/lettings/log_creator_spec.rb b/spec/services/bulk_upload/lettings/log_creator_spec.rb new file mode 100644 index 000000000..734907898 --- /dev/null +++ b/spec/services/bulk_upload/lettings/log_creator_spec.rb @@ -0,0 +1,31 @@ +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 valid csv with existing log" do + xit "what should happen?" + end + end +end