diff --git a/app/controllers/admin/deduplicate_patients_controller.rb b/app/controllers/admin/deduplicate_patients_controller.rb index 0cbd71d60e..f9291a8244 100644 --- a/app/controllers/admin/deduplicate_patients_controller.rb +++ b/app/controllers/admin/deduplicate_patients_controller.rb @@ -1,18 +1,31 @@ class Admin::DeduplicatePatientsController < AdminController skip_before_action :verify_authenticity_token + before_action :set_filter_options, only: [:show], if: :filter_enabled? DUPLICATE_LIMIT = 250 def show facilities = current_admin.accessible_facilities(:manage) authorize { facilities.any? } + # Apply facility filter if selected and feature flag is enabled + filtered_facilities = if filter_enabled? && @selected_facility.present? + facilities.where(id: @selected_facility.id) + elsif filter_enabled? && @selected_district.present? + facilities.where(id: @selected_district.facilities) + else + facilities + end + # Scoping by facilities is costly for users who have a lot of facilities - duplicate_patient_ids = if current_admin.accessible_organizations(:manage).any? + use_all_organizations = current_admin.accessible_organizations(:manage).any? && + (!filter_enabled? || (!@selected_district.present? && !@selected_facility.present?)) + + duplicate_patient_ids = if use_all_organizations PatientDeduplication::Strategies.identifier_excluding_full_name_match(limit: DUPLICATE_LIMIT) else PatientDeduplication::Strategies.identifier_excluding_full_name_match_for_facilities( limit: DUPLICATE_LIMIT, - facilities: facilities + facilities: filtered_facilities ) end @@ -44,4 +57,42 @@ def can_admin_deduplicate_patients?(patients) .where(id: patients.pluck(:assigned_facility_id)) .any? end + + private + + def set_filter_options + @accessible_facilities = current_admin.accessible_facilities(:manage) + populate_districts + set_selected_district + populate_facilities + set_selected_facility + end + + def populate_districts + @districts = Region.district_regions + .joins("INNER JOIN regions facility_region ON regions.path @> facility_region.path") + .where("facility_region.source_id" => @accessible_facilities.map(&:id)) + .distinct(:slug) + .order(:name) + end + + def set_selected_district + @selected_district = if params[:district_slug].present? + @districts.find_by(slug: params[:district_slug]) + elsif @districts.present? + @districts.first + end + end + + def populate_facilities + @facilities = @accessible_facilities.where(id: @selected_district&.facilities).order(:name) + end + + def set_selected_facility + @selected_facility = @facilities.find_by(id: params[:facility_id]) if params[:facility_id].present? + end + + def filter_enabled? + Flipper.enabled?(:patient_deduplication_filter, current_admin) + end end diff --git a/app/views/admin/deduplicate_patients/show.html.erb b/app/views/admin/deduplicate_patients/show.html.erb index 5532fb1bd9..1aa2584a75 100644 --- a/app/views/admin/deduplicate_patients/show.html.erb +++ b/app/views/admin/deduplicate_patients/show.html.erb @@ -1,4 +1,38 @@

Merge duplicate patients

+ +<% if Flipper.enabled?(:patient_deduplication_filter, current_admin) %> + <%= bootstrap_form_with(url: admin_deduplication_path, method: :get, layout: :horizontal, class: "mb-4") do |form| %> + <% html_select_options = { onchange: "this.form.submit();" } + searchable_select_options = html_select_options.merge(class: "selectpicker", data: {live_search: true}) %> +
+
+ <%= form.select :district_slug, + @districts.order(:name).map { |district| [district.name, district.slug] }, + { + hide_label: true, + selected: @selected_district&.slug, + wrapper: false + }, + searchable_select_options + %> +
+
+ <%= form.select :facility_id, + @facilities.order(:name).map { |facility| [facility.label_with_district, facility.id] }, + { + hide_label: true, + include_blank: "All facilities", + selected: @selected_facility&.id, + wrapper: false + }, + searchable_select_options + %> +
+
+ <%= form.submit "Filter", style: "display: none" %> + <% end %> +<% end %> +

<% if @duplicate_count == Admin::DeduplicatePatientsController::DUPLICATE_LIMIT %>