diff --git a/app/controllers/bulk_upload_lettings_resume_controller.rb b/app/controllers/bulk_upload_lettings_resume_controller.rb index 4c21d39e2..7041051ba 100644 --- a/app/controllers/bulk_upload_lettings_resume_controller.rb +++ b/app/controllers/bulk_upload_lettings_resume_controller.rb @@ -9,6 +9,7 @@ class BulkUploadLettingsResumeController < ApplicationController def show @bulk_upload = current_user.bulk_uploads.find(params[:id]) + @soft_errors_only = params[:soft_errors_only] == "true" render form.view_path end diff --git a/app/controllers/bulk_upload_lettings_soft_validations_check_controller.rb b/app/controllers/bulk_upload_lettings_soft_validations_check_controller.rb new file mode 100644 index 000000000..5f9140452 --- /dev/null +++ b/app/controllers/bulk_upload_lettings_soft_validations_check_controller.rb @@ -0,0 +1,43 @@ +class BulkUploadLettingsSoftValidationsCheckController < ApplicationController + include ActionView::Helpers::TextHelper + + before_action :authenticate_user! + + def show + @bulk_upload = current_user.bulk_uploads.find(params[:id]) + + render form.view_path + end + + def update + @bulk_upload = current_user.bulk_uploads.find(params[:id]) + + if form.valid? && form.save! + if params[:page] == "confirm" + n_logs = pluralize(@bulk_upload.logs.count, "log") + flash[:notice] = "You’ve successfully uploaded #{n_logs}" + end + + redirect_to form.next_path + else + render form.view_path + end + end + +private + + def form + @form ||= case params[:page] + when "confirm-soft-errors" + Forms::BulkUploadLettingsSoftValidationsCheck::ConfirmSoftErrors.new(form_params.merge(bulk_upload: @bulk_upload)) + when "confirm" + Forms::BulkUploadLettingsSoftValidationsCheck::Confirm.new(form_params.merge(bulk_upload: @bulk_upload)) + else + raise "invalid form" + end + end + + def form_params + params.fetch(:form, {}).permit(:confirm_soft_errors) + end +end diff --git a/app/controllers/bulk_upload_sales_resume_controller.rb b/app/controllers/bulk_upload_sales_resume_controller.rb index f38bf24bf..e120620a2 100644 --- a/app/controllers/bulk_upload_sales_resume_controller.rb +++ b/app/controllers/bulk_upload_sales_resume_controller.rb @@ -9,6 +9,7 @@ class BulkUploadSalesResumeController < ApplicationController def show @bulk_upload = current_user.bulk_uploads.find(params[:id]) + @soft_errors_only = params[:soft_errors_only] == "true" render form.view_path end diff --git a/app/controllers/bulk_upload_sales_soft_validations_check_controller.rb b/app/controllers/bulk_upload_sales_soft_validations_check_controller.rb new file mode 100644 index 000000000..6daf167f8 --- /dev/null +++ b/app/controllers/bulk_upload_sales_soft_validations_check_controller.rb @@ -0,0 +1,43 @@ +class BulkUploadSalesSoftValidationsCheckController < ApplicationController + include ActionView::Helpers::TextHelper + + before_action :authenticate_user! + + def show + @bulk_upload = current_user.bulk_uploads.find(params[:id]) + + render form.view_path + end + + def update + @bulk_upload = current_user.bulk_uploads.find(params[:id]) + + if form.valid? && form.save! + if params[:page] == "confirm" + n_logs = pluralize(@bulk_upload.logs.count, "log") + flash[:notice] = "You’ve successfully uploaded #{n_logs}" + end + + redirect_to form.next_path + else + render form.view_path + end + end + +private + + def form + @form ||= case params[:page] + when "confirm-soft-errors" + Forms::BulkUploadSalesSoftValidationsCheck::ConfirmSoftErrors.new(form_params.merge(bulk_upload: @bulk_upload)) + when "confirm" + Forms::BulkUploadSalesSoftValidationsCheck::Confirm.new(form_params.merge(bulk_upload: @bulk_upload)) + else + raise "invalid form" + end + end + + def form_params + params.fetch(:form, {}).permit(:confirm_soft_errors) + end +end diff --git a/app/mailers/bulk_upload_mailer.rb b/app/mailers/bulk_upload_mailer.rb index c6e59b15e..e2b98c9b9 100644 --- a/app/mailers/bulk_upload_mailer.rb +++ b/app/mailers/bulk_upload_mailer.rb @@ -5,16 +5,39 @@ class BulkUploadMailer < NotifyMailer FAILED_CSV_ERRORS_TEMPLATE_ID = "e27abcd4-5295-48c2-b127-e9ee4b781b75".freeze FAILED_FILE_SETUP_ERROR_TEMPLATE_ID = "24c9f4c7-96ad-470a-ba31-eb51b7cbafd9".freeze FAILED_SERVICE_ERROR_TEMPLATE_ID = "c3f6288c-7a74-4e77-99ee-6c4a0f6e125a".freeze - HOW_FIX_UPLOAD_TEMPLATE_ID = "21a07b26-f625-4846-9f4d-39e30937aa24".freeze + HOW_TO_FIX_UPLOAD_TEMPLATE_ID = "21a07b26-f625-4846-9f4d-39e30937aa24".freeze + CHECK_SOFT_VALIDATIONS_TEMPLATE_ID = "21a07b26-f625-4846-9f4d-39e30937aa24".freeze - def send_how_fix_upload_mail(bulk_upload:) + def send_how_to_fix_upload_mail(bulk_upload:) title = "We found #{pluralize(bulk_upload.bulk_upload_errors.count, 'error')} in your bulk upload" description = "There was a problem with your #{bulk_upload.year_combo} #{bulk_upload.log_type} data. Check the error report below to fix these errors." cta_link = bulk_upload.sales? ? start_bulk_upload_sales_resume_url(bulk_upload) : start_bulk_upload_lettings_resume_url(bulk_upload) send_email( bulk_upload.user.email, - HOW_FIX_UPLOAD_TEMPLATE_ID, + HOW_TO_FIX_UPLOAD_TEMPLATE_ID, + { + title:, + filename: bulk_upload.filename, + upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time), + description:, + cta_link:, + }, + ) + end + + def send_check_soft_validations_mail(bulk_upload:) + title = "Check your file data" + description = "Some of your #{bulk_upload.year_combo} #{bulk_upload.log_type} data might not be right. Click the link below to review the potential errors, and check your file to see if the data is correct." + cta_link = if bulk_upload.lettings? + bulk_upload_lettings_soft_validations_check_url(bulk_upload, page: "confirm-soft-errors") + else + bulk_upload_sales_soft_validations_check_url(bulk_upload, page: "confirm-soft-errors") + end + + send_email( + bulk_upload.user.email, + CHECK_SOFT_VALIDATIONS_TEMPLATE_ID, { title:, filename: bulk_upload.filename, diff --git a/app/models/bulk_upload.rb b/app/models/bulk_upload.rb index ed1e9ab21..65a25507b 100644 --- a/app/models/bulk_upload.rb +++ b/app/models/bulk_upload.rb @@ -72,6 +72,41 @@ class BulkUpload < ApplicationRecord end end + def unpend_and_confirm_soft_validations + logs.find_each do |log| + log.retirement_value_check = 0 + + if log.lettings? + log.pregnancy_value_check = 0 + log.major_repairs_date_value_check = 0 + log.void_date_value_check = 0 + log.rent_value_check = 0 + log.net_income_value_check = 0 + log.carehome_charges_value_check = 0 + elsif log.sales? + log.mortgage_value_check = 0 + log.shared_ownership_deposit_value_check = 0 + log.value_value_check = 0 + log.savings_value_check = 0 + log.income1_value_check = 0 + log.deposit_value_check = 0 + log.wheel_value_check = 0 + log.extrabor_value_check = 0 + log.grant_value_check = 0 + log.staircase_bought_value_check = 0 + log.deposit_and_mortgage_value_check = 0 + log.old_persons_shared_ownership_value_check = 0 + log.income2_value_check = 0 + log.monthly_charges_value_check = 0 + log.student_not_child_value_check = 0 + log.discounted_sale_value_check = 0 + log.buyer_livein_value_check = 0 + log.percentage_discount_value_check = 0 + end + log.save! + end + end + private def generate_identifier diff --git a/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm.rb b/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm.rb new file mode 100644 index 000000000..b804d7767 --- /dev/null +++ b/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm.rb @@ -0,0 +1,30 @@ +module Forms + module BulkUploadLettingsSoftValidationsCheck + class Confirm + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :bulk_upload + + def view_path + "bulk_upload_lettings_soft_validations_check/confirm" + end + + def back_path + page_bulk_upload_lettings_soft_validations_check_path(bulk_upload, page: "confirm-soft-errors") + end + + def next_path + lettings_logs_path + end + + def save! + processor = BulkUpload::Processor.new(bulk_upload:) + processor.approve_and_confirm_soft_validations + + true + end + end + end +end diff --git a/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.rb b/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.rb new file mode 100644 index 000000000..cbf486a4d --- /dev/null +++ b/app/models/forms/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.rb @@ -0,0 +1,40 @@ +module Forms + module BulkUploadLettingsSoftValidationsCheck + class ConfirmSoftErrors + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :bulk_upload + attribute :confirm_soft_errors, :string + + validates :confirm_soft_errors, presence: true + + def options + [ + OpenStruct.new(id: "yes", name: "Yes, these fields are correct"), + OpenStruct.new(id: "no", name: "No, there are errors"), + ] + end + + def view_path + "bulk_upload_lettings_soft_validations_check/confirm_soft_errors" + end + + def next_path + case confirm_soft_errors + when "no" + page_bulk_upload_lettings_resume_path(bulk_upload, page: "fix-choice", soft_errors_only: true) + when "yes" + page_bulk_upload_lettings_soft_validations_check_path(bulk_upload, page: "confirm") + else + raise "invalid choice" + end + end + + def save! + true + end + end + end +end diff --git a/app/models/forms/bulk_upload_sales_soft_validations_check/confirm.rb b/app/models/forms/bulk_upload_sales_soft_validations_check/confirm.rb new file mode 100644 index 000000000..579af7e84 --- /dev/null +++ b/app/models/forms/bulk_upload_sales_soft_validations_check/confirm.rb @@ -0,0 +1,30 @@ +module Forms + module BulkUploadSalesSoftValidationsCheck + class Confirm + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :bulk_upload + + def view_path + "bulk_upload_sales_soft_validations_check/confirm" + end + + def back_path + page_bulk_upload_sales_soft_validations_check_path(bulk_upload, page: "confirm-soft-errors") + end + + def next_path + sales_logs_path + end + + def save! + processor = BulkUpload::Processor.new(bulk_upload:) + processor.approve_and_confirm_soft_validations + + true + end + end + end +end diff --git a/app/models/forms/bulk_upload_sales_soft_validations_check/confirm_soft_errors.rb b/app/models/forms/bulk_upload_sales_soft_validations_check/confirm_soft_errors.rb new file mode 100644 index 000000000..e6fe00495 --- /dev/null +++ b/app/models/forms/bulk_upload_sales_soft_validations_check/confirm_soft_errors.rb @@ -0,0 +1,40 @@ +module Forms + module BulkUploadSalesSoftValidationsCheck + class ConfirmSoftErrors + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :bulk_upload + attribute :confirm_soft_errors, :string + + validates :confirm_soft_errors, presence: true + + def options + [ + OpenStruct.new(id: "yes", name: "Yes, these fields are correct"), + OpenStruct.new(id: "no", name: "No, there are errors"), + ] + end + + def view_path + "bulk_upload_sales_soft_validations_check/confirm_soft_errors" + end + + def next_path + case confirm_soft_errors + when "no" + page_bulk_upload_sales_resume_path(bulk_upload, page: "fix-choice", soft_errors_only: true) + when "yes" + page_bulk_upload_sales_soft_validations_check_path(bulk_upload, page: "confirm") + else + raise "invalid choice" + end + end + + def save! + true + end + end + end +end diff --git a/app/services/bulk_upload/lettings/validator.rb b/app/services/bulk_upload/lettings/validator.rb index c24e67235..68cb5be08 100644 --- a/app/services/bulk_upload/lettings/validator.rb +++ b/app/services/bulk_upload/lettings/validator.rb @@ -63,6 +63,24 @@ class BulkUpload::Lettings::Validator .positive? end + def soft_validation_errors_only? + errors = bulk_upload.bulk_upload_errors + errors.count == errors.where(category: "soft_validation").count && errors.count.positive? + end + + def over_column_error_threshold? + fields = ("field_1".."field_134").to_a + percentage_threshold = (row_parsers.size * COLUMN_PERCENTAGE_ERROR_THRESHOLD).ceil + + fields.any? do |field| + count = row_parsers.count { |row_parser| row_parser.errors[field].present? } + + next if count < COLUMN_ABSOLUTE_ERROR_THRESHOLD + + count > percentage_threshold + end + end + def any_logs_already_exist? row_parsers.any?(&:log_already_exists?) end diff --git a/app/services/bulk_upload/processor.rb b/app/services/bulk_upload/processor.rb index 66c6b9d10..16d0a067d 100644 --- a/app/services/bulk_upload/processor.rb +++ b/app/services/bulk_upload/processor.rb @@ -18,8 +18,10 @@ class BulkUpload::Processor elsif validator.create_logs? create_logs - if created_logs_but_incompleted? - send_how_fix_upload_mail + if validator.soft_validation_errors_only? + send_check_soft_validations_mail + elsif created_logs_but_incompleted? + send_how_to_fix_upload_mail elsif created_logs_and_all_completed? bulk_upload.unpend send_success_mail @@ -38,11 +40,21 @@ class BulkUpload::Processor bulk_upload.unpend end + def approve_and_confirm_soft_validations + bulk_upload.unpend_and_confirm_soft_validations + end + private - def send_how_fix_upload_mail + def send_how_to_fix_upload_mail + BulkUploadMailer + .send_how_to_fix_upload_mail(bulk_upload:) + .deliver_later + end + + def send_check_soft_validations_mail BulkUploadMailer - .send_how_fix_upload_mail(bulk_upload:) + .send_check_soft_validations_mail(bulk_upload:) .deliver_later end diff --git a/app/services/bulk_upload/sales/validator.rb b/app/services/bulk_upload/sales/validator.rb index a72e3bbcf..2aa3bfd61 100644 --- a/app/services/bulk_upload/sales/validator.rb +++ b/app/services/bulk_upload/sales/validator.rb @@ -59,6 +59,11 @@ class BulkUpload::Sales::Validator row_parsers.any?(&:log_already_exists?) end + def soft_validation_errors_only? + errors = bulk_upload.bulk_upload_errors + errors.count == errors.where(category: "soft_validation").count && errors.count.positive? + end + private def any_logs_invalid? diff --git a/app/services/bulk_upload/sales/year2022/row_parser.rb b/app/services/bulk_upload/sales/year2022/row_parser.rb index c55500eb9..d1f31ecd7 100644 --- a/app/services/bulk_upload/sales/year2022/row_parser.rb +++ b/app/services/bulk_upload/sales/year2022/row_parser.rb @@ -481,6 +481,7 @@ private socprevten: %i[field_122], mortgageused: %i[field_123 field_124 field_125], soctenant: %i[field_39 field_113], + uprn: %i[], } end diff --git a/app/views/bulk_upload_lettings_resume/fix_choice.html.erb b/app/views/bulk_upload_lettings_resume/fix_choice.html.erb index cc8e33eaa..d887ec98e 100644 --- a/app/views/bulk_upload_lettings_resume/fix_choice.html.erb +++ b/app/views/bulk_upload_lettings_resume/fix_choice.html.erb @@ -30,7 +30,12 @@ :name, legend: { hidden: true } %> - <%= f.govuk_submit %> +
+ <%= f.govuk_submit %> + <% if @soft_errors_only %> + <%= govuk_button_link_to "Cancel", bulk_upload_lettings_soft_validations_check_url(@bulk_upload, page: "confirm-soft-errors"), secondary: true %> + <% end %> +
<% end %> diff --git a/app/views/bulk_upload_lettings_soft_validations_check/confirm.html.erb b/app/views/bulk_upload_lettings_soft_validations_check/confirm.html.erb new file mode 100644 index 000000000..8f29801da --- /dev/null +++ b/app/views/bulk_upload_lettings_soft_validations_check/confirm.html.erb @@ -0,0 +1,22 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +
+
+ Bulk upload for lettings (<%= @bulk_upload.year_combo %>) +

Are you sure you want to upload all logs from this bulk upload?

+ +

There are <%= pluralize(@bulk_upload.logs.count, "log") %> in this bulk upload, and <%= pluralize(@bulk_upload.bulk_upload_errors.count, "unexpected answer") %> will be marked as correct.

+ + <%= govuk_warning_text(icon_fallback_text: "Danger") do %> + You can not delete logs once you create them + <% end %> + + <%= form_with model: @form, scope: :form, url: page_bulk_upload_lettings_soft_validations_check_path(@bulk_upload, page: "confirm"), method: :patch do |f| %> + <%= f.govuk_submit %> + + <%= govuk_button_link_to "Cancel", @form.back_path, secondary: true %> + <% end %> +
+
diff --git a/app/views/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.html.erb b/app/views/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.html.erb new file mode 100644 index 000000000..fb5bde1c2 --- /dev/null +++ b/app/views/bulk_upload_lettings_soft_validations_check/confirm_soft_errors.html.erb @@ -0,0 +1,32 @@ +<%= form_with model: @form, scope: :form, url: page_bulk_upload_lettings_soft_validations_check_path(@bulk_upload, page: "confirm-soft-errors"), method: :patch do |f| %> +
+
+ <%= f.govuk_error_summary %> + + Bulk upload for lettings (<%= @bulk_upload.year_combo %>) +

Check these <%= pluralize(@bulk_upload.bulk_upload_errors.count, "answer") %>

+ +

Some data from your bulk upload might not be right. Check your file for any errors in the fields below.

+ +

+ <%= @bulk_upload.filename %> +

+
+ +
+ <% @bulk_upload.bulk_upload_errors.order_by_cell.group_by(&:row).each do |_row, errors_for_row| %> + <%= render BulkUploadErrorRowComponent.new(bulk_upload_errors: errors_for_row) %> + <% end %> +
+ +
+ <%= f.govuk_collection_radio_buttons :confirm_soft_errors, + @form.options, + :id, + :name, + legend: { text: "Are these fields correct?", size: "l" } %> + + <%= f.govuk_submit %> +
+
+<% end %> diff --git a/app/views/bulk_upload_sales_resume/fix_choice.html.erb b/app/views/bulk_upload_sales_resume/fix_choice.html.erb index d646d531c..ad4dce814 100644 --- a/app/views/bulk_upload_sales_resume/fix_choice.html.erb +++ b/app/views/bulk_upload_sales_resume/fix_choice.html.erb @@ -30,7 +30,12 @@ :name, legend: { hidden: true } %> - <%= f.govuk_submit %> +
+ <%= f.govuk_submit %> + <% if @soft_errors_only %> + <%= govuk_button_link_to "Cancel", bulk_upload_sales_soft_validations_check_url(@bulk_upload, page: "confirm-soft-errors"), secondary: true %> + <% end %> +
<% end %> diff --git a/app/views/bulk_upload_sales_soft_validations_check/confirm.html.erb b/app/views/bulk_upload_sales_soft_validations_check/confirm.html.erb new file mode 100644 index 000000000..2eb9df34e --- /dev/null +++ b/app/views/bulk_upload_sales_soft_validations_check/confirm.html.erb @@ -0,0 +1,22 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +
+
+ Bulk upload for sales (<%= @bulk_upload.year_combo %>) +

Are you sure you want to upload all logs from this bulk upload?

+ +

There are <%= pluralize(@bulk_upload.logs.count, "log") %> in this bulk upload, and <%= pluralize(@bulk_upload.bulk_upload_errors.count, "unexpected answer") %> will be marked as correct.

+ + <%= govuk_warning_text(icon_fallback_text: "Danger") do %> + You can not delete logs once you create them + <% end %> + + <%= form_with model: @form, scope: :form, url: page_bulk_upload_sales_soft_validations_check_path(@bulk_upload, page: "confirm"), method: :patch do |f| %> + <%= f.govuk_submit %> + + <%= govuk_button_link_to "Cancel", @form.back_path, secondary: true %> + <% end %> +
+
diff --git a/app/views/bulk_upload_sales_soft_validations_check/confirm_soft_errors.html.erb b/app/views/bulk_upload_sales_soft_validations_check/confirm_soft_errors.html.erb new file mode 100644 index 000000000..9ed175afb --- /dev/null +++ b/app/views/bulk_upload_sales_soft_validations_check/confirm_soft_errors.html.erb @@ -0,0 +1,32 @@ +<%= form_with model: @form, scope: :form, url: page_bulk_upload_sales_soft_validations_check_path(@bulk_upload, page: "confirm-soft-errors"), method: :patch do |f| %> +
+
+ <%= f.govuk_error_summary %> + + Bulk upload for sales (<%= @bulk_upload.year_combo %>) +

Check these <%= pluralize(@bulk_upload.bulk_upload_errors.count, "answer") %>

+ +

Some data from your bulk upload might not be right. Check your file for any errors in the fields below.

+ +

+ <%= @bulk_upload.filename %> +

+
+ +
+ <% @bulk_upload.bulk_upload_errors.order_by_cell.group_by(&:row).each do |_row, errors_for_row| %> + <%= render BulkUploadErrorRowComponent.new(bulk_upload_errors: errors_for_row) %> + <% end %> +
+ +
+ <%= f.govuk_collection_radio_buttons :confirm_soft_errors, + @form.options, + :id, + :name, + legend: { text: "Are these fields correct?", size: "l" } %> + + <%= f.govuk_submit %> +
+
+<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index ccf055e17..ae318678f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -71,8 +71,21 @@ en: forms/bulk_upload_lettings_resume/fix_choice: attributes: choice: - blank: You must select how would you like to fix errors - inclusion: You must select one of the following options for how would like to fix errors + blank: Select how you would like to fix these errors + inclusion: You must select one of the following options for how you would like to fix these errors + forms/bulk_upload_lettings_soft_validations_check/confirm_soft_errors: + attributes: + confirm_soft_errors: + blank: You must select if there are errors in these fields + forms/bulk_upload_sales_soft_validations_check/confirm_soft_errors: + attributes: + confirm_soft_errors: + blank: You must select if there are errors in these fields + forms/bulk_upload_sales_resume/fix_choice: + attributes: + choice: + blank: Select how you would like to fix these errors + inclusion: You must select one of the following options for how you would like to fix these errors activerecord: errors: diff --git a/config/routes.rb b/config/routes.rb index 07090f073..05b0f32fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -180,6 +180,13 @@ Rails.application.routes.draw do end end + resources :bulk_upload_lettings_soft_validations_check, path: "bulk-upload-soft-validations-check", only: %i[show update] do + member do + get "*page", to: "bulk_upload_lettings_soft_validations_check#show", as: "page" + patch "*page", to: "bulk_upload_lettings_soft_validations_check#update" + end + end + get "update-logs", to: "lettings_logs#update_logs" end @@ -227,6 +234,13 @@ Rails.application.routes.draw do patch "*page", to: "bulk_upload_sales_resume#update" end end + + resources :bulk_upload_sales_soft_validations_check, path: "bulk-upload-soft-validations-check", only: %i[show update] do + member do + get "*page", to: "bulk_upload_sales_soft_validations_check#show", as: "page" + patch "*page", to: "bulk_upload_sales_soft_validations_check#update" + end + end end member do diff --git a/spec/mailers/bulk_upload_mailer_spec.rb b/spec/mailers/bulk_upload_mailer_spec.rb index e2e32ab96..ba49d50b5 100644 --- a/spec/mailers/bulk_upload_mailer_spec.rb +++ b/spec/mailers/bulk_upload_mailer_spec.rb @@ -97,4 +97,27 @@ RSpec.describe BulkUploadMailer do end end end + + describe "#send_check_soft_validations_mail" do + before do + create(:bulk_upload_error, bulk_upload:, col: "A", field: "field_1", category: "soft_validation") + create(:bulk_upload_error, bulk_upload:, col: "E", field: "field_4", category: "soft_validation") + end + + it "sends correctly formed email" do + expect(notify_client).to receive(:send_email).with( + email_address: bulk_upload.user.email, + template_id: described_class::CHECK_SOFT_VALIDATIONS_TEMPLATE_ID, + personalisation: { + title: "Check your file data", + filename: bulk_upload.filename, + upload_timestamp: bulk_upload.created_at.to_fs(:govuk_date_and_time), + description: "Some of your 2022/23 lettings data might not be right. Click the link below to review the potential errors, and check your file to see if the data is correct.", + cta_link: bulk_upload_lettings_soft_validations_check_url(bulk_upload, page: "confirm-soft-errors"), + }, + ) + + mailer.send_check_soft_validations_mail(bulk_upload:) + end + end end diff --git a/spec/requests/bulk_upload_lettings_resume_controller_spec.rb b/spec/requests/bulk_upload_lettings_resume_controller_spec.rb index 5529a13db..3666bc777 100644 --- a/spec/requests/bulk_upload_lettings_resume_controller_spec.rb +++ b/spec/requests/bulk_upload_lettings_resume_controller_spec.rb @@ -27,6 +27,18 @@ RSpec.describe BulkUploadLettingsResumeController, type: :request do expect(response.body).to include("2022/23") expect(response.body).to include("How would you like to fix 2 errors?") expect(response.body).to include(bulk_upload.filename) + expect(response.body).not_to include("Cancel") + end + end + + describe "GET /lettings-logs/bulk-upload-resume/:ID/fix-choice?soft_errors_only=true" do + it "displays a cancel button" do + get "/lettings-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice?soft_errors_only=true" + + expect(response).to be_successful + + expect(response.body).to include("Bulk upload for lettings") + expect(response.body).to include("Cancel") end end @@ -37,7 +49,7 @@ RSpec.describe BulkUploadLettingsResumeController, type: :request do expect(response).to be_successful - expect(response.body).to include("You must select") + expect(response.body).to include("Select how you would like to fix these errors") end end diff --git a/spec/requests/bulk_upload_lettings_soft_validations_check_controller_spec.rb b/spec/requests/bulk_upload_lettings_soft_validations_check_controller_spec.rb new file mode 100644 index 000000000..d1252b5e2 --- /dev/null +++ b/spec/requests/bulk_upload_lettings_soft_validations_check_controller_spec.rb @@ -0,0 +1,90 @@ +require "rails_helper" + +RSpec.describe BulkUploadLettingsSoftValidationsCheckController, type: :request do + let(:user) { create(:user) } + let(:bulk_upload) { create(:bulk_upload, :lettings, user:, bulk_upload_errors:) } + let(:bulk_upload_errors) { create_list(:bulk_upload_error, 2) } + + before do + create_list(:lettings_log, 2, bulk_upload:) + sign_in user + end + + describe "GET /lettings-logs/bulk-upload-soft-validations-check/:ID/confirm-soft-errors" do + it "shows the soft validation errors with confirmation question" do + get "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response.body).to include("Bulk upload for lettings") + expect(response.body).to include("2022/23") + expect(response.body).to include("Check these 2 answers") + expect(response.body).to include(bulk_upload.filename) + expect(response.body).to include("Are these fields correct?") + end + + it "shows the soft validation and lists the errors" do + get "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response.body).to include("Row #{bulk_upload_errors.first.row}") + expect(response.body).to include("Tenant code") + expect(response.body).to include("some error") + end + end + + describe "PATCH /lettings-logs/bulk-upload-soft-validations-check/:ID/confirm-soft-errors" do + context "when no option selected" do + it "renders error message" do + patch "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response).to be_successful + + expect(response.body).to include("You must select if there are errors in these fields") + end + end + + context "when no is selected" do + it "sends them to the fix choice page" do + patch "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors", params: { form: { confirm_soft_errors: "no" } } + + expect(response).to redirect_to("/lettings-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice?soft_errors_only=true") + end + end + + context "when yes is selected" do + it "sends them to confirm choice" do + patch "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors", params: { form: { confirm_soft_errors: "yes" } } + + expect(response).to redirect_to("/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm") + follow_redirect! + expect(response.body).not_to include("You’ve successfully uploaded") + end + end + end + + describe "GET /lettings-logs/bulk-upload-soft-validations-check/:ID/confirm" do + it "renders page" do + get "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm" + + expect(response).to be_successful + + expect(response.body).to include("Are you sure you want to upload all logs from this bulk upload?") + expect(response.body).to include("There are 2 logs in this bulk upload, and 2 unexpected answers will be marked as correct.") + expect(response.body).not_to include("You’ve successfully uploaded") + end + end + + describe "PATCH /lettings-logs/bulk-upload-soft-validations-check/:ID/confirm" do + let(:mock_processor) { instance_double(BulkUpload::Processor, approve_and_confirm_soft_validations: nil) } + + it "approves logs for creation" do + allow(BulkUpload::Processor).to receive(:new).with(bulk_upload:).and_return(mock_processor) + + patch "/lettings-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm" + + expect(mock_processor).to have_received(:approve_and_confirm_soft_validations) + + expect(response).to redirect_to("/lettings-logs") + follow_redirect! + expect(response.body).to include("You’ve successfully uploaded 2 logs") + end + end +end diff --git a/spec/requests/bulk_upload_sales_resume_controller_spec.rb b/spec/requests/bulk_upload_sales_resume_controller_spec.rb new file mode 100644 index 000000000..8dcc0ba00 --- /dev/null +++ b/spec/requests/bulk_upload_sales_resume_controller_spec.rb @@ -0,0 +1,96 @@ +require "rails_helper" + +RSpec.describe BulkUploadSalesResumeController, type: :request do + let(:user) { create(:user) } + let(:bulk_upload) { create(:bulk_upload, :sales, user:, bulk_upload_errors:) } + let(:bulk_upload_errors) { create_list(:bulk_upload_error, 2) } + + before do + sign_in user + end + + describe "GET /sales-logs/bulk-upload-resume/:ID/start" do + it "redirects to choice page" do + get "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/start" + + expect(response).to redirect_to("/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice") + end + end + + describe "GET /sales-logs/bulk-upload-resume/:ID/fix-choice" do + it "renders the page correctly" do + get "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice" + + expect(response).to be_successful + + expect(response.body).to include("Bulk upload for sales") + expect(response.body).to include("2022/23") + expect(response.body).to include("How would you like to fix 2 errors?") + expect(response.body).to include(bulk_upload.filename) + expect(response.body).not_to include("Cancel") + end + end + + describe "GET /sales-logs/bulk-upload-resume/:ID/fix-choice?soft_errors_only=true" do + it "displays a cancel button" do + get "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice?soft_errors_only=true" + + expect(response).to be_successful + + expect(response.body).to include("Bulk upload for sales") + expect(response.body).to include("Cancel") + end + end + + describe "PATCH /sales-logs/bulk-upload-resume/:ID/fix-choice" do + context "when no option selected" do + it "renders error message" do + patch "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice" + + expect(response).to be_successful + + expect(response.body).to include("Select how you would like to fix these errors") + end + end + + context "when upload again selected" do + it "sends them to relevant report" do + patch "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice", params: { form: { choice: "upload-again" } } + + expect(response).to redirect_to("/sales-logs/bulk-upload-results/#{bulk_upload.id}") + end + end + + context "when fix inline selected" do + it "sends them to confirm choice" do + patch "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice", params: { form: { choice: "create-fix-inline" } } + + expect(response).to redirect_to("/sales-logs/bulk-upload-resume/#{bulk_upload.id}/confirm") + end + end + end + + describe "GET /sales-logs/bulk-upload-resume/:ID/confirm" do + it "renders page" do + get "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/confirm" + + expect(response).to be_successful + + expect(response.body).to include("Are you sure") + end + end + + describe "PATCH /sales-logs/bulk-upload-resume/:ID/confirm" do + let(:mock_processor) { instance_double(BulkUpload::Processor, approve: nil) } + + it "approves logs for creation" do + allow(BulkUpload::Processor).to receive(:new).with(bulk_upload:).and_return(mock_processor) + + patch "/sales-logs/bulk-upload-resume/#{bulk_upload.id}/confirm" + + expect(mock_processor).to have_received(:approve) + + expect(response).to redirect_to("/sales-logs/bulk-upload-results/#{bulk_upload.id}/resume") + end + end +end diff --git a/spec/requests/bulk_upload_sales_soft_validations_check_controller_spec.rb b/spec/requests/bulk_upload_sales_soft_validations_check_controller_spec.rb new file mode 100644 index 000000000..3aaa433f0 --- /dev/null +++ b/spec/requests/bulk_upload_sales_soft_validations_check_controller_spec.rb @@ -0,0 +1,90 @@ +require "rails_helper" + +RSpec.describe BulkUploadSalesSoftValidationsCheckController, type: :request do + let(:user) { create(:user) } + let(:bulk_upload) { create(:bulk_upload, :sales, user:, bulk_upload_errors:) } + let(:bulk_upload_errors) { create_list(:bulk_upload_error, 2) } + + before do + create_list(:sales_log, 2, bulk_upload:) + sign_in user + end + + describe "GET /sales-logs/bulk-upload-soft-validations-check/:ID/confirm-soft-errors" do + it "shows the soft validation errors with confirmation question" do + get "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response.body).to include("Bulk upload for sales") + expect(response.body).to include("2022/23") + expect(response.body).to include("Check these 2 answers") + expect(response.body).to include(bulk_upload.filename) + expect(response.body).to include("Are these fields correct?") + end + + it "shows the soft validation and lists the errors" do + get "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response.body).to include("Row #{bulk_upload_errors.first.row}") + expect(response.body).to include("Purchaser code") + expect(response.body).to include("some error") + end + end + + describe "PATCH /sales-logs/bulk-upload-soft-validations-check/:ID/confirm-soft-errors" do + context "when no option selected" do + it "renders error message" do + patch "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors" + + expect(response).to be_successful + + expect(response.body).to include("You must select if there are errors in these fields") + end + end + + context "when no is selected" do + it "sends them to the fix choice page" do + patch "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors", params: { form: { confirm_soft_errors: "no" } } + + expect(response).to redirect_to("/sales-logs/bulk-upload-resume/#{bulk_upload.id}/fix-choice?soft_errors_only=true") + end + end + + context "when yes is selected" do + it "sends them to confirm choice" do + patch "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm-soft-errors", params: { form: { confirm_soft_errors: "yes" } } + + expect(response).to redirect_to("/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm") + follow_redirect! + expect(response.body).not_to include("You’ve successfully uploaded") + end + end + end + + describe "GET /sales-logs/bulk-upload-soft-validations-check/:ID/confirm" do + it "renders page" do + get "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm" + + expect(response).to be_successful + + expect(response.body).to include("Are you sure you want to upload all logs from this bulk upload?") + expect(response.body).to include("There are 2 logs in this bulk upload, and 2 unexpected answers will be marked as correct.") + expect(response.body).not_to include("You’ve successfully uploaded") + end + end + + describe "PATCH /sales-logs/bulk-upload-soft-validations-check/:ID/confirm" do + let(:mock_processor) { instance_double(BulkUpload::Processor, approve_and_confirm_soft_validations: nil) } + + it "approves logs for creation" do + allow(BulkUpload::Processor).to receive(:new).with(bulk_upload:).and_return(mock_processor) + + patch "/sales-logs/bulk-upload-soft-validations-check/#{bulk_upload.id}/confirm" + + expect(mock_processor).to have_received(:approve_and_confirm_soft_validations) + + expect(response).to redirect_to("/sales-logs") + follow_redirect! + expect(response.body).to include("You’ve successfully uploaded 2 logs") + end + end +end diff --git a/spec/services/bulk_upload/lettings/log_creator_spec.rb b/spec/services/bulk_upload/lettings/log_creator_spec.rb index 9c28cc81e..87ac6e320 100644 --- a/spec/services/bulk_upload/lettings/log_creator_spec.rb +++ b/spec/services/bulk_upload/lettings/log_creator_spec.rb @@ -129,6 +129,52 @@ RSpec.describe BulkUpload::Lettings::LogCreator do end end + context "with a valid csv and soft validations" do + let(:file) { Tempfile.new } + let(:path) { file.path } + let(:log) do + build( + :lettings_log, + :completed, + renttype: 3, + age1: 22, + age1_known: 0, + ecstat1: 5, + owning_organisation: owning_org, + managing_organisation: owning_org, + created_by: user, + national: 18, + waityear: 9, + joint: 2, + tenancy: 9, + ppcodenk: 0, + ) + end + + before do + file.write(BulkUpload::LettingsLogToCsv.new(log:, col_offset: 0).to_2022_csv_row) + file.rewind + end + + it "creates a new log" do + expect { service.call }.to change(LettingsLog, :count) + end + + it "creates a log with pending status" do + service.call + expect(LettingsLog.last.status).to eql("pending") + end + + it "does not set unanswered soft validations" do + service.call + + log = LettingsLog.last + expect(log.age1).to be(22) + expect(log.ecstat1).to be(5) + expect(log.retirement_value_check).to be(nil) + end + end + context "when valid csv with existing log" do xit "what should happen?" end diff --git a/spec/services/bulk_upload/processor_spec.rb b/spec/services/bulk_upload/processor_spec.rb index 0c9d50be8..6c250bbb6 100644 --- a/spec/services/bulk_upload/processor_spec.rb +++ b/spec/services/bulk_upload/processor_spec.rb @@ -224,16 +224,104 @@ RSpec.describe BulkUpload::Processor do expect { processor.call }.to change(LettingsLog.pending, :count).by(1) end - it "sends how_fix_upload_mail" do + it "sends how_to_fix_upload_mail" do mail_double = instance_double("ActionMailer::MessageDelivery", deliver_later: nil) - allow(BulkUploadMailer).to receive(:send_how_fix_upload_mail).and_return(mail_double) + allow(BulkUploadMailer).to receive(:send_how_to_fix_upload_mail).and_return(mail_double) processor.call - expect(BulkUploadMailer).to have_received(:send_how_fix_upload_mail) + expect(BulkUploadMailer).to have_received(:send_how_to_fix_upload_mail) expect(mail_double).to have_received(:deliver_later) end + + it "calls log creator" do + log_creator_double = instance_double(BulkUpload::Lettings::LogCreator, call: nil) + + allow(BulkUpload::Lettings::LogCreator).to receive(:new).and_return(log_creator_double) + + processor.call + + expect(BulkUpload::Lettings::LogCreator).to have_received(:new).with(bulk_upload:, path:) + end + end + + context "when a bulk upload has logs with only soft validations triggered" do + let(:mock_downloader) do + instance_double( + BulkUpload::Downloader, + call: nil, + path:, + delete_local_file!: nil, + ) + end + + let(:file) { Tempfile.new } + let(:path) { file.path } + + let(:log) do + build( + :lettings_log, + :completed, + renttype: 3, + age1: 20, + ecstat1: 5, + owning_organisation: owning_org, + managing_organisation: owning_org, + created_by: nil, + national: 18, + waityear: 9, + joint: 2, + tenancy: 2, + ppcodenk: 0, + voiddate: Date.new(2022, 1, 1), + reason: 40, + leftreg: 3, + mrcdate: nil, + startdate: Date.new(2022, 10, 1), + tenancylength: nil, + ) + end + + before do + FormHandler.instance.use_real_forms! + file.write(BulkUpload::LettingsLogToCsv.new(log:, col_offset: 0).to_2022_csv_row) + file.rewind + + allow(BulkUpload::Downloader).to receive(:new).with(bulk_upload:).and_return(mock_downloader) + allow(FeatureToggle).to receive(:bulk_upload_duplicate_log_check_enabled?).and_return(true) + end + + after do + FormHandler.instance.use_fake_forms! + end + + it "creates pending log" do + expect { processor.call }.to change(LettingsLog.pending, :count).by(1) + end + + it "sends check_soft_validations_mail" do + mail_double = instance_double("ActionMailer::MessageDelivery", deliver_later: nil) + + allow(BulkUploadMailer).to receive(:send_check_soft_validations_mail).and_return(mail_double) + allow(BulkUploadMailer).to receive(:send_how_to_fix_upload_mail).and_return(mail_double) + + processor.call + + expect(BulkUploadMailer).to have_received(:send_check_soft_validations_mail) + expect(BulkUploadMailer).not_to have_received(:send_how_to_fix_upload_mail) + expect(mail_double).to have_received(:deliver_later) + end + + it "calls log creator" do + log_creator_double = instance_double(BulkUpload::Lettings::LogCreator, call: nil) + + allow(BulkUpload::Lettings::LogCreator).to receive(:new).and_return(log_creator_double) + + processor.call + + expect(BulkUpload::Lettings::LogCreator).to have_received(:new).with(bulk_upload:, path:) + end end context "when upload has no setup errors something blocks log creation" do diff --git a/spec/services/bulk_upload/sales/log_creator_spec.rb b/spec/services/bulk_upload/sales/log_creator_spec.rb index 2abda527d..14a363a4c 100644 --- a/spec/services/bulk_upload/sales/log_creator_spec.rb +++ b/spec/services/bulk_upload/sales/log_creator_spec.rb @@ -130,5 +130,44 @@ RSpec.describe BulkUpload::Sales::LogCreator do context "when valid csv with existing log" do xit "what should happen?" end + + context "with a valid csv and soft validations" do + let(:file) { Tempfile.new } + let(:path) { file.path } + let(:log) do + build( + :sales_log, + :completed, + age1: 30, + age1_known: 0, + ecstat1: 5, + owning_organisation: owning_org, + created_by: user, + ) + end + + before do + file.write(BulkUpload::SalesLogToCsv.new(log:, col_offset: 0).to_2022_csv_row) + file.rewind + end + + it "creates a new log" do + expect { service.call }.to change(SalesLog, :count) + end + + it "creates a log with pending status" do + service.call + expect(SalesLog.last.status).to eql("pending") + end + + it "does not set unanswered soft validations" do + service.call + + log = SalesLog.last + expect(log.age1).to be(30) + expect(log.ecstat1).to be(5) + expect(log.retirement_value_check).to be(nil) + end + end end end diff --git a/spec/support/bulk_upload/lettings_log_to_csv.rb b/spec/support/bulk_upload/lettings_log_to_csv.rb index 6d3110b2a..256ea2fb4 100644 --- a/spec/support/bulk_upload/lettings_log_to_csv.rb +++ b/spec/support/bulk_upload/lettings_log_to_csv.rb @@ -123,15 +123,15 @@ class BulkUpload::LettingsLogToCsv log.benefits, log.earnings, # 50 net_income_known, - nil, + log.reason, log.reasonother, nil, - nil, - nil, - nil, - nil, - nil, - nil, # 60 + log.housingneeds_a, + log.housingneeds_b, + log.housingneeds_c, + log.housingneeds_f, + log.housingneeds_g, + log.housingneeds_h, # 60 log.prevten, log.prevloc, ((log.ppostcode_full || "").split(" ") || [""]).first,