diff --git a/.github/workflows/review_pipeline.yml b/.github/workflows/review_pipeline.yml index 603a8315c..ae1cb3c27 100644 --- a/.github/workflows/review_pipeline.yml +++ b/.github/workflows/review_pipeline.yml @@ -123,6 +123,7 @@ jobs: cf set-env $APP_NAME CSV_DOWNLOAD_PAAS_INSTANCE $CSV_DOWNLOAD_PAAS_INSTANCE cf set-env $APP_NAME SENTRY_DSN $SENTRY_DSN cf set-env $APP_NAME APP_HOST "https://dluhc-core-review-${{ github.event.pull_request.number }}.london.cloudapps.digital" + cf set-env $APP_NAME CSV_BUCKET "dluhc-core-review-csv-bucket" - name: Bind postgres service env: diff --git a/.github/workflows/staging_pipeline.yml b/.github/workflows/staging_pipeline.yml index d59024cd3..01c7943e8 100644 --- a/.github/workflows/staging_pipeline.yml +++ b/.github/workflows/staging_pipeline.yml @@ -231,4 +231,5 @@ jobs: cf set-env $APP_NAME S3_CONFIG $S3_CONFIG cf set-env $APP_NAME CSV_DOWNLOAD_PAAS_INSTANCE $CSV_DOWNLOAD_PAAS_INSTANCE cf set-env $APP_NAME SENTRY_DSN $SENTRY_DSN + cf set-env $APP_NAME CSV_BUCKET "dluhc-core-staging-csv-bucket" cf push $APP_NAME --strategy rolling diff --git a/app/controllers/bulk_upload_controller.rb b/app/controllers/bulk_upload_controller.rb index ed2ac2627..c045dc066 100644 --- a/app/controllers/bulk_upload_controller.rb +++ b/app/controllers/bulk_upload_controller.rb @@ -2,14 +2,14 @@ class BulkUploadController < ApplicationController before_action :authenticate_user! def show - @bulk_upload = BulkUpload.new(nil, nil) + @bulk_upload = LegacyBulkUpload.new(nil, nil) render "logs/bulk_upload" end def bulk_upload file = upload_params.tempfile content_type = upload_params.content_type - @bulk_upload = BulkUpload.new(file, content_type) + @bulk_upload = LegacyBulkUpload.new(file, content_type) @bulk_upload.process(current_user) if @bulk_upload.errors.present? render "logs/bulk_upload", status: :unprocessable_entity diff --git a/app/controllers/bulk_upload_lettings_logs_controller.rb b/app/controllers/bulk_upload_lettings_logs_controller.rb index aaa25f29e..59d37e2c5 100644 --- a/app/controllers/bulk_upload_lettings_logs_controller.rb +++ b/app/controllers/bulk_upload_lettings_logs_controller.rb @@ -14,7 +14,7 @@ class BulkUploadLettingsLogsController < ApplicationController end def update - if form.valid? + if form.valid? && form.save! redirect_to form.next_path else render form.view_path @@ -38,7 +38,7 @@ private when "prepare-your-file" Forms::BulkUploadLettings::PrepareYourFile.new(form_params) when "upload-your-file" - Forms::BulkUploadLettings::UploadYourFile.new(form_params) + Forms::BulkUploadLettings::UploadYourFile.new(form_params.merge(current_user:)) when "checking-file" Forms::BulkUploadLettings::CheckingFile.new(form_params) else diff --git a/app/controllers/bulk_upload_sales_logs_controller.rb b/app/controllers/bulk_upload_sales_logs_controller.rb index b570a4296..9c344cdf9 100644 --- a/app/controllers/bulk_upload_sales_logs_controller.rb +++ b/app/controllers/bulk_upload_sales_logs_controller.rb @@ -14,7 +14,7 @@ class BulkUploadSalesLogsController < ApplicationController end def update - if form.valid? + if form.valid? && form.save! redirect_to form.next_path else render form.view_path @@ -38,7 +38,7 @@ private when "prepare-your-file" Forms::BulkUploadSales::PrepareYourFile.new(form_params) when "upload-your-file" - Forms::BulkUploadSales::UploadYourFile.new(form_params) + Forms::BulkUploadSales::UploadYourFile.new(form_params.merge(current_user:)) when "checking-file" Forms::BulkUploadSales::CheckingFile.new(form_params) else diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index fa2a7a0e9..8b007f450 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -1,197 +1,13 @@ -class BulkUpload - include ActiveModel::Model - include ActiveModel::Validations - include ActiveModel::Conversion +class BulkUpload < ApplicationRecord + enum log_type: { lettings: "lettings", sales: "sales" } - SPREADSHEET_CONTENT_TYPES = %w[ - application/vnd.ms-excel - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - ].freeze + belongs_to :user - FIRST_DATA_ROW = 7 + after_initialize :generate_identifier, unless: :identifier - def initialize(file, content_type) - @file = file - @content_type = content_type - end - - def process(current_user) - return unless valid_content_type? - - xlsx = Roo::Spreadsheet.open(@file, extension: :xlsx) - sheet = xlsx.sheet(0) - last_row = sheet.last_row - if last_row < FIRST_DATA_ROW - errors.add(:lettings_log_bulk_upload, "No data found") - else - data_range = FIRST_DATA_ROW..last_row - data_range.map do |row_num| - row = sheet.row(row_num) - # owning_organisation = Organisation.find(row[111]) - # managing_organisation = Organisation.find(row[113]) - lettings_log = LettingsLog.create!( - owning_organisation: current_user.organisation, - managing_organisation: current_user.organisation, - created_by: current_user, - ) - map_row(row).each do |attr_key, attr_val| - _update = lettings_log.update(attr_key => attr_val) - rescue ArgumentError - # TODO: determine what we want to do when bulk upload contains totally invalid data for a field. - end - end - end - end - - def valid_content_type? - if SPREADSHEET_CONTENT_TYPES.include?(@content_type) - true - else - errors.add(:lettings_log_bulk_upload, "Invalid file type") - false - end - end - - def map_row(row) - { - lettype: row[1], - # reg_num_la_core_code: row[3], - # managementgroup: row[4], - # schemecode: row[5], - # firstletting: row[6], - tenancycode: row[7], - startertenancy: row[8], - tenancy: row[9], - tenancyother: row[10], - # tenancyduration: row[11], - hhmemb: hhmemb(row), - age1: row[12], - age2: row[13], - age3: row[14], - age4: row[15], - age5: row[16], - age6: row[17], - age7: row[18], - age8: row[19], - sex1: row[20], - sex2: row[21], - sex3: row[22], - sex4: row[23], - sex5: row[24], - sex6: row[25], - sex7: row[26], - sex8: row[27], - relat2: row[28], - relat3: row[29], - relat4: row[30], - relat5: row[31], - relat6: row[32], - relat7: row[33], - relat8: row[34], - ecstat1: row[35], - ecstat2: row[36], - ecstat3: row[37], - ecstat4: row[38], - ecstat5: row[39], - ecstat6: row[40], - ecstat7: row[41], - ecstat8: row[42], - ethnic: row[43], - national: row[44], - armedforces: row[45], - reservist: row[46], - preg_occ: row[47], - hb: row[48], - benefits: row[49], - net_income_known: row[50].present? ? 1 : nil, - earnings: row[50], - # increfused: row[51], - reason: row[52], - reasonother: row[53], - underoccupation_benefitcap: row[54], - housingneeds_a: row[55], - housingneeds_b: row[56], - housingneeds_c: row[57], - housingneeds_f: row[58], - housingneeds_g: row[59], - housingneeds_h: row[60], - prevten: row[61], - prevloc: row[62], - # prevpco_unknown: row[65], - layear: row[66], - waityear: row[67], - homeless: row[68], - reasonpref: row[69], - rp_homeless: row[70], - rp_insan_unsat: row[71], - rp_medwel: row[72], - rp_hardship: row[73], - rp_dontknow: row[74], - cbl: row[75], - chr: row[76], - cap: row[77], - # referral_source: row[78], - period: row[79], - brent: row[80], - scharge: row[81], - pscharge: row[82], - supcharg: row[83], - tcharge: row[84], - # tcharge_care_homes: row[85], - # no_rent_or_charge: row[86], - hbrentshortfall: row[87], - tshortfall: row[88], - voiddate: row[89].to_s + row[90].to_s + row[91].to_s, - majorrepairs: row[92].present? ? "1" : nil, - mrcdate: row[92].to_s + row[93].to_s + row[94].to_s, - # supported_scheme: row[95], - startdate: date_time(row[98], row[97], row[96]), - # startdate_day: row[96], - # startdate_month: row[97], - # startdate_year: row[98], - offered: row[99], - # property_reference: row[100], - beds: row[101], - unittype_gn: row[102], - builtype: row[103], - wchair: row[104], - property_relet: row[105], - rsnvac: row[106], - la: row[107], - # row[110] removed - # row[111] is owning organisation used above - # username: row[112], - # row[113] is managing organisation used above - leftreg: row[114], - # uprn: row[115], - incfreq: row[116], - # sheltered_accom: row[117], - illness: row[118], - illness_type_1: row[119], - illness_type_2: row[120], - illness_type_3: row[121], - illness_type_4: row[122], - illness_type_8: row[123], - illness_type_5: row[124], - illness_type_6: row[125], - illness_type_7: row[126], - illness_type_9: row[127], - illness_type_10: row[128], - # london_affordable: row[129], - rent_type: row[130], - irproduct_other: row[131], - # data_protection: row[132], - declaration: 1, - } - end - - def date_time(year, month, day) - return unless year && month && day - - Time.zone.local("20#{year}", month.to_s, day.to_s) - end +private - def hhmemb(row) - [14, 15, 16, 17, 18, 19, 20].count { |idx| row[idx].present? } + def generate_identifier + self.identifier ||= SecureRandom.uuid end end diff --git a/app/models/forms/bulk_upload_lettings/checking_file.rb b/app/models/forms/bulk_upload_lettings/checking_file.rb index 7e79e9c83..8cd9ee696 100644 --- a/app/models/forms/bulk_upload_lettings/checking_file.rb +++ b/app/models/forms/bulk_upload_lettings/checking_file.rb @@ -18,6 +18,10 @@ module Forms def year_combo "#{year}/#{year + 1 - 2000}" end + + def save! + true + end end end end diff --git a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb index 684ba1437..31a332596 100644 --- a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb @@ -31,6 +31,10 @@ module Forms "#{year}/#{year + 1 - 2000}" end + def save! + true + end + private def in_crossover_period? diff --git a/app/models/forms/bulk_upload_lettings/upload_your_file.rb b/app/models/forms/bulk_upload_lettings/upload_your_file.rb index 29e6f6118..06c7183d1 100644 --- a/app/models/forms/bulk_upload_lettings/upload_your_file.rb +++ b/app/models/forms/bulk_upload_lettings/upload_your_file.rb @@ -7,6 +7,7 @@ module Forms attribute :year, :integer attribute :file + attribute :current_user validates :file, presence: true validate :validate_file_is_csv @@ -27,8 +28,30 @@ module Forms bulk_upload_lettings_log_path(id: "checking-file", form: { year: }) end + def save! + bulk_upload = BulkUpload.create!( + user: current_user, + log_type: BulkUpload.log_types[:lettings], + year:, + ) + + if upload_enabled? + storage_service.write_file(bulk_upload.identifier, File.read(file.path)) + end + + true + end + private + def upload_enabled? + !Rails.env.development? + end + + def storage_service + @storage_service ||= Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["CSV_BUCKET"]) + end + def validate_file_is_csv return unless file diff --git a/app/models/forms/bulk_upload_lettings/year.rb b/app/models/forms/bulk_upload_lettings/year.rb index 9fa17b19e..68db63978 100644 --- a/app/models/forms/bulk_upload_lettings/year.rb +++ b/app/models/forms/bulk_upload_lettings/year.rb @@ -27,6 +27,10 @@ module Forms bulk_upload_lettings_log_path(id: "prepare-your-file", form: { year: }) end + def save! + true + end + private def possible_years diff --git a/app/models/forms/bulk_upload_sales/checking_file.rb b/app/models/forms/bulk_upload_sales/checking_file.rb index 64d671e65..a37be3ccb 100644 --- a/app/models/forms/bulk_upload_sales/checking_file.rb +++ b/app/models/forms/bulk_upload_sales/checking_file.rb @@ -18,6 +18,10 @@ module Forms def year_combo "#{year}/#{year + 1 - 2000}" end + + def save! + true + end end end end diff --git a/app/models/forms/bulk_upload_sales/prepare_your_file.rb b/app/models/forms/bulk_upload_sales/prepare_your_file.rb index da017dbbd..955301ac4 100644 --- a/app/models/forms/bulk_upload_sales/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_sales/prepare_your_file.rb @@ -31,6 +31,10 @@ module Forms "#{year}/#{year + 1 - 2000}" end + def save! + true + end + private def in_crossover_period? diff --git a/app/models/forms/bulk_upload_sales/upload_your_file.rb b/app/models/forms/bulk_upload_sales/upload_your_file.rb index def280399..6b5b7a629 100644 --- a/app/models/forms/bulk_upload_sales/upload_your_file.rb +++ b/app/models/forms/bulk_upload_sales/upload_your_file.rb @@ -7,6 +7,7 @@ module Forms attribute :year, :integer attribute :file + attribute :current_user validates :file, presence: true validate :validate_file_is_csv @@ -27,8 +28,30 @@ module Forms bulk_upload_sales_log_path(id: "checking-file", form: { year: }) end + def save! + bulk_upload = BulkUpload.create!( + user: current_user, + log_type: BulkUpload.log_types[:sales], + year:, + ) + + if upload_enabled? + storage_service.write_file(bulk_upload.identifier, File.read(file.path)) + end + + true + end + private + def upload_enabled? + !Rails.env.development? + end + + def storage_service + @storage_service ||= Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["CSV_BUCKET"]) + end + def validate_file_is_csv return unless file diff --git a/app/models/forms/bulk_upload_sales/year.rb b/app/models/forms/bulk_upload_sales/year.rb index 361061990..2d4b48e4a 100644 --- a/app/models/forms/bulk_upload_sales/year.rb +++ b/app/models/forms/bulk_upload_sales/year.rb @@ -27,6 +27,10 @@ module Forms bulk_upload_sales_log_path(id: "prepare-your-file", form: { year: }) end + def save! + true + end + private def possible_years diff --git a/app/models/legacy_bulk_upload.rb b/app/models/legacy_bulk_upload.rb new file mode 100644 index 000000000..e80321d04 --- /dev/null +++ b/app/models/legacy_bulk_upload.rb @@ -0,0 +1,197 @@ +class LegacyBulkUpload + include ActiveModel::Model + include ActiveModel::Validations + include ActiveModel::Conversion + + SPREADSHEET_CONTENT_TYPES = %w[ + application/vnd.ms-excel + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + ].freeze + + FIRST_DATA_ROW = 7 + + def initialize(file, content_type) + @file = file + @content_type = content_type + end + + def process(current_user) + return unless valid_content_type? + + xlsx = Roo::Spreadsheet.open(@file, extension: :xlsx) + sheet = xlsx.sheet(0) + last_row = sheet.last_row + if last_row < FIRST_DATA_ROW + errors.add(:lettings_log_bulk_upload, "No data found") + else + data_range = FIRST_DATA_ROW..last_row + data_range.map do |row_num| + row = sheet.row(row_num) + # owning_organisation = Organisation.find(row[111]) + # managing_organisation = Organisation.find(row[113]) + lettings_log = LettingsLog.create!( + owning_organisation: current_user.organisation, + managing_organisation: current_user.organisation, + created_by: current_user, + ) + map_row(row).each do |attr_key, attr_val| + _update = lettings_log.update(attr_key => attr_val) + rescue ArgumentError + # TODO: determine what we want to do when bulk upload contains totally invalid data for a field. + end + end + end + end + + def valid_content_type? + if SPREADSHEET_CONTENT_TYPES.include?(@content_type) + true + else + errors.add(:lettings_log_bulk_upload, "Invalid file type") + false + end + end + + def map_row(row) + { + lettype: row[1], + # reg_num_la_core_code: row[3], + # managementgroup: row[4], + # schemecode: row[5], + # firstletting: row[6], + tenancycode: row[7], + startertenancy: row[8], + tenancy: row[9], + tenancyother: row[10], + # tenancyduration: row[11], + hhmemb: hhmemb(row), + age1: row[12], + age2: row[13], + age3: row[14], + age4: row[15], + age5: row[16], + age6: row[17], + age7: row[18], + age8: row[19], + sex1: row[20], + sex2: row[21], + sex3: row[22], + sex4: row[23], + sex5: row[24], + sex6: row[25], + sex7: row[26], + sex8: row[27], + relat2: row[28], + relat3: row[29], + relat4: row[30], + relat5: row[31], + relat6: row[32], + relat7: row[33], + relat8: row[34], + ecstat1: row[35], + ecstat2: row[36], + ecstat3: row[37], + ecstat4: row[38], + ecstat5: row[39], + ecstat6: row[40], + ecstat7: row[41], + ecstat8: row[42], + ethnic: row[43], + national: row[44], + armedforces: row[45], + reservist: row[46], + preg_occ: row[47], + hb: row[48], + benefits: row[49], + net_income_known: row[50].present? ? 1 : nil, + earnings: row[50], + # increfused: row[51], + reason: row[52], + reasonother: row[53], + underoccupation_benefitcap: row[54], + housingneeds_a: row[55], + housingneeds_b: row[56], + housingneeds_c: row[57], + housingneeds_f: row[58], + housingneeds_g: row[59], + housingneeds_h: row[60], + prevten: row[61], + prevloc: row[62], + # prevpco_unknown: row[65], + layear: row[66], + waityear: row[67], + homeless: row[68], + reasonpref: row[69], + rp_homeless: row[70], + rp_insan_unsat: row[71], + rp_medwel: row[72], + rp_hardship: row[73], + rp_dontknow: row[74], + cbl: row[75], + chr: row[76], + cap: row[77], + # referral_source: row[78], + period: row[79], + brent: row[80], + scharge: row[81], + pscharge: row[82], + supcharg: row[83], + tcharge: row[84], + # tcharge_care_homes: row[85], + # no_rent_or_charge: row[86], + hbrentshortfall: row[87], + tshortfall: row[88], + voiddate: row[89].to_s + row[90].to_s + row[91].to_s, + majorrepairs: row[92].present? ? "1" : nil, + mrcdate: row[92].to_s + row[93].to_s + row[94].to_s, + # supported_scheme: row[95], + startdate: date_time(row[98], row[97], row[96]), + # startdate_day: row[96], + # startdate_month: row[97], + # startdate_year: row[98], + offered: row[99], + # property_reference: row[100], + beds: row[101], + unittype_gn: row[102], + builtype: row[103], + wchair: row[104], + property_relet: row[105], + rsnvac: row[106], + la: row[107], + # row[110] removed + # row[111] is owning organisation used above + # username: row[112], + # row[113] is managing organisation used above + leftreg: row[114], + # uprn: row[115], + incfreq: row[116], + # sheltered_accom: row[117], + illness: row[118], + illness_type_1: row[119], + illness_type_2: row[120], + illness_type_3: row[121], + illness_type_4: row[122], + illness_type_8: row[123], + illness_type_5: row[124], + illness_type_6: row[125], + illness_type_7: row[126], + illness_type_9: row[127], + illness_type_10: row[128], + # london_affordable: row[129], + rent_type: row[130], + irproduct_other: row[131], + # data_protection: row[132], + declaration: 1, + } + end + + def date_time(year, month, day) + return unless year && month && day + + Time.zone.local("20#{year}", month.to_s, day.to_s) + end + + def hhmemb(row) + [14, 15, 16, 17, 18, 19, 20].count { |idx| row[idx].present? } + end +end diff --git a/app/views/logs/bulk_upload.html.erb b/app/views/logs/bulk_upload.html.erb index 0f1b544f7..6d06af7a3 100644 --- a/app/views/logs/bulk_upload.html.erb +++ b/app/views/logs/bulk_upload.html.erb @@ -1,6 +1,6 @@ <% content_for :title, "Bulk upload" %> -<%= form_for @bulk_upload, url: bulk_upload_lettings_logs_path, method: "post" do |f| %> +<%= form_for @bulk_upload, scope: :bulk_upload, url: bulk_upload_lettings_logs_path, method: "post" do |f| %> <%= f.govuk_error_summary %> <%= f.govuk_file_field :lettings_log_bulk_upload, diff --git a/db/migrate/20221128130843_create_bulk_uploads.rb b/db/migrate/20221128130843_create_bulk_uploads.rb new file mode 100644 index 000000000..adb3385b5 --- /dev/null +++ b/db/migrate/20221128130843_create_bulk_uploads.rb @@ -0,0 +1,14 @@ +class CreateBulkUploads < ActiveRecord::Migration[7.0] + def change + create_table :bulk_uploads do |t| + t.references :user + t.text :log_type, null: false + t.integer :year, null: false + t.uuid :identifier, null: false + + t.timestamps + end + + add_index :bulk_uploads, :identifier, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 912eba818..9e55c430a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -14,6 +14,17 @@ ActiveRecord::Schema[7.0].define(version: 2022_12_02_100512) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "bulk_uploads", force: :cascade do |t| + t.bigint "user_id" + t.text "log_type", null: false + t.integer "year", null: false + t.uuid "identifier", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["identifier"], name: "index_bulk_uploads_on_identifier", unique: true + t.index ["user_id"], name: "index_bulk_uploads_on_user_id" + end + create_table "data_protection_confirmations", force: :cascade do |t| t.bigint "organisation_id" t.bigint "data_protection_officer_id" diff --git a/spec/features/bulk_upload_lettings_logs_spec.rb b/spec/features/bulk_upload_lettings_logs_spec.rb index 63d9bce4d..5c2400fa1 100644 --- a/spec/features/bulk_upload_lettings_logs_spec.rb +++ b/spec/features/bulk_upload_lettings_logs_spec.rb @@ -3,7 +3,19 @@ require "rails_helper" RSpec.describe "Bulk upload lettings log" do let(:user) { create(:user) } + let(:stub_file_upload) do + vcap_services = { "aws-s3-bucket" => {} } + mock_storage_service = instance_double("S3Service") + + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services.to_json) + + allow(Storage::S3Service).to receive(:new).and_return(mock_storage_service) + allow(mock_storage_service).to receive(:write_file) + end + before do + stub_file_upload sign_in user end @@ -38,7 +50,9 @@ RSpec.describe "Bulk upload lettings log" do expect(page).to have_content("Your file must be in CSV format") attach_file "file", file_fixture("blank_bulk_upload_sales.csv") - click_button("Upload") + expect { + click_button("Upload") + }.to change(BulkUpload, :count).by(1) expect(page).to have_content("Once this is done") click_link("Back") diff --git a/spec/features/bulk_upload_sales_logs_spec.rb b/spec/features/bulk_upload_sales_logs_spec.rb index b531c90b4..b49713b54 100644 --- a/spec/features/bulk_upload_sales_logs_spec.rb +++ b/spec/features/bulk_upload_sales_logs_spec.rb @@ -3,7 +3,19 @@ require "rails_helper" RSpec.describe "Bulk upload sales log" do let(:user) { create(:user) } + let(:stub_file_upload) do + vcap_services = { "aws-s3-bucket" => {} } + mock_storage_service = instance_double("S3Service") + + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services.to_json) + + allow(Storage::S3Service).to receive(:new).and_return(mock_storage_service) + allow(mock_storage_service).to receive(:write_file) + end + before do + stub_file_upload sign_in user end @@ -38,7 +50,9 @@ RSpec.describe "Bulk upload sales log" do expect(page).to have_content("Your file must be in CSV format") attach_file "file", file_fixture("blank_bulk_upload_sales.csv") - click_button("Upload") + expect { + click_button("Upload") + }.to change(BulkUpload, :count).by(1) expect(page).to have_content("Once this is done") click_link("Back") diff --git a/spec/models/forms/bulk_upload_lettings/upload_your_file_spec.rb b/spec/models/forms/bulk_upload_lettings/upload_your_file_spec.rb new file mode 100644 index 000000000..1199201fa --- /dev/null +++ b/spec/models/forms/bulk_upload_lettings/upload_your_file_spec.rb @@ -0,0 +1,47 @@ +require "rails_helper" + +RSpec.describe Forms::BulkUploadLettings::UploadYourFile do + subject(:form) { described_class.new(year:, file:, current_user:) } + + let(:year) { 2022 } + let(:actual_file) { File.open(file_fixture("blank_bulk_upload_sales.csv")) } + let(:file) { ActionDispatch::Http::UploadedFile.new(tempfile: actual_file) } + let(:current_user) { create(:user) } + let(:mock_storage_service) { instance_double("S3Service") } + + before do + vcap_services = { "aws-s3-bucket" => {} } + + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services.to_json) + + allow(Storage::S3Service).to receive(:new).and_return(mock_storage_service) + allow(mock_storage_service).to receive(:write_file) + end + + describe "#save" do + it "persists a BulkUpload" do + expect { form.save! }.to change(BulkUpload, :count).by(1) + end + + it "persists a BulkUpload correctly" do + form.save! + + bulk_upload = BulkUpload.last + + expect(bulk_upload.user).to eql(current_user) + expect(bulk_upload.log_type).to eql("lettings") + expect(bulk_upload.year).to eql(year) + expect(bulk_upload.identifier).to be_present + end + + it "uploads file via storage service" do + form.save! + + bulk_upload = BulkUpload.last + + expect(Storage::S3Service).to have_received(:new) + expect(mock_storage_service).to have_received(:write_file).with(bulk_upload.identifier, actual_file.read) + end + end +end diff --git a/spec/models/forms/bulk_upload_sales/upload_your_file_spec.rb b/spec/models/forms/bulk_upload_sales/upload_your_file_spec.rb new file mode 100644 index 000000000..1b11b0f82 --- /dev/null +++ b/spec/models/forms/bulk_upload_sales/upload_your_file_spec.rb @@ -0,0 +1,47 @@ +require "rails_helper" + +RSpec.describe Forms::BulkUploadSales::UploadYourFile do + subject(:form) { described_class.new(year:, file:, current_user:) } + + let(:year) { 2022 } + let(:actual_file) { File.open(file_fixture("blank_bulk_upload_sales.csv")) } + let(:file) { ActionDispatch::Http::UploadedFile.new(tempfile: actual_file) } + let(:current_user) { create(:user) } + let(:mock_storage_service) { instance_double("S3Service") } + + before do + vcap_services = { "aws-s3-bucket" => {} } + + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services.to_json) + + allow(Storage::S3Service).to receive(:new).and_return(mock_storage_service) + allow(mock_storage_service).to receive(:write_file) + end + + describe "#save" do + it "persists a BulkUpload" do + expect { form.save! }.to change(BulkUpload, :count).by(1) + end + + it "persists a BulkUpload correctly" do + form.save! + + bulk_upload = BulkUpload.last + + expect(bulk_upload.user).to eql(current_user) + expect(bulk_upload.log_type).to eql("sales") + expect(bulk_upload.year).to eql(year) + expect(bulk_upload.identifier).to be_present + end + + it "uploads file via storage service" do + form.save! + + bulk_upload = BulkUpload.last + + expect(Storage::S3Service).to have_received(:new) + expect(mock_storage_service).to have_received(:write_file).with(bulk_upload.identifier, actual_file.read) + end + end +end diff --git a/spec/requests/bulk_upload_controller_spec.rb b/spec/requests/bulk_upload_controller_spec.rb index bc75dbe84..fc3afd21c 100644 --- a/spec/requests/bulk_upload_controller_spec.rb +++ b/spec/requests/bulk_upload_controller_spec.rb @@ -45,7 +45,7 @@ RSpec.describe BulkUploadController, type: :request do end it "returns a page with a file upload form" do - expect(response.body).to match(/