From a305bb7d52920df01afeb8b493ea4bfc6c8de856 Mon Sep 17 00:00:00 2001 From: Phil Lee Date: Thu, 1 Dec 2022 09:55:08 +0000 Subject: [PATCH] [1714] Bulk upload part three (#1032) * add start of bulk upload logs journey * split upload controller into 2 * add year page to bulk upload journey * bulk upload years now dynamic * bulk upload journey: add copy for prepare file * add link to bulk upload template * add placeholder for upload your file page * handle bulk upload when not in crossover * fix tests around bulk upload redirect * fix typos in bulk upload jouney --- .../bulk_upload_lettings_logs_controller.rb | 50 +++++++++++++++++ .../bulk_upload_sales_logs_controller.rb | 50 +++++++++++++++++ app/helpers/logs_helper.rb | 21 ++++++++ app/helpers/navigation_items_helper.rb | 4 +- app/models/form.rb | 8 +++ .../bulk_upload_lettings/prepare_your_file.rb | 41 ++++++++++++++ .../bulk_upload_lettings/upload_your_file.rb | 19 +++++++ app/models/forms/bulk_upload_lettings/year.rb | 37 +++++++++++++ .../bulk_upload_sales/prepare_your_file.rb | 41 ++++++++++++++ .../bulk_upload_sales/upload_your_file.rb | 19 +++++++ app/models/forms/bulk_upload_sales/year.rb | 37 +++++++++++++ .../forms/prepare_your_file.html.erb | 33 ++++++++++++ .../forms/upload_your_file.html.erb | 17 ++++++ .../forms/year.html.erb | 16 ++++++ .../forms/prepare_your_file.html.erb | 33 ++++++++++++ .../forms/upload_your_file.html.erb | 17 ++++++ .../forms/year.html.erb | 16 ++++++ app/views/logs/index.html.erb | 12 +++-- config/initializers/feature_toggle.rb | 4 ++ config/locales/en.yml | 12 +++++ config/routes.rb | 14 +++++ .../bulk-upload-lettings-template-v1.xlsx | Bin 0 -> 35928 bytes .../files/bulk-upload-sales-template-v1.xlsx | Bin 0 -> 26703 bytes .../bulk_upload_lettings_logs_spec.rb | 51 ++++++++++++++++++ spec/features/bulk_upload_sales_logs_spec.rb | 51 ++++++++++++++++++ spec/models/form_spec.rb | 34 ++++++++++++ .../forms/bulk_upload_lettings/year_spec.rb | 12 +++++ .../forms/bulk_upload_sales/year_spec.rb | 12 +++++ spec/rails_helper.rb | 1 + ...lk_upload_lettings_logs_controller_spec.rb | 32 +++++++++++ .../bulk_upload_sales_logs_controller_spec.rb | 32 +++++++++++ 31 files changed, 720 insertions(+), 6 deletions(-) create mode 100644 app/controllers/bulk_upload_lettings_logs_controller.rb create mode 100644 app/controllers/bulk_upload_sales_logs_controller.rb create mode 100644 app/helpers/logs_helper.rb create mode 100644 app/models/forms/bulk_upload_lettings/prepare_your_file.rb create mode 100644 app/models/forms/bulk_upload_lettings/upload_your_file.rb create mode 100644 app/models/forms/bulk_upload_lettings/year.rb create mode 100644 app/models/forms/bulk_upload_sales/prepare_your_file.rb create mode 100644 app/models/forms/bulk_upload_sales/upload_your_file.rb create mode 100644 app/models/forms/bulk_upload_sales/year.rb create mode 100644 app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb create mode 100644 app/views/bulk_upload_lettings_logs/forms/upload_your_file.html.erb create mode 100644 app/views/bulk_upload_lettings_logs/forms/year.html.erb create mode 100644 app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb create mode 100644 app/views/bulk_upload_sales_logs/forms/upload_your_file.html.erb create mode 100644 app/views/bulk_upload_sales_logs/forms/year.html.erb create mode 100644 public/files/bulk-upload-lettings-template-v1.xlsx create mode 100644 public/files/bulk-upload-sales-template-v1.xlsx create mode 100644 spec/features/bulk_upload_lettings_logs_spec.rb create mode 100644 spec/features/bulk_upload_sales_logs_spec.rb create mode 100644 spec/models/forms/bulk_upload_lettings/year_spec.rb create mode 100644 spec/models/forms/bulk_upload_sales/year_spec.rb create mode 100644 spec/requests/bulk_upload_lettings_logs_controller_spec.rb create mode 100644 spec/requests/bulk_upload_sales_logs_controller_spec.rb diff --git a/app/controllers/bulk_upload_lettings_logs_controller.rb b/app/controllers/bulk_upload_lettings_logs_controller.rb new file mode 100644 index 000000000..108c25fef --- /dev/null +++ b/app/controllers/bulk_upload_lettings_logs_controller.rb @@ -0,0 +1,50 @@ +class BulkUploadLettingsLogsController < ApplicationController + before_action :authenticate_user! + + def start + if in_crossover_period? + redirect_to bulk_upload_lettings_log_path(id: "year") + else + redirect_to bulk_upload_lettings_log_path(id: "prepare-your-file", form: { year: current_year }) + end + end + + def show + render form.view_path + end + + def update + if form.valid? + redirect_to form.next_path + else + render form.view_path + end + end + +private + + def current_year + FormHandler.instance.forms["current_lettings"].start_date.year + end + + def in_crossover_period? + FormHandler.instance.forms.values.any?(&:in_crossover_period?) + end + + def form + @form ||= case params[:id] + when "year" + Forms::BulkUploadLettings::Year.new(form_params) + when "prepare-your-file" + Forms::BulkUploadLettings::PrepareYourFile.new(form_params) + when "upload-your-file" + Forms::BulkUploadLettings::UploadYourFile.new(form_params) + else + raise "Page not found for path #{params[:id]}" + end + end + + def form_params + params.fetch(:form, {}).permit(:year) + end +end diff --git a/app/controllers/bulk_upload_sales_logs_controller.rb b/app/controllers/bulk_upload_sales_logs_controller.rb new file mode 100644 index 000000000..81d018d4c --- /dev/null +++ b/app/controllers/bulk_upload_sales_logs_controller.rb @@ -0,0 +1,50 @@ +class BulkUploadSalesLogsController < ApplicationController + before_action :authenticate_user! + + def start + if in_crossover_period? + redirect_to bulk_upload_sales_log_path(id: "year") + else + redirect_to bulk_upload_sales_log_path(id: "prepare-your-file", form: { year: current_year }) + end + end + + def show + render form.view_path + end + + def update + if form.valid? + redirect_to form.next_path + else + render form.view_path + end + end + +private + + def current_year + FormHandler.instance.forms["current_sales"].start_date.year + end + + def in_crossover_period? + FormHandler.instance.forms.values.any?(&:in_crossover_period?) + end + + def form + @form ||= case params[:id] + when "year" + Forms::BulkUploadSales::Year.new(form_params) + when "prepare-your-file" + Forms::BulkUploadSales::PrepareYourFile.new(form_params) + when "upload-your-file" + Forms::BulkUploadSales::UploadYourFile.new(form_params) + else + raise "Page not found for path #{params[:id]}" + end + end + + def form_params + params.fetch(:form, {}).permit(:year) + end +end diff --git a/app/helpers/logs_helper.rb b/app/helpers/logs_helper.rb new file mode 100644 index 000000000..6567f0a13 --- /dev/null +++ b/app/helpers/logs_helper.rb @@ -0,0 +1,21 @@ +module LogsHelper + def log_type_for_controller(controller) + case controller.class.to_s + when "LettingsLogsController" + "lettings" + when "SalesLogsController" + "sales" + else + raise "Log type not found for #{controller.class}" + end + end + + def bulk_upload_path_for_controller(controller, id:) + case log_type_for_controller(controller) + when "lettings" + bulk_upload_lettings_log_path(id:) + when "sales" + bulk_upload_sales_log_path(id:) + end + end +end diff --git a/app/helpers/navigation_items_helper.rb b/app/helpers/navigation_items_helper.rb index 07c125a8d..d996894ea 100644 --- a/app/helpers/navigation_items_helper.rb +++ b/app/helpers/navigation_items_helper.rb @@ -65,11 +65,11 @@ module NavigationItemsHelper private def lettings_logs_current?(path) - path == "/lettings-logs" + path.starts_with?("/lettings-logs") end def sales_logs_current?(path) - path == "/sales-logs" + path.starts_with?("/sales-logs") end def users_current?(path) diff --git a/app/models/form.rb b/app/models/form.rb index 22321f431..9d9acf2ea 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -223,4 +223,12 @@ class Form end end end + + def in_crossover_period?(now: Time.zone.now) + ((end_date - 3.months) < now) && (now < end_date) + end + + def inspect + "#<#{self.class} @type=#{type} @name=#{name}>" + 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 new file mode 100644 index 000000000..684ba1437 --- /dev/null +++ b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb @@ -0,0 +1,41 @@ +module Forms + module BulkUploadLettings + class PrepareYourFile + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + def view_path + "bulk_upload_lettings_logs/forms/prepare_your_file" + end + + def back_path + if in_crossover_period? + Rails.application.routes.url_helpers.bulk_upload_lettings_log_path(id: "year", form: { year: }) + else + Rails.application.routes.url_helpers.lettings_logs_path + end + end + + def next_path + bulk_upload_lettings_log_path(id: "upload-your-file", form: { year: }) + end + + def template_path + "/files/bulk-upload-lettings-template-v1.xlsx" + end + + def year_combo + "#{year}/#{year + 1 - 2000}" + end + + private + + def in_crossover_period? + FormHandler.instance.forms.values.any?(&:in_crossover_period?) + end + end + end +end diff --git a/app/models/forms/bulk_upload_lettings/upload_your_file.rb b/app/models/forms/bulk_upload_lettings/upload_your_file.rb new file mode 100644 index 000000000..1415ffe19 --- /dev/null +++ b/app/models/forms/bulk_upload_lettings/upload_your_file.rb @@ -0,0 +1,19 @@ +module Forms + module BulkUploadLettings + class UploadYourFile + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + def view_path + "bulk_upload_lettings_logs/forms/upload_your_file" + end + + def back_path + bulk_upload_lettings_log_path(id: "prepare-your-file", form: { year: }) + end + end + end +end diff --git a/app/models/forms/bulk_upload_lettings/year.rb b/app/models/forms/bulk_upload_lettings/year.rb new file mode 100644 index 000000000..9fa17b19e --- /dev/null +++ b/app/models/forms/bulk_upload_lettings/year.rb @@ -0,0 +1,37 @@ +module Forms + module BulkUploadLettings + class Year + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + validates :year, presence: true + + def view_path + "bulk_upload_lettings_logs/forms/year" + end + + def options + possible_years.map do |year| + OpenStruct.new(id: year, name: "#{year}/#{year + 1}") + end + end + + def back_path + lettings_logs_path + end + + def next_path + bulk_upload_lettings_log_path(id: "prepare-your-file", form: { year: }) + end + + private + + def possible_years + FormHandler.instance.lettings_forms.values.map { |form| form.start_date.year }.sort.reverse + 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 new file mode 100644 index 000000000..da017dbbd --- /dev/null +++ b/app/models/forms/bulk_upload_sales/prepare_your_file.rb @@ -0,0 +1,41 @@ +module Forms + module BulkUploadSales + class PrepareYourFile + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + def view_path + "bulk_upload_sales_logs/forms/prepare_your_file" + end + + def back_path + if in_crossover_period? + Rails.application.routes.url_helpers.bulk_upload_sales_log_path(id: "year", form: { year: }) + else + Rails.application.routes.url_helpers.sales_logs_path + end + end + + def next_path + bulk_upload_sales_log_path(id: "upload-your-file", form: { year: }) + end + + def template_path + "/files/bulk-upload-sales-template-v1.xlsx" + end + + def year_combo + "#{year}/#{year + 1 - 2000}" + end + + private + + def in_crossover_period? + FormHandler.instance.forms.values.any?(&:in_crossover_period?) + end + end + end +end diff --git a/app/models/forms/bulk_upload_sales/upload_your_file.rb b/app/models/forms/bulk_upload_sales/upload_your_file.rb new file mode 100644 index 000000000..3d421e9f1 --- /dev/null +++ b/app/models/forms/bulk_upload_sales/upload_your_file.rb @@ -0,0 +1,19 @@ +module Forms + module BulkUploadSales + class UploadYourFile + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + def view_path + "bulk_upload_sales_logs/forms/upload_your_file" + end + + def back_path + bulk_upload_sales_log_path(id: "prepare-your-file", form: { year: }) + end + end + end +end diff --git a/app/models/forms/bulk_upload_sales/year.rb b/app/models/forms/bulk_upload_sales/year.rb new file mode 100644 index 000000000..361061990 --- /dev/null +++ b/app/models/forms/bulk_upload_sales/year.rb @@ -0,0 +1,37 @@ +module Forms + module BulkUploadSales + class Year + include ActiveModel::Model + include ActiveModel::Attributes + include Rails.application.routes.url_helpers + + attribute :year, :integer + + validates :year, presence: true + + def view_path + "bulk_upload_sales_logs/forms/year" + end + + def options + possible_years.map do |year| + OpenStruct.new(id: year, name: "#{year}/#{year + 1}") + end + end + + def back_path + sales_logs_path + end + + def next_path + bulk_upload_sales_log_path(id: "prepare-your-file", form: { year: }) + end + + private + + def possible_years + FormHandler.instance.sales_forms.values.map { |form| form.start_date.year }.sort.reverse + end + end + end +end diff --git a/app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb b/app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb new file mode 100644 index 000000000..d8cfedd08 --- /dev/null +++ b/app/views/bulk_upload_lettings_logs/forms/prepare_your_file.html.erb @@ -0,0 +1,33 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +
+
+ <%= form_with model: @form, scope: :form, url: bulk_upload_lettings_log_path(id: "prepare-your-file"), method: :patch do |f| %> + <%= f.hidden_field :year %> + + Upload lettings logs in bulk (<%= @form.year_combo %>) +

Prepare your file

+ +

Create your file

+
    +
  • Download the <%= govuk_link_to "bulk lettings template", @form.template_path %>
  • +
  • Export the data from your housing management system, matching the template
  • +
  • If you cannot export it in this format, you may have to input it manually
  • +
+ +

Check your data

+
    +
  • Check data is complete and formatted correctly, using data specifications (opens in a new tab)
  • +
+ +

Save your file

+
    +
  • Save the file (CSV format only)
  • +
+ + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/bulk_upload_lettings_logs/forms/upload_your_file.html.erb b/app/views/bulk_upload_lettings_logs/forms/upload_your_file.html.erb new file mode 100644 index 000000000..86dde8ae2 --- /dev/null +++ b/app/views/bulk_upload_lettings_logs/forms/upload_your_file.html.erb @@ -0,0 +1,17 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +<%= form_with model: @form, scope: :form, url: bulk_upload_lettings_log_path(id: "upload-your-file"), method: :patch do |f| %> + <%= f.govuk_error_summary %> + +
+ Upload your file goes here +
+ +
+ year selected <%= @form.year %> +
+ + <%= f.govuk_submit %> +<% end %> diff --git a/app/views/bulk_upload_lettings_logs/forms/year.html.erb b/app/views/bulk_upload_lettings_logs/forms/year.html.erb new file mode 100644 index 000000000..8ba1c280f --- /dev/null +++ b/app/views/bulk_upload_lettings_logs/forms/year.html.erb @@ -0,0 +1,16 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +<%= form_with model: @form, scope: :form, url: bulk_upload_lettings_log_path(id: "year"), method: :patch do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_collection_radio_buttons :year, + @form.options, + :id, + :name, + legend: { text: "Which year are you uploading data for?", size: "l" }, + caption: { text: "Upload lettings logs in bulk", size: "l" } %> + + <%= f.govuk_submit %> +<% end %> diff --git a/app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb b/app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb new file mode 100644 index 000000000..0157b66eb --- /dev/null +++ b/app/views/bulk_upload_sales_logs/forms/prepare_your_file.html.erb @@ -0,0 +1,33 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +
+
+ <%= form_with model: @form, scope: :form, url: bulk_upload_sales_log_path(id: "prepare-your-file"), method: :patch do |f| %> + <%= f.hidden_field :year %> + + Upload sales logs in bulk (<%= @form.year_combo %>) +

Prepare your file

+ +

Create your file

+
    +
  • Download the <%= govuk_link_to "bulk sales template", @form.template_path %>
  • +
  • Export the data from your housing management system, matching the template
  • +
  • If you cannot export it in this format, you may have to input it manually
  • +
+ +

Check your data

+
    +
  • Check data is complete and formatted correctly, using data specifications (opens in a new tab)
  • +
+ +

Save your file

+
    +
  • Save the file (CSV format only)
  • +
+ + <%= f.govuk_submit %> + <% end %> +
+
diff --git a/app/views/bulk_upload_sales_logs/forms/upload_your_file.html.erb b/app/views/bulk_upload_sales_logs/forms/upload_your_file.html.erb new file mode 100644 index 000000000..a178339e8 --- /dev/null +++ b/app/views/bulk_upload_sales_logs/forms/upload_your_file.html.erb @@ -0,0 +1,17 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +<%= form_with model: @form, scope: :form, url: bulk_upload_sales_log_path(id: "upload-your-file"), method: :patch do |f| %> + <%= f.govuk_error_summary %> + +
+ Upload your file goes here +
+ +
+ year selected <%= @form.year %> +
+ + <%= f.govuk_submit %> +<% end %> diff --git a/app/views/bulk_upload_sales_logs/forms/year.html.erb b/app/views/bulk_upload_sales_logs/forms/year.html.erb new file mode 100644 index 000000000..d8aa09172 --- /dev/null +++ b/app/views/bulk_upload_sales_logs/forms/year.html.erb @@ -0,0 +1,16 @@ +<% content_for :before_content do %> + <%= govuk_back_link href: @form.back_path %> +<% end %> + +<%= form_with model: @form, scope: :form, url: bulk_upload_sales_log_path(id: "year"), method: :patch do |f| %> + <%= f.govuk_error_summary %> + + <%= f.govuk_collection_radio_buttons :year, + @form.options, + :id, + :name, + legend: { text: "Which year are you uploading data for?", size: "l" }, + caption: { text: "Upload sales logs in bulk", size: "l" } %> + + <%= f.govuk_submit %> +<% end %> diff --git a/app/views/logs/index.html.erb b/app/views/logs/index.html.erb index 431ca0f45..a340973cf 100644 --- a/app/views/logs/index.html.erb +++ b/app/views/logs/index.html.erb @@ -10,14 +10,18 @@ <% end %>
-
+
<% if current_page?(controller: 'lettings_logs', action: 'index') %> - <%= govuk_button_to "Create a new lettings log", lettings_logs_path %> + <%= govuk_button_to "Create a new lettings log", lettings_logs_path, class: "govuk-!-margin-right-6" %> <% end %> + <% if FeatureToggle.sales_log_enabled? && current_page?(controller: 'sales_logs', action: 'index') %> - <%= govuk_button_to "Create a new sales log", sales_logs_path %> + <%= govuk_button_to "Create a new sales log", sales_logs_path, class: "govuk-!-margin-right-6" %> + <% end %> + + <% if FeatureToggle.bulk_upload_logs? %> + <%= govuk_button_link_to "Upload #{log_type_for_controller(controller)} logs in bulk", bulk_upload_path_for_controller(controller, id: "start"), secondary: true %> <% end %> - <%#= govuk_link_to "Upload logs", bulk_upload_lettings_logs_path %>
<%= render partial: "log_filters" %> diff --git a/config/initializers/feature_toggle.rb b/config/initializers/feature_toggle.rb index 7cd75ddd3..8fc2cd7d4 100644 --- a/config/initializers/feature_toggle.rb +++ b/config/initializers/feature_toggle.rb @@ -22,4 +22,8 @@ class FeatureToggle def self.managing_for_other_user_enabled? !Rails.env.production? end + + def self.bulk_upload_logs? + !Rails.env.production? + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 43e03c814..2463041f9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -38,6 +38,18 @@ en: create_password: "Create a password to finish setting up your account" reset_password: "Reset your password" + activemodel: + errors: + models: + forms/bulk_upload_lettings/year: + attributes: + year: + blank: You must select a collection period to upload for + forms/bulk_upload_sales/year: + attributes: + year: + blank: You must select a collection period to upload for + activerecord: errors: models: diff --git a/config/routes.rb b/config/routes.rb index ce005902f..aebc664ab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -111,6 +111,12 @@ Rails.application.routes.draw do get "csv-download", to: "lettings_logs#download_csv" post "email-csv", to: "lettings_logs#email_csv" get "csv-confirmation", to: "lettings_logs#csv_confirmation" + + resources :bulk_upload_lettings_logs, path: "bulk-upload-logs" do + collection do + get :start + end + end end member do @@ -130,6 +136,14 @@ Rails.application.routes.draw do end resources :sales_logs, path: "/sales-logs" do + collection do + resources :bulk_upload_sales_logs, path: "bulk-upload-logs" do + collection do + get :start + end + end + end + FormHandler.instance.sales_forms.each do |_key, form| form.pages.map do |page| get page.id.to_s.dasherize, to: "form#show_page" diff --git a/public/files/bulk-upload-lettings-template-v1.xlsx b/public/files/bulk-upload-lettings-template-v1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ca30388baf0f2e1933ef805f8e397d0bd9ca6c13 GIT binary patch literal 35928 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 literal 0 HcmV?d00001 diff --git a/public/files/bulk-upload-sales-template-v1.xlsx b/public/files/bulk-upload-sales-template-v1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..73c9f829c4e4ebe46b21db1539704ccb4b048927 GIT binary patch literal 26703 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 literal 0 HcmV?d00001 diff --git a/spec/features/bulk_upload_lettings_logs_spec.rb b/spec/features/bulk_upload_lettings_logs_spec.rb new file mode 100644 index 000000000..e9a05b07d --- /dev/null +++ b/spec/features/bulk_upload_lettings_logs_spec.rb @@ -0,0 +1,51 @@ +require "rails_helper" + +RSpec.describe "Bulk upload lettings log" do + let(:user) { create(:user) } + + before do + sign_in user + end + + context "when during crossover period" do + it "shows journey with year option" do + Timecop.freeze(2023, 6, 1) do + visit("/lettings-logs") + expect(page).to have_link("Upload lettings logs in bulk") + click_link("Upload lettings logs in bulk") + + expect(page).to have_content("Which year") + click_button("Continue") + + expect(page).to have_content("You must select a collection period to upload for") + choose("2022/2023") + click_button("Continue") + + click_link("Back") + + expect(page.find_field("form-year-2022-field")).to be_checked + click_button("Continue") + + expect(page).to have_content("Upload lettings logs in bulk (2022/23)") + click_button("Continue") + + expect(page).to have_content("Upload your file") + end + end + end + + context "when not it crossover period" do + it "shows journey with year option" do + Timecop.freeze(2023, 10, 1) do + visit("/lettings-logs") + expect(page).to have_link("Upload lettings logs in bulk") + click_link("Upload lettings logs in bulk") + + expect(page).to have_content("Upload lettings logs in bulk (2022/23)") + click_button("Continue") + + expect(page).to have_content("Upload your file") + end + end + end +end diff --git a/spec/features/bulk_upload_sales_logs_spec.rb b/spec/features/bulk_upload_sales_logs_spec.rb new file mode 100644 index 000000000..67187ff78 --- /dev/null +++ b/spec/features/bulk_upload_sales_logs_spec.rb @@ -0,0 +1,51 @@ +require "rails_helper" + +RSpec.describe "Bulk upload sales log" do + let(:user) { create(:user) } + + before do + sign_in user + end + + context "when during crossover period" do + it "shows journey with year option" do + Timecop.freeze(2023, 6, 1) do + visit("/sales-logs") + expect(page).to have_link("Upload sales logs in bulk") + click_link("Upload sales logs in bulk") + + expect(page).to have_content("Which year") + click_button("Continue") + + expect(page).to have_content("You must select a collection period to upload for") + choose("2022/2023") + click_button("Continue") + + click_link("Back") + + expect(page.find_field("form-year-2022-field")).to be_checked + click_button("Continue") + + expect(page).to have_content("Upload sales logs in bulk (2022/23)") + click_button("Continue") + + expect(page).to have_content("Upload your file") + end + end + end + + context "when not it crossover period" do + it "shows journey with year option" do + Timecop.freeze(2023, 10, 1) do + visit("/sales-logs") + expect(page).to have_link("Upload sales logs in bulk") + click_link("Upload sales logs in bulk") + + expect(page).to have_content("Upload sales logs in bulk (2022/23)") + click_button("Continue") + + expect(page).to have_content("Upload your file") + end + end + end +end diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index a062a4aa5..f8bcddcca 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -235,4 +235,38 @@ RSpec.describe Form, type: :model do expect(form.sections[1].class).to eq(Form::Sales::Sections::PropertyInformation) end end + + describe "#in_crossover_period?" do + context "when now not specified" do + context "when after end period" do + subject(:form) { described_class.new(nil, 2022, [], "sales") } + + it "returns false" do + Timecop.freeze(2023, 8, 1) do + expect(form).not_to be_in_crossover_period + end + end + end + + context "when during crossover" do + subject(:form) { described_class.new(nil, 2022, [], "sales") } + + it "returns true" do + Timecop.freeze(2023, 6, 1) do + expect(form).to be_in_crossover_period + end + end + end + + context "when before crossover" do + subject(:form) { described_class.new(nil, 2022, [], "sales") } + + it "returns false" do + Timecop.freeze(2023, 1, 1) do + expect(form).not_to be_in_crossover_period + end + end + end + end + end end diff --git a/spec/models/forms/bulk_upload_lettings/year_spec.rb b/spec/models/forms/bulk_upload_lettings/year_spec.rb new file mode 100644 index 000000000..0b0babb30 --- /dev/null +++ b/spec/models/forms/bulk_upload_lettings/year_spec.rb @@ -0,0 +1,12 @@ +require "rails_helper" + +RSpec.describe Forms::BulkUploadLettings::Year do + subject(:form) { described_class.new } + + describe "#options" do + it "returns correct years" do + expect(form.options.map(&:id)).to eql([2022, 2021]) + expect(form.options.map(&:name)).to eql(%w[2022/2023 2021/2022]) + end + end +end diff --git a/spec/models/forms/bulk_upload_sales/year_spec.rb b/spec/models/forms/bulk_upload_sales/year_spec.rb new file mode 100644 index 000000000..2276b1e4d --- /dev/null +++ b/spec/models/forms/bulk_upload_sales/year_spec.rb @@ -0,0 +1,12 @@ +require "rails_helper" + +RSpec.describe Forms::BulkUploadSales::Year do + subject(:form) { described_class.new } + + describe "#options" do + it "returns correct years" do + expect(form.options.map(&:id)).to eql([2022, 2021]) + expect(form.options.map(&:name)).to eql(%w[2022/2023 2021/2022]) + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index cdeb71092..e25631df7 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -82,6 +82,7 @@ RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::ControllerHelpers, type: :view config.include Devise::Test::IntegrationHelpers, type: :request + config.include Devise::Test::IntegrationHelpers, type: :feature config.include ViewComponent::TestHelpers, type: :component config.include Capybara::RSpecMatchers, type: :component config.include ActiveJob::TestHelper diff --git a/spec/requests/bulk_upload_lettings_logs_controller_spec.rb b/spec/requests/bulk_upload_lettings_logs_controller_spec.rb new file mode 100644 index 000000000..788965e83 --- /dev/null +++ b/spec/requests/bulk_upload_lettings_logs_controller_spec.rb @@ -0,0 +1,32 @@ +require "rails_helper" + +RSpec.describe BulkUploadLettingsLogsController, type: :request do + let(:user) { FactoryBot.create(:user) } + let(:organisation) { user.organisation } + + before do + sign_in user + end + + describe "GET /lettings-logs/bulk-upload-logs/start" do + context "when not in crossover period" do + it "redirects to /prepare-your-file" do + Timecop.freeze(2022, 1, 1) do + get "/lettings-logs/bulk-upload-logs/start", params: {} + + expect(response).to redirect_to("/lettings-logs/bulk-upload-logs/prepare-your-file?form%5Byear%5D=2022") + end + end + end + + context "when in crossover period" do + it "redirects to /year" do + Timecop.freeze(2023, 6, 1) do + get "/lettings-logs/bulk-upload-logs/start", params: {} + + expect(response).to redirect_to("/lettings-logs/bulk-upload-logs/year") + end + end + end + end +end diff --git a/spec/requests/bulk_upload_sales_logs_controller_spec.rb b/spec/requests/bulk_upload_sales_logs_controller_spec.rb new file mode 100644 index 000000000..f668b0da1 --- /dev/null +++ b/spec/requests/bulk_upload_sales_logs_controller_spec.rb @@ -0,0 +1,32 @@ +require "rails_helper" + +RSpec.describe BulkUploadSalesLogsController, type: :request do + let(:user) { FactoryBot.create(:user) } + let(:organisation) { user.organisation } + + before do + sign_in user + end + + describe "GET /sales-logs/bulk-upload-logs/start" do + context "when not in crossover period" do + it "redirects to /prepare-your-file" do + Timecop.freeze(2022, 1, 1) do + get "/sales-logs/bulk-upload-logs/start", params: {} + + expect(response).to redirect_to("/sales-logs/bulk-upload-logs/prepare-your-file?form%5Byear%5D=2022") + end + end + end + + context "when in crossover period" do + it "redirects to /year" do + Timecop.freeze(2023, 6, 1) do + get "/sales-logs/bulk-upload-logs/start", params: {} + + expect(response).to redirect_to("/sales-logs/bulk-upload-logs/year") + end + end + end + end +end