diff --git a/Gemfile.lock b/Gemfile.lock index c8d1edd1a..7fdef3710 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -379,7 +379,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.2) + rexml (3.3.3) strscan roo (2.10.1) nokogiri (~> 1) diff --git a/app/components/bulk_upload_error_row_component.html.erb b/app/components/bulk_upload_error_row_component.html.erb index 907c73298..4e9ff1390 100644 --- a/app/components/bulk_upload_error_row_component.html.erb +++ b/app/components/bulk_upload_error_row_component.html.erb @@ -1,13 +1,16 @@
These errors must be fixed to complete your logs.
<%= govuk_table do |table| %> <%= table.with_head do |head| %> <% head.with_row do |row| %> @@ -18,16 +21,49 @@ <% end %> <%= table.with_body do |body| %> - <% bulk_upload_errors.each do |error| %> + <% critical_errors.each do |error| %> <% body.with_row do |row| %> - <% row.with_cell(header: true, text: error.cell) %> - <% row.with_cell(text: question_for_field(error.field)) %> - <% row.with_cell(text: error.error) %> - <% row.with_cell(text: error.field.humanize) %> + <% row.with_cell(text: error.cell) %> + <% row.with_cell(text: question_for_field(error.field)) %> + <% row.with_cell(text: error.error, html_attributes: { class: "govuk-!-font-weight-bold" }) %> + <% row.with_cell(text: error.field.humanize) %> <% end %> <% end %> <% end %> <% end %> <% end %> + + <% if potential_errors.any? %> +The following groups of cells might have conflicting data. Check the answers and fix any incorrect data.
If the answers are correct, fix the critical errors and reupload the file. You'll need to confirm that the following data is correct when the file only contains potential errors.
- We could not create logs from your bulk upload. Below is a list of everything that you need to fix your spreadsheet. You can download the <%= govuk_link_to "specification", Forms::BulkUploadLettings::PrepareYourFile.new(year: @bulk_upload.year).specification_path, target: "_blank" %> to help you fix the cells in your CSV file. + We could not create logs from your bulk upload because of the following errors. Download the <%= govuk_link_to "specification", Forms::BulkUploadLettings::PrepareYourFile.new(year: @bulk_upload.year).specification_path, target: "_blank" %> to help you fix the cells in your CSV file.
diff --git a/app/views/bulk_upload_sales_results/summary.html.erb b/app/views/bulk_upload_sales_results/summary.html.erb index 8fd6c22ed..af504acbd 100644 --- a/app/views/bulk_upload_sales_results/summary.html.erb +++ b/app/views/bulk_upload_sales_results/summary.html.erb @@ -4,7 +4,7 @@
- We could not create logs from your bulk upload. Below is a list of everything that you need to fix your spreadsheet. You can download the <%= govuk_link_to "specification", Forms::BulkUploadSales::PrepareYourFile.new(year: @bulk_upload.year).specification_path, target: "_blank" %> to help you fix the cells in your CSV file. + We could not create logs from your bulk upload because of the following errors. Download the <%= govuk_link_to "specification", Forms::BulkUploadSales::PrepareYourFile.new(year: @bulk_upload.year).specification_path, target: "_blank" %> to help you fix the cells in your CSV file.
diff --git a/app/views/filters/_radio_filter.html.erb b/app/views/filters/_radio_filter.html.erb index 6eb902dba..e4d23573c 100644 --- a/app/views/filters/_radio_filter.html.erb +++ b/app/views/filters/_radio_filter.html.erb @@ -10,6 +10,7 @@ collection: option[:conditional_filter][:options], category: option[:conditional_filter][:category], label: option[:conditional_filter][:label], + caption_text: option[:conditional_filter][:caption_text], secondary: true, hint_text: option[:conditional_filter][:hint_text], } %> diff --git a/app/views/filters/_text_select_filter.html.erb b/app/views/filters/_text_select_filter.html.erb new file mode 100644 index 000000000..ecc997bba --- /dev/null +++ b/app/views/filters/_text_select_filter.html.erb @@ -0,0 +1,20 @@ + +<%= f.govuk_text_field "#{category}_text_search".to_sym, + label: { text: label, hidden: secondary }, + "data-controller": "search conditional-filter", + caption: { text: caption_text }, + "data-info": { search_url: filter_search_url(category.to_sym) }.to_json, + value: selected_option("#{category}_text_search", @filter_type) %> + +<%= f.govuk_select(category.to_sym, + label: { text: label, hidden: secondary }, + "data-controller": "search conditional-filter", + "hidden": true, + "data-info": { search_url: filter_search_url(category.to_sym) }.to_json) do %> + <% collection.each do |answer| %> + + <% end %> + <% end %> diff --git a/app/views/filters/assigned_to.html.erb b/app/views/filters/assigned_to.html.erb index 9f0582fbb..778d63c8a 100644 --- a/app/views/filters/assigned_to.html.erb +++ b/app/views/filters/assigned_to.html.erb @@ -11,7 +11,8 @@ type: "select", label: "User", category: "user", - options: assigned_to_filter_options(current_user), + caption_text: "User's name or email", + options: assigned_to_csv_filter_options(current_user), }, }, }, diff --git a/app/views/filters/managed_by.html.erb b/app/views/filters/managed_by.html.erb index e3d849c9b..5d4b684f3 100644 --- a/app/views/filters/managed_by.html.erb +++ b/app/views/filters/managed_by.html.erb @@ -9,7 +9,8 @@ type: "select", label: "Managed by", category: "managing_organisation", - options: managing_organisation_filter_options(current_user), + options: managing_organisation_csv_filter_options(current_user), + caption_text: "Organisation name", }, }, }, diff --git a/app/views/filters/owned_by.html.erb b/app/views/filters/owned_by.html.erb index 7acfd459c..271b68de9 100644 --- a/app/views/filters/owned_by.html.erb +++ b/app/views/filters/owned_by.html.erb @@ -9,7 +9,8 @@ type: "select", label: "Owning Organisation", category: "owning_organisation", - options: owning_organisation_filter_options(current_user), + options: all_owning_organisation_filter_options(current_user), + caption_text: "Organisation name", }, }, }, diff --git a/app/views/form/guidance/_finding_scheme.erb b/app/views/form/guidance/_finding_scheme.erb index d2dea2202..8101c5a6d 100644 --- a/app/views/form/guidance/_finding_scheme.erb +++ b/app/views/form/guidance/_finding_scheme.erb @@ -1,6 +1,6 @@ <%= govuk_details(summary_text: "Can’t find your scheme?") do %>
Schemes are attached to the organisation that owns the property. Check you have correctly answered question 1 "Which organisation owns this property?"
If your organisation’s schemes were migrated from old CORE, they may have new names and codes. Search by postcode to find your scheme.
-<%= govuk_link_to("View your organisation’s schemes", schemes_path) %>
+<%= govuk_link_to("View your organisation’s schemes", clear_filters_url(filter_type: "schemes")) %>
<%= govuk_link_to("Read more about how schemes have changed", scheme_changes_path) %>
<% end %> diff --git a/app/views/logs/_log_filters.html.erb b/app/views/logs/_log_filters.html.erb index aaef70377..3beab4b6b 100644 --- a/app/views/logs/_log_filters.html.erb +++ b/app/views/logs/_log_filters.html.erb @@ -66,10 +66,11 @@ "specific_user": { label: "Specific user", conditional_filter: { - type: "select", + type: "text_select", label: "User", category: "user", - options: assigned_to_filter_options(current_user), + options: assigned_to_filter_options(@filter_type), + caption_text: "User's name or email", }, }, }, @@ -86,10 +87,11 @@ "specific_org": { label: "Specific owning organisation", conditional_filter: { - type: "select", + type: "text_select", label: "Owning Organisation", category: "owning_organisation", - options: owning_organisation_filter_options(current_user), + options: owning_organisation_filter_options(current_user, @filter_type), + caption_text: "Organisation name", }, }, }, @@ -107,10 +109,11 @@ "specific_org": { label: "Specific managing organisation", conditional_filter: { - type: "select", + type: "text_select", label: user_or_org_lettings_path? ? "Managed by" : "Reported by", category: "managing_organisation", - options: managing_organisation_filter_options(current_user), + options: managing_organisation_filter_options(current_user, @filter_type), + caption_text: "Organisation name", }, }, }, diff --git a/app/views/schemes/_scheme_filters.html.erb b/app/views/schemes/_scheme_filters.html.erb index ca0538463..51687a096 100644 --- a/app/views/schemes/_scheme_filters.html.erb +++ b/app/views/schemes/_scheme_filters.html.erb @@ -35,7 +35,7 @@ type: "select", label: "Owning Organisation", category: "owning_organisation", - options: owning_organisation_filter_options(current_user), + options: all_owning_organisation_filter_options(current_user), }, }, }, diff --git a/config/locales/en.yml b/config/locales/en.yml index a70e7082b..a53b375fe 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -436,7 +436,9 @@ en: under_10: "Enter a total charge that is at least £10.00 per week" less_than_shortfall: "The total charge must be more than the outstanding amount" rent_period: - invalid_for_org: "%{org_name} does not use %{rent_period} as a rent period. Choose another rent period, or a data coordinator can add rent periods to your organisation" + invalid_for_org: + period: "%{org_name} does not use %{rent_period} as a rent period. Choose another rent period, or a data coordinator can add rent periods to your organisation" + managing_org: "%{org_name} does not use %{rent_period} as a rent period. Set another rent period on this log, or a data coordinator can add rent periods to this organisation" carehome: out_of_range: "Household rent and other charges must be between %{min_chcharge} and %{max_chcharge} if paying %{period}" not_provided: "Enter how much rent and other charges the household pays %{period}" @@ -587,13 +589,13 @@ en: declaration: missing: - pre_2024: "You must show the MHCLG privacy notice to the tenant before you can submit this log." - post_2024: "You must show or give access to the MHCLG privacy notice to the tenant before you can submit this log." + pre_2024: "You must show the MHCLG privacy notice to the tenant before you can submit this log" + post_2024: "You must show or give the tenant access to the MHCLG privacy notice before you can submit this log" privacynotice: missing: - pre_2024: "You must show the MHCLG privacy notice to the %{buyer_or_buyers} before you can submit this log." - post_2024: "You must show or give access to the MHCLG privacy notice to the %{buyer_or_buyers} before you can submit this log." + pre_2024: "You must show the MHCLG privacy notice to the %{buyer_or_buyers} before you can submit this log" + post_2024: "You must show or give the %{buyer_or_buyers} access to the MHCLG privacy notice before you can submit this log" scheme: toggle_date: diff --git a/config/routes.rb b/config/routes.rb index e0d9631e9..faea457fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -125,6 +125,10 @@ Rails.application.routes.draw do get "edit-dpo", to: "users#dpo" get "edit-key-contact", to: "users#key_contact" + collection do + get :search + end + member do get "deactivate", to: "users#deactivate" get "reactivate", to: "users#reactivate" @@ -191,6 +195,10 @@ Rails.application.routes.draw do get "delete-confirmation", to: "organisations#delete_confirmation" delete "delete", to: "organisations#delete" end + + collection do + get :search + end end resources :merge_requests, path: "/merge-request" do diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index ee982b784..849732bc5 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -226,7 +226,7 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.3.2) + rexml (3.3.3) strscan rouge (3.26.0) ruby2_keywords (0.0.5) diff --git a/spec/components/bulk_upload_error_row_component_spec.rb b/spec/components/bulk_upload_error_row_component_spec.rb index 01af041cb..b593a0048 100644 --- a/spec/components/bulk_upload_error_row_component_spec.rb +++ b/spec/components/bulk_upload_error_row_component_spec.rb @@ -108,4 +108,53 @@ RSpec.describe BulkUploadErrorRowComponent, type: :component do expect(result).to have_content(expected) end end + + context "when there are potential errors" do + let(:row) { rand(9_999) } + let(:tenant_code) { SecureRandom.hex(4) } + let(:property_ref) { SecureRandom.hex(4) } + let(:purchaser_code) { nil } + let(:category) { "soft_validation" } + let(:field_46) { 40 } + let(:field_50) { 5 } + let(:error) { "You told us this person is aged 40 years and retired." } + let(:bulk_upload) { create(:bulk_upload, :lettings) } + let(:bulk_upload_errors) do + [ + FactoryBot.build( + :bulk_upload_error, + bulk_upload:, + row:, + tenant_code:, + property_ref:, + purchaser_code:, + field: :field_46, + error:, + category:, + ), + FactoryBot.build( + :bulk_upload_error, + bulk_upload:, + row:, + tenant_code:, + property_ref:, + purchaser_code:, + field: :field_50, + error:, + category:, + ), + ] + end + + it "renders the potential errors section" do + result = render_inline(described_class.new(bulk_upload_errors:)) + expect(result).to have_content("Potential errors") + end + + it "renders the potential error message" do + expected = error + result = render_inline(described_class.new(bulk_upload_errors:)) + expect(result).to have_content(expected, count: 1) + end + end end diff --git a/spec/features/lettings_log_spec.rb b/spec/features/lettings_log_spec.rb index 2b977fdd7..ac9a1e4a8 100644 --- a/spec/features/lettings_log_spec.rb +++ b/spec/features/lettings_log_spec.rb @@ -89,9 +89,9 @@ RSpec.describe "Lettings Log Features" do check("In progress") choose("You") choose("Specific owning organisation") - select(stock_owner_1.name, from: "owning_organisation") + fill_in("owning-organisation-text-search-field", with: "stock") choose("Specific managing organisation") - select(managing_agent_1.name, from: "managing_organisation") + fill_in("managing-organisation-text-search-field", with: "managing") click_button("Apply filters") end diff --git a/spec/features/organisation_spec.rb b/spec/features/organisation_spec.rb index 65f787c2a..1867285eb 100644 --- a/spec/features/organisation_spec.rb +++ b/spec/features/organisation_spec.rb @@ -199,14 +199,14 @@ RSpec.describe "User Features" do it "can filter lettings logs by year" do check("years-2022-field") click_button("Apply filters") - expect(page).to have_current_path("/organisations/#{org_id}/lettings-logs?years[]=&years[]=2022&status[]=&needstypes[]=&assigned_to=all&user=&owning_organisation_select=all&owning_organisation=&managing_organisation_select=all&managing_organisation=") + expect(page).to have_current_path("/organisations/#{org_id}/lettings-logs?years[]=&years[]=2022&status[]=&needstypes[]=&assigned_to=all&user_text_search=&user=&owning_organisation_select=all&owning_organisation_text_search=&owning_organisation=&managing_organisation_select=all&managing_organisation_text_search=&managing_organisation=") expect(page).not_to have_link first_log.id.to_s, href: "/lettings-logs/#{first_log.id}" end it "can filter lettings logs by needstype" do check("needstypes-1-field") click_button("Apply filters") - expect(page).to have_current_path("/organisations/#{org_id}/lettings-logs?years[]=&status[]=&needstypes[]=&needstypes[]=1&assigned_to=all&user=&owning_organisation_select=all&owning_organisation=&managing_organisation_select=all&managing_organisation=") + expect(page).to have_current_path("/organisations/#{org_id}/lettings-logs?years[]=&status[]=&needstypes[]=&needstypes[]=1&assigned_to=all&user_text_search=&user=&owning_organisation_select=all&owning_organisation_text_search=&owning_organisation=&managing_organisation_select=all&managing_organisation_text_search=&managing_organisation=") other_general_needs_logs.each do |general_needs_log| expect(page).to have_link general_needs_log.id.to_s, href: "/lettings-logs/#{general_needs_log.id}" end @@ -245,7 +245,7 @@ RSpec.describe "User Features" do end check("years-2022-field") click_button("Apply filters") - expect(page).to have_current_path("/organisations/#{org_id}/sales-logs?years[]=&years[]=2022&status[]=&assigned_to=all&user=&owning_organisation_select=all&owning_organisation=&managing_organisation_select=all&managing_organisation=") + expect(page).to have_current_path("/organisations/#{org_id}/sales-logs?years[]=&years[]=2022&status[]=&assigned_to=all&user_text_search=&user=&owning_organisation_select=all&owning_organisation_text_search=&owning_organisation=&managing_organisation_select=all&managing_organisation_text_search=&managing_organisation=") expect(page).not_to have_link first_log.id.to_s, href: "/sales-logs/#{first_log.id}" end end diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index da80693ec..2d43e9b02 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -99,6 +99,20 @@ RSpec.describe "Schemes scheme Features" do expect(page).not_to have_link("Clear", href: "/clear-filters?filter_type=schemes") end end + + context "when on the scheme question page" do + let(:lettings_log) { FactoryBot.create(:lettings_log, assigned_to: user, needstype: 2) } + + it "open from guidance page with filters cleared" do + expect(page).to have_text("2 filters applied") + visit("/lettings-logs/#{lettings_log.id}/scheme") + find(".govuk-details__summary").click + expect(page).to have_link("View your organisation’s schemes") + click_link "View your organisation’s schemes" + expect(page).to have_current_path("/organisations/#{user.organisation.id}/schemes") + expect(page).to have_text("No filters applied") + end + end end end end diff --git a/spec/features/user_spec.rb b/spec/features/user_spec.rb index 169465cb1..c30abe1e9 100644 --- a/spec/features/user_spec.rb +++ b/spec/features/user_spec.rb @@ -796,12 +796,13 @@ RSpec.describe "User Features" do visit("/lettings-logs") choose("owning-organisation-select-specific-org-field", allow_label_click: true) expect(page).to have_field("owning-organisation-field", with: "") - find("#owning-organisation-field").click.native.send_keys("F", "i", "l", "t", :down, :enter) + find("#owning-organisation-field").click.native.send_keys("F", "i", "l", "t") + select(parent_organisation.name, from: "owning-organisation-field-select", visible: false) click_button("Apply filters") - expect(page).to have_current_path("/lettings-logs?%5Byears%5D%5B%5D=&%5Bstatus%5D%5B%5D=&%5Bneedstypes%5D%5B%5D=&assigned_to=all&owning_organisation_select=specific_org&owning_organisation=#{parent_organisation.id}&managing_organisation_select=all") + expect(page).to have_current_path("/lettings-logs?%5Byears%5D%5B%5D=&%5Bstatus%5D%5B%5D=&%5Bneedstypes%5D%5B%5D=&assigned_to=all&user_text_search=&owning_organisation_select=specific_org&owning_organisation_text_search=&owning_organisation=#{parent_organisation.id}&managing_organisation_select=all&managing_organisation_text_search=") choose("owning-organisation-select-all-field", allow_label_click: true) click_button("Apply filters") - expect(page).to have_current_path("/lettings-logs?%5Byears%5D%5B%5D=&%5Bstatus%5D%5B%5D=&%5Bneedstypes%5D%5B%5D=&assigned_to=all&owning_organisation_select=all&managing_organisation_select=all") + expect(page).to have_current_path("/lettings-logs?%5Byears%5D%5B%5D=&%5Bstatus%5D%5B%5D=&%5Bneedstypes%5D%5B%5D=&assigned_to=all&user_text_search=&owning_organisation_select=all&owning_organisation_text_search=&managing_organisation_select=all&managing_organisation_text_search=") end end end diff --git a/spec/helpers/filters_helper_spec.rb b/spec/helpers/filters_helper_spec.rb index f04157521..c57f92311 100644 --- a/spec/helpers/filters_helper_spec.rb +++ b/spec/helpers/filters_helper_spec.rb @@ -175,27 +175,146 @@ RSpec.describe FiltersHelper do context "with a support user" do let(:user) { FactoryBot.create(:user, :support, organisation: child_organisation) } - it "returns a list of all organisations" do - expect(owning_organisation_filter_options(user)).to match_array([ - OpenStruct.new(id: "", name: "Select an option"), - OpenStruct.new(id: child_organisation.id, name: "Child organisation"), - OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), - OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), - OpenStruct.new(id: 99, name: "Other organisation"), - ]) + context "when no organisation is selected in the filters" do + it "returns an empty list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a specific child organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": child_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: child_organisation.id, name: "Child organisation"), + ]) + end + end + + context "when a specific parent organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": parent_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), + ]) + end + end + + context "when a specific absorbed organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": absorbed_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), + ]) + end + end + + context "when a specific non related organisation is selected in the filters" do + let(:unrelated_organisation) { create(:organisation, name: "Unrelated organisation") } + + before do + session[:lettings_logs_filters] = { "owning_organisation": unrelated_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: unrelated_organisation.id, name: "Unrelated organisation"), + ]) + end + end + + context "when a non existing organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": 143_542_542 }.to_json + end + + it "returns an empty list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end end end context "with a data coordinator user" do let(:user) { FactoryBot.create(:user, :data_coordinator, organisation: child_organisation) } - it "returns a list of parent orgs and your own organisation" do - expect(owning_organisation_filter_options(user.reload)).to eq([ - OpenStruct.new(id: "", name: "Select an option"), - OpenStruct.new(id: child_organisation.id, name: "Child organisation"), - OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), - OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), - ]) + context "when no organisation is selected in the filters" do + it "returns an empty list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a specific child organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": child_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: child_organisation.id, name: "Child organisation"), + ]) + end + end + + context "when a specific parent organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": parent_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), + ]) + end + end + + context "when a specific absorbed organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": absorbed_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), + ]) + end + end + + context "when a specific non related organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": create(:organisation).id }.to_json + end + + it "returns an empty list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a non existing organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "owning_organisation": 143_542_542 }.to_json + end + + it "returns an empty list" do + expect(owning_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end end end end @@ -214,27 +333,146 @@ RSpec.describe FiltersHelper do context "with a support user" do let(:user) { FactoryBot.create(:user, :support, organisation: parent_organisation) } - it "returns a list of all organisations" do - expect(managing_organisation_filter_options(user)).to eq([ - OpenStruct.new(id: "", name: "Select an option"), - OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), - OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), - OpenStruct.new(id: child_organisation.id, name: "Child organisation"), - OpenStruct.new(id: 99, name: "Other organisation"), - ]) + context "when no organisation is selected in the filters" do + it "returns an empty list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a specific child organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": child_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: child_organisation.id, name: "Child organisation"), + ]) + end + end + + context "when a specific parent organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": parent_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), + ]) + end + end + + context "when a specific absorbed organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": absorbed_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), + ]) + end + end + + context "when a specific non related organisation is selected in the filters" do + let(:unrelated_organisation) { create(:organisation, name: "Unrelated organisation") } + + before do + session[:lettings_logs_filters] = { "managing_organisation": unrelated_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: unrelated_organisation.id, name: "Unrelated organisation"), + ]) + end + end + + context "when a non existing organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": 143_542_542 }.to_json + end + + it "returns an empty list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end end end context "with a data coordinator user" do let(:user) { FactoryBot.create(:user, :data_coordinator, organisation: parent_organisation) } - it "returns a list of child orgs and your own organisation" do - expect(managing_organisation_filter_options(user.reload)).to eq([ - OpenStruct.new(id: "", name: "Select an option"), - OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), - OpenStruct.new(id: child_organisation.id, name: "Child organisation"), - OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), - ]) + context "when no organisation is selected in the filters" do + it "returns an empty list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a specific child organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": child_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: child_organisation.id, name: "Child organisation"), + ]) + end + end + + context "when a specific parent organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": parent_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: parent_organisation.id, name: "Parent organisation"), + ]) + end + end + + context "when a specific absorbed organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": absorbed_organisation.id }.to_json + end + + it "returns the selected organisation in the list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: absorbed_organisation.id, name: "Absorbed organisation"), + ]) + end + end + + context "when a specific non related organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": create(:organisation).id }.to_json + end + + it "returns an empty list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end + end + + context "when a non existing organisation is selected in the filters" do + before do + session[:lettings_logs_filters] = { "managing_organisation": 143_542_542 }.to_json + end + + it "returns an empty list" do + expect(managing_organisation_filter_options(user.reload, "lettings_logs")).to eq([ + OpenStruct.new(id: "", name: "Select an option"), + ]) + end end end end diff --git a/spec/models/form/lettings/questions/declaration_spec.rb b/spec/models/form/lettings/questions/declaration_spec.rb index ab9bcebef..c64e7f3c8 100644 --- a/spec/models/form/lettings/questions/declaration_spec.rb +++ b/spec/models/form/lettings/questions/declaration_spec.rb @@ -63,7 +63,7 @@ RSpec.describe Form::Lettings::Questions::Declaration, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the tenant before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the tenant before you can submit this log") end end @@ -87,7 +87,7 @@ RSpec.describe Form::Lettings::Questions::Declaration, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show or give access to the MHCLG privacy notice to the tenant before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show or give the tenant access to the MHCLG privacy notice before you can submit this log") end end end diff --git a/spec/models/form/sales/questions/privacy_notice_spec.rb b/spec/models/form/sales/questions/privacy_notice_spec.rb index 4be918c5c..9fb81057a 100644 --- a/spec/models/form/sales/questions/privacy_notice_spec.rb +++ b/spec/models/form/sales/questions/privacy_notice_spec.rb @@ -60,7 +60,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the buyer before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the buyer before you can submit this log") end end @@ -78,7 +78,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the buyers before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show the MHCLG privacy notice to the buyers before you can submit this log") end end end @@ -100,7 +100,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show or give access to the MHCLG privacy notice to the buyer before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show or give the buyer access to the MHCLG privacy notice before you can submit this log") end end @@ -118,7 +118,7 @@ RSpec.describe Form::Sales::Questions::PrivacyNotice, type: :model do end it "returns correct unanswered_error_message" do - expect(question.unanswered_error_message).to eq("You must show or give access to the MHCLG privacy notice to the buyers before you can submit this log.") + expect(question.unanswered_error_message).to eq("You must show or give the buyers access to the MHCLG privacy notice before you can submit this log") end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index edb998ac3..6a04e9a0b 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -164,7 +164,7 @@ RSpec.describe User, type: :model do end it "can filter lettings logs by user, year and status" do - expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user bulk_upload_id]) + expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user bulk_upload_id user_text_search]) end end @@ -174,7 +174,7 @@ RSpec.describe User, type: :model do end it "can filter lettings logs by user, year, status, managing_organisation and owning_organisation" do - expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user managing_organisation owning_organisation bulk_upload_id]) + expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user managing_organisation owning_organisation bulk_upload_id managing_organisation_text_search owning_organisation_text_search user_text_search]) end end end @@ -215,7 +215,7 @@ RSpec.describe User, type: :model do end it "can filter lettings logs by user, year, status, managing_organisation and owning_organisation" do - expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user owning_organisation managing_organisation bulk_upload_id]) + expect(user.logs_filters).to match_array(%w[years status needstypes assigned_to user owning_organisation managing_organisation bulk_upload_id managing_organisation_text_search owning_organisation_text_search user_text_search]) end end diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb index c743381f7..a6eefa708 100644 --- a/spec/models/validations/financial_validations_spec.rb +++ b/spec/models/validations/financial_validations_spec.rb @@ -165,7 +165,13 @@ RSpec.describe Validations::FinancialValidations do financial_validator.validate_rent_period(record) expect(record.errors["period"]) .to include(match I18n.t( - "validations.financial.rent_period.invalid_for_org", + "validations.financial.rent_period.invalid_for_org.period", + org_name: user.organisation.name, + rent_period: "every 4 weeks", + )) + expect(record.errors["managing_organisation_id"]) + .to include(match I18n.t( + "validations.financial.rent_period.invalid_for_org.managing_org", org_name: user.organisation.name, rent_period: "every 4 weeks", )) diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index 13879a38c..d3e8a8155 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -75,6 +75,13 @@ RSpec.describe OrganisationsController, type: :request do end end end + + describe "#search" do + it "redirects to the sign in page" do + get "/organisations/search" + expect(response).to redirect_to("/account/sign-in") + end + end end context "when user is signed in" do @@ -807,6 +814,25 @@ RSpec.describe OrganisationsController, type: :request do end end end + + describe "#search" do + let(:parent_organisation) { create(:organisation, name: "parent test organisation") } + let(:child_organisation) { create(:organisation, name: "child test organisation") } + + before do + user.organisation.update!(name: "test organisation") + create(:organisation_relationship, parent_organisation: user.organisation, child_organisation:) + create(:organisation_relationship, child_organisation: user.organisation, parent_organisation:) + create(:organisation, name: "other organisation test organisation") + end + + it "only searches within the current user's organisation, managing agents and stock owners" do + get "/organisations/search", headers:, params: { query: "test organisation" } + result = JSON.parse(response.body) + expect(result.count).to eq(3) + expect(result.keys).to match_array([user.organisation.id.to_s, parent_organisation.id.to_s, child_organisation.id.to_s]) + end + end end context "with a data provider user" do @@ -2077,6 +2103,25 @@ RSpec.describe OrganisationsController, type: :request do end end end + + describe "#search" do + let(:parent_organisation) { create(:organisation, name: "parent test organisation") } + let(:child_organisation) { create(:organisation, name: "child test organisation") } + let!(:other_organisation) { create(:organisation, name: "other organisation test organisation") } + + before do + user.organisation.update!(name: "test organisation") + create(:organisation_relationship, parent_organisation: user.organisation, child_organisation:) + create(:organisation_relationship, child_organisation: user.organisation, parent_organisation:) + end + + it "searches within all the organisations" do + get "/organisations/search", headers:, params: { query: "test organisation" } + result = JSON.parse(response.body) + expect(result.count).to eq(4) + expect(result.keys).to match_array([user.organisation.id.to_s, parent_organisation.id.to_s, child_organisation.id.to_s, other_organisation.id.to_s]) + end + end end end diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index bb0a1cca3..8e87f7f28 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -117,6 +117,13 @@ RSpec.describe UsersController, type: :request do expect(response).to redirect_to("/account/sign-in") end end + + describe "#search" do + it "redirects to the sign in page" do + get "/users/search" + expect(response).to redirect_to("/account/sign-in") + end + end end context "when user is signed in as a data provider" do @@ -404,6 +411,25 @@ RSpec.describe UsersController, type: :request do expect(response).to have_http_status(:unauthorized) end end + + describe "#search" do + let(:parent_relationship) { create(:organisation_relationship, parent_organisation: user.organisation) } + let(:child_relationship) { create(:organisation_relationship, child_organisation: user.organisation) } + let!(:org_user) { create(:user, organisation: user.organisation, name: "test_name") } + let!(:managing_user) { create(:user, organisation: parent_relationship.child_organisation, name: "managing_agent_test_name") } + + before do + create(:user, organisation: child_relationship.parent_organisation, name: "stock_owner_test_name") + create(:user, name: "other_organisation_test_name") + end + + it "only searches within the current user's organisation and managing agents" do + get "/users/search", headers:, params: { query: "test_name" } + result = JSON.parse(response.body) + expect(result.count).to eq(2) + expect(result.keys).to match_array([org_user.id.to_s, managing_user.id.to_s]) + end + end end context "when user is signed in as a data coordinator" do @@ -1174,6 +1200,25 @@ RSpec.describe UsersController, type: :request do expect(response).to have_http_status(:unauthorized) end end + + describe "#search" do + let(:parent_relationship) { create(:organisation_relationship, parent_organisation: user.organisation) } + let(:child_relationship) { create(:organisation_relationship, child_organisation: user.organisation) } + let!(:org_user) { create(:user, organisation: user.organisation, email: "test_name@example.com") } + let!(:managing_user) { create(:user, organisation: parent_relationship.child_organisation, email: "managing_agent_test_name@example.com") } + + before do + create(:user, email: "other_organisation_test_name@example.com") + create(:user, organisation: child_relationship.parent_organisation, email: "stock_owner_test_name@example.com") + end + + it "only searches within the current user's organisation and managing agents" do + get "/users/search", headers:, params: { query: "test_name" } + result = JSON.parse(response.body) + expect(result.count).to eq(2) + expect(result.keys).to match_array([org_user.id.to_s, managing_user.id.to_s]) + end + end end context "when user is signed in as a support user" do @@ -2111,6 +2156,22 @@ RSpec.describe UsersController, type: :request do expect(page).not_to have_link("User to be deleted") end end + + describe "#search" do + let(:parent_relationship) { create(:organisation_relationship, parent_organisation: user.organisation) } + let(:child_relationship) { create(:organisation_relationship, child_organisation: user.organisation) } + let!(:org_user) { create(:user, organisation: user.organisation, name: "test_name") } + let!(:managing_user) { create(:user, organisation: child_relationship.parent_organisation, name: "stock_owner_test_name") } + let!(:owner_user) { create(:user, organisation: parent_relationship.child_organisation, name: "managing_agent_test_name") } + let!(:other_user) { create(:user, name: "other_organisation_test_name") } + + it "searches all users" do + get "/users/search", headers:, params: { query: "test_name" } + result = JSON.parse(response.body) + expect(result.count).to eq(4) + expect(result.keys).to match_array([org_user.id.to_s, managing_user.id.to_s, owner_user.id.to_s, other_user.id.to_s]) + end + end end describe "title link" do diff --git a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb index a8cfd0a79..e38396328 100644 --- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb @@ -686,7 +686,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do it "cannot be nulled" do parser.valid? - expect(parser.errors[:field_45]).to eq(["You must show the MHCLG privacy notice to the tenant before you can submit this log."]) + expect(parser.errors[:field_45]).to eq(["You must show the MHCLG privacy notice to the tenant before you can submit this log"]) end end end diff --git a/spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb index 32a3171a7..42a05e33c 100644 --- a/spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb @@ -747,7 +747,19 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do it "cannot be nulled" do parser.valid? - expect(parser.errors[:field_15]).to eq(["You must answer tenant has seen the privacy notice"]) + expect(parser.errors[:field_15]).to eq(["You must show or give the tenant access to the MHCLG privacy notice before you can submit this log"]) + end + end + + context "when there is a :skip_bu_error error" do + let(:managing_org) { create(:organisation, :with_old_visible_id, rent_periods: [4, 1]) } + let(:attributes) { valid_attributes.merge({ field_123: 3, field_128: 80 }) } + + it "does not add that error" do + parser.valid? + + expect(parser.log.errors.map(&:attribute).sort).to eql(%i[managing_organisation_id period]) + expect(parser.errors.map(&:attribute)).to eql(%i[field_123]) end end end diff --git a/spec/services/bulk_upload/sales/year2024/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2024/row_parser_spec.rb index 115995f3e..656ff7a2f 100644 --- a/spec/services/bulk_upload/sales/year2024/row_parser_spec.rb +++ b/spec/services/bulk_upload/sales/year2024/row_parser_spec.rb @@ -1042,12 +1042,21 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do describe "#field_18" do # data protection let(:attributes) { setup_section_params.merge({ field_18: nil }) } + before do + parser.valid? + end + context "when not answered" do it "returns a setup error" do - parser.valid? expect(parser.errors.where(:field_18, category: :setup)).to be_present end end + + context "when the privacy notice is not accepted" do + it "cannot be nulled" do + expect(parser.errors[:field_18]).to eq(["You must show or give the buyer access to the MHCLG privacy notice before you can submit this log"]) + end + end end [ diff --git a/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb b/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb index 3dea3ce92..637dfa3a9 100644 --- a/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb +++ b/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb @@ -33,7 +33,7 @@ RSpec.describe "bulk_upload_lettings_results/show.html.erb" do fragment = Capybara::Node::Simple.new(rendered) - expect(fragment.find_css("table tbody th").map(&:inner_text)).to eql(%w[Z100 AA100]) + expect(fragment.find_css("table tbody td").map(&:inner_text).values_at(0, 4)).to eql(%w[Z100 AA100]) end end end diff --git a/spec/views/bulk_upload_lettings_results/summary.html.erb_spec.rb b/spec/views/bulk_upload_lettings_results/summary.html.erb_spec.rb index 05e2dce85..ac0c1f82d 100644 --- a/spec/views/bulk_upload_lettings_results/summary.html.erb_spec.rb +++ b/spec/views/bulk_upload_lettings_results/summary.html.erb_spec.rb @@ -33,7 +33,7 @@ RSpec.describe "bulk_upload_lettings_results/summary.html.erb" do fragment = Capybara::Node::Simple.new(rendered) - expect(fragment.find_css("table tbody th").map(&:inner_text)).to eql(%w[Z100 AA100]) + expect(fragment.find_css("table tbody td").map(&:inner_text).values_at(0, 4)).to eql(%w[Z100 AA100]) end end end diff --git a/spec/views/bulk_upload_sales_results/show.html.erb_spec.rb b/spec/views/bulk_upload_sales_results/show.html.erb_spec.rb index 785d830b3..dc6751dc8 100644 --- a/spec/views/bulk_upload_sales_results/show.html.erb_spec.rb +++ b/spec/views/bulk_upload_sales_results/show.html.erb_spec.rb @@ -32,8 +32,7 @@ RSpec.describe "bulk_upload_sales_results/show.html.erb" do render fragment = Capybara::Node::Simple.new(rendered) - - expect(fragment.find_css("table tbody th").map(&:inner_text)).to eql(%w[Z100 AA100]) + expect(fragment.find_css("table tbody td").map(&:inner_text).values_at(0, 4)).to eql(%w[Z100 AA100]) end end end diff --git a/spec/views/bulk_upload_sales_results/summary.html.erb_spec.rb b/spec/views/bulk_upload_sales_results/summary.html.erb_spec.rb index 6c00e5adf..b3d9aa006 100644 --- a/spec/views/bulk_upload_sales_results/summary.html.erb_spec.rb +++ b/spec/views/bulk_upload_sales_results/summary.html.erb_spec.rb @@ -33,7 +33,7 @@ RSpec.describe "bulk_upload_sales_results/summary.html.erb" do fragment = Capybara::Node::Simple.new(rendered) - expect(fragment.find_css("table tbody th").map(&:inner_text)).to eql(%w[Z100 AA100]) + expect(fragment.find_css("table tbody td").map(&:inner_text).values_at(0, 4)).to eql(%w[Z100 AA100]) end end end