diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index e55ee10d6..7535bd142 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -6,13 +6,15 @@ class LocationsController < ApplicationController before_action :find_location, except: %i[create index] before_action :find_scheme before_action :scheme_and_location_present, except: %i[create index] + before_action :session_filters, if: :current_user, only: %i[index] + before_action -> { filter_manager.serialize_filters_to_session }, if: :current_user, only: %i[index] before_action :authorize_user, except: %i[index create] def index authorize @scheme - @pagy, @locations = pagy(filtered_collection(@scheme.locations, search_term)) + @pagy, @locations = pagy(filter_manager.filtered_locations(@scheme.locations, search_term, session_filters)) @total_count = @scheme.locations.size @searched = search_term.presence end @@ -297,4 +299,12 @@ private params[:referrer] == "check_answers" end helper_method :return_to_check_your_answers? + + def filter_manager + FilterManager.new(current_user:, session:, params:, filter_type: "locations") + end + + def session_filters + filter_manager.session_filters + end end diff --git a/app/models/location.rb b/app/models/location.rb index 0dd6ba522..8fe580ee8 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -27,6 +27,7 @@ class Location < ApplicationRecord scope :active_in_2_weeks, -> { where(confirmed: true).and(started_in_2_weeks) } scope :confirmed, -> { where(confirmed: true) } scope :unconfirmed, -> { where.not(confirmed: true) } + scope :filter_by_status, ->(status, _user = nil) { where status: } LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h @@ -98,6 +99,10 @@ class Location < ApplicationRecord :active end + def self.filter_by_status(statuses, _user = nil) + where(id: all.select { |record| statuses.include?(record.status.to_s) }) + end + def active? status == :active end diff --git a/app/services/filter_manager.rb b/app/services/filter_manager.rb index 63b13ecdc..6da12ed56 100644 --- a/app/services/filter_manager.rb +++ b/app/services/filter_manager.rb @@ -62,6 +62,17 @@ class FilterManager schemes end + def self.filter_locations(locations, search_term, filters, user) + locations = filter_by_search(locations, search_term) + + filters.each do |category, values| + next if Array(values).reject(&:empty?).blank? + + locations = locations.public_send("filter_by_#{category}", values, user) + end + locations.order(created_at: :desc) + end + def serialize_filters_to_session(specific_org: false) session[session_name_for(filter_type)] = session_filters(specific_org:).to_json end @@ -86,7 +97,7 @@ class FilterManager new_filters["user"] = current_user.id.to_s if params["assigned_to"] == "you" end - if (filter_type.include?("schemes") || filter_type.include?("users")) && params["status"].present? + if (filter_type.include?("schemes") || filter_type.include?("users") || filter_type.include?("locations")) && params["status"].present? new_filters["status"] = params["status"] end @@ -117,6 +128,10 @@ class FilterManager FilterManager.filter_schemes(schemes, search_term, filters, current_user, all_orgs) end + def filtered_locations(locations, search_term, filters) + FilterManager.filter_locations(locations, search_term, filters, current_user) + end + def bulk_upload id = (logs_filters["bulk_upload_id"] || []).reject(&:blank?)[0] @bulk_upload ||= current_user.bulk_uploads.find_by(id:) diff --git a/spec/factories/location.rb b/spec/factories/location.rb index f43da0ac8..00fa0d77f 100644 --- a/spec/factories/location.rb +++ b/spec/factories/location.rb @@ -21,6 +21,11 @@ FactoryBot.define do old_visible_id { "111" } end + trait :incomplete do + units { nil } + confirmed { false } + end + trait :with_old_visible_id do old_visible_id { rand(9_999_999).to_s } end diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb index 52b1c087f..5d31fee2f 100644 --- a/spec/requests/locations_controller_spec.rb +++ b/spec/requests/locations_controller_spec.rb @@ -119,6 +119,49 @@ RSpec.describe LocationsController, type: :request do it "returns 200" do expect(response).to be_successful end + + context "when filtering" do + context "with status filter" do + let(:scheme) { create(:scheme, owning_organisation: user.organisation) } + let!(:incomplete_location) { create(:location, :incomplete, scheme:, startdate: Time.zone.local(2022, 4, 1)) } + let!(:active_location) { create(:location, scheme:, startdate: Time.zone.local(2022, 4, 1)) } + + it "shows locations for multiple selected statuses" do + get "/schemes/#{scheme.id}/locations?status[]=incomplete&status[]=active", headers:, params: {} + expect(page).to have_link(incomplete_location.postcode) + expect(page).to have_link(active_location.postcode) + end + + it "shows filtered incomplete locations" do + get "/schemes/#{scheme.id}/locations?status[]=incomplete", headers:, params: {} + expect(page).to have_link(incomplete_location.postcode) + expect(page).not_to have_link(active_location.postcode) + end + + it "shows filtered active locations" do + get "/schemes/#{scheme.id}/locations?status[]=active", headers:, params: {} + expect(page).to have_link(active_location.postcode) + expect(page).not_to have_link(incomplete_location.postcode) + end + + xit "shows filtered deactivated locations" do + get "/schemes/#{scheme.id}/locations?status[]=deactivated", headers:, params: {} + expect(page).to have_link(deactivated_location.postcode) + expect(page).not_to have_link(active_location.postcode) + expect(page).not_to have_link(incomplete_location.postcode) + end + + it "does not reset the filters" do + get "/schemes/#{scheme.id}/locations?status[]=incomplete", headers:, params: {} + expect(page).to have_link(incomplete_location.postcode) + expect(page).not_to have_link(active_location.postcode) + + get "/schemes/#{scheme.id}/locations", headers:, params: {} + expect(page).to have_link(incomplete_location.postcode) + expect(page).not_to have_link(active_location.postcode) + end + end + end end context "when signed in as a data coordinator user" do