diff --git a/app/javascript/components/record-actions/bulk-transtions/reducer.js b/app/javascript/components/record-actions/bulk-transtions/reducer.js index 5cd9860b7b..21ea2890e9 100644 --- a/app/javascript/components/record-actions/bulk-transtions/reducer.js +++ b/app/javascript/components/record-actions/bulk-transtions/reducer.js @@ -27,7 +27,8 @@ export default namespace => return state .setIn([NAMESPACE, "loading"], false) .setIn([NAMESPACE, "data"], fromJS([])) - .setIn([NAMESPACE, "errors"], fromJS([])); + .setIn([NAMESPACE, "errors"], fromJS([])) + .setIn([NAMESPACE, "selectedRecordsLength"], 0); case `${namespace}/${actions.BULK_ASSIGN_USER_SELECTED_RECORDS_LENGTH}`: return state.setIn([NAMESPACE, "selectedRecordsLength"], fromJS(payload.selectedRecordsLength, 0)); default: diff --git a/app/javascript/components/record-actions/transitions/components/reassign-form.jsx b/app/javascript/components/record-actions/transitions/components/reassign-form.jsx index dc2770ab47..80586ffc8d 100644 --- a/app/javascript/components/record-actions/transitions/components/reassign-form.jsx +++ b/app/javascript/components/record-actions/transitions/components/reassign-form.jsx @@ -17,7 +17,6 @@ import SearchableSelect from "../../../searchable-select"; import { enqueueSnackbar } from "../../../notifier"; import { useI18n } from "../../../i18n"; import { applyFilters } from "../../../index-filters/action-creators"; -import { DEFAULT_FILTERS } from "../../../record-list/constants"; import { filterUsers } from "../utils"; import { useMemoizedSelector } from "../../../../libs"; import { getFiltersValuesByRecordType } from "../../../index-filters/selectors"; @@ -128,7 +127,7 @@ const ReassignForm = ({ dispatch( applyFilters({ recordType, - data: DEFAULT_FILTERS + data: appliedFilters }) ); }; diff --git a/app/models/assign.rb b/app/models/assign.rb index c5404c0e29..d5d3c8e12d 100644 --- a/app/models/assign.rb +++ b/app/models/assign.rb @@ -7,6 +7,8 @@ class Assign < Transition MAX_BULK_RECORDS = 100 + attr_accessor :from_bulk_export + def perform return if transitioned_to_user.nil? @@ -25,4 +27,8 @@ def consent_given? def notified_statuses [Transition::STATUS_DONE] end + + def should_notify? + !from_bulk_export && super + end end diff --git a/app/models/child.rb b/app/models/child.rb index 8b1a098f4d..8740f67e38 100644 --- a/app/models/child.rb +++ b/app/models/child.rb @@ -110,7 +110,7 @@ def self.alert_count_self(current_user) "INNER JOIN transitions ON transitions.record_type = 'Child' AND (transitions.record_id)::uuid = cases.id" ).where(transitions: { - type: Referral.name, + type: [Referral.name, Transfer.name], status: [Transition::STATUS_INPROGRESS, Transition::STATUS_ACCEPTED], transitioned_to: current_user.user_name }).ids diff --git a/app/models/managed_reports/indicators/verified_information_violations.rb b/app/models/managed_reports/indicators/verified_information_violations.rb index 72f9d9ddaa..89ea15d5de 100644 --- a/app/models/managed_reports/indicators/verified_information_violations.rb +++ b/app/models/managed_reports/indicators/verified_information_violations.rb @@ -26,6 +26,7 @@ def sql(current_user, params = {}) OR violations.data ->> 'type' = 'attack_on_schools' OR violations.data ->> 'type' = 'denial_humanitarian_access') and violations.data->>'ctfmr_verified' = 'verified' + and violations.data ->> 'is_late_verification' != 'true' #{date_range_query(date_filter_param(params['ghn_date_filter']), 'violations')&.prepend('and ')} GROUP BY violations.data ->> 'type' diff --git a/app/models/transition.rb b/app/models/transition.rb index 084df3e2b2..11f79b43ce 100644 --- a/app/models/transition.rb +++ b/app/models/transition.rb @@ -94,11 +94,15 @@ def notified_statuses end def notify - return unless notified_statuses.include?(status) + return unless should_notify? TransitionNotifyJob.perform_later(id) end + def should_notify? + notified_statuses.include?(status) + end + def index_record Sunspot.index(record) if record end diff --git a/app/services/bulk_assign_service.rb b/app/services/bulk_assign_service.rb index 65f35f9764..31518ed483 100644 --- a/app/services/bulk_assign_service.rb +++ b/app/services/bulk_assign_service.rb @@ -11,7 +11,15 @@ def initialize(model_class, transitioned_by, args) end def assign_records! - search_results.each do |record| + Child.where(id: search_results_ids).find_in_batches(batch_size: 10) do |records| + assign_records_batch(records) + end + end + + private + + def assign_records_batch(records) + records.each do |record| next unless @transitioned_by.can_assign?(record) create_assignment(record) @@ -21,21 +29,20 @@ def assign_records! end end - private - def create_assignment(record) Assign.create!( record:, transitioned_to: @args[:transitioned_to], transitioned_by: @transitioned_by.user_name, - notes: @args[:notes] + notes: @args[:notes], + from_bulk_export: true ) end - def search_results + def search_results_ids SearchService.search( @model_class, query:, filters: search_filters, pagination: { page: 1, per_page: Assign::MAX_BULK_RECORDS } - ).results + ).hits.map(&:primary_key) end def query diff --git a/config/initializers/generate_options.rb b/config/initializers/generate_options.rb index 198f13d4ed..0db32efcac 100644 --- a/config/initializers/generate_options.rb +++ b/config/initializers/generate_options.rb @@ -18,7 +18,8 @@ .rows.flatten.first count_system_settings.positive? && count_locations.positive? && GenerateLocationFilesService.generate end - rescue ActiveRecord::NoDatabaseError => e + rescue StandardError => e + Rails.logger.error 'Locations options not generated' Rails.logger.error e.message end end diff --git a/config/locales/en.yml b/config/locales/en.yml index fb94c626e1..6bcfba96cc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2652,6 +2652,7 @@ en: label: Export Photowall export_unhcr_csv: label: Export UNHCR CSV + explanation: DEPRECATED - This feature is no longer in use. export_xls: explanation: 'User can generate a XLS file export from the case list or case show pages, which contains all fields to which the current user @@ -3140,6 +3141,13 @@ en: label: Forms - Registry family: label: Forms - Family + explanation: 'Limiting a user''s access to forms for Families limits + which information the user can see on a family. For instance, if the + user only has access to the Record Owner form, they will also only be + able to see the information contained in the fields on that form. If the + current user has limited form access and has the ability to manage the + form configuration, limiting their form access also limits which forms + they can configure.' group: actions: admin_only: @@ -3501,6 +3509,8 @@ en: label: Export PDF export_custom: label: Export custom + explanation: User can select specific forms or fields from the Family list or + Family show pages to export to an XLS file. flag: explanation: Ability to add a flag to a Family. Users with this permission can also remove the flags that they have added to a Family. diff --git a/spec/jobs/bulk_assign_records_spec.rb b/spec/jobs/bulk_assign_records_spec.rb index 90e63c65ad..5639f071a2 100644 --- a/spec/jobs/bulk_assign_records_spec.rb +++ b/spec/jobs/bulk_assign_records_spec.rb @@ -32,6 +32,10 @@ disclosure_other_orgs: true, module_id: PrimeroModule::CP) end + before :each do + BulkAssignService.any_instance.stub(:search_results).and_return([child]) + end + describe 'perform_later' do before do ActiveJob::Base.queue_adapter = :test @@ -53,6 +57,26 @@ end end + describe 'when job is performed' do + let(:bulk_assign_params) do + { + transitioned_to: user2.user_name, + transitioned_by: user.user_name, + notes: 'this is a note', + filters: { short_id: [child.short_id] } + } + end + + it 'should not enqueue a TransitionNotifyJob' do + ActiveJob::Base.queue_adapter = :test + BulkAssignRecordsJob.perform_now(Child, user, **bulk_assign_params) + + expect( + ActiveJob::Base.queue_adapter.enqueued_jobs.select { |j| j[:job] == TransitionNotifyJob }.size + ).to eq(0) + end + end + after :each do clean_data(User, Role, PrimeroModule, PrimeroProgram, Field, FormSection, UserGroup, Agency, Child, Transition) end diff --git a/spec/models/assign_spec.rb b/spec/models/assign_spec.rb index 3573ea704a..a00b3f0219 100644 --- a/spec/models/assign_spec.rb +++ b/spec/models/assign_spec.rb @@ -5,6 +5,8 @@ require 'rails_helper' describe Assign do + include ActiveJob::TestHelper + before do clean_data(User, Role, PrimeroModule, UserGroup, Agency, Transition, Incident, Child) @@ -150,6 +152,28 @@ end end end + + describe '.notify' do + context 'when should_notify? is true' do + it 'should enqueue a TransitionNotifyJob' do + expect( + ActiveJob::Base.queue_adapter.enqueued_jobs.select { |j| j[:job] == TransitionNotifyJob }.size + ).to eq(1) + end + end + context 'when should_notify? is false' do + before do + clear_enqueued_jobs + Assign.create!(transitioned_by: 'user1', transitioned_to: 'user2', record: @case, from_bulk_export: true) + end + + it 'should enqueue a TransitionNotifyJob' do + expect( + ActiveJob::Base.queue_adapter.enqueued_jobs.select { |j| j[:job] == TransitionNotifyJob }.size + ).to eq(0) + end + end + end end context 'and the user has permission within the user group' do diff --git a/spec/models/concerns/alertable_spec.rb b/spec/models/concerns/alertable_spec.rb index 8a178a4d42..46375ec692 100644 --- a/spec/models/concerns/alertable_spec.rb +++ b/spec/models/concerns/alertable_spec.rb @@ -62,7 +62,10 @@ permissions: [ Permission.new( resource: Permission::CASE, - actions: [Permission::MANAGE, Permission::REFERRAL, Permission::RECEIVE_REFERRAL] + actions: [ + Permission::MANAGE, Permission::REFERRAL, Permission::RECEIVE_REFERRAL, + Permission::TRANSFER, Permission::RECEIVE_TRANSFER + ] ) ], modules: [cp] @@ -237,6 +240,37 @@ end end + context 'Count alert from transferred cases' do + before do + Transfer.create!( + transitioned_by: 'test_user_2', transitioned_to: 'test_user_4', record: @test_class, + type: Transfer.name, consent_overridden: true + ) + child_tranferred = Child.create(name: 'bar', data: { owned_by: @user_c.user_name, module_id: 'primeromodule-cp' }) + Transfer.create!( + transitioned_by: 'test_user_3', transitioned_to: 'test_user_1', record: child_tranferred, + type: Transfer.name, consent_overridden: true + ) + end + + it 'count alert from self permissions users that has owned and transferred' do + expect(Child.alert_count(@user_a)).to eq(2) + expect(Child.alert_count_self(@user_a)).to eq(2) + end + + it 'count alert from self permissions users' do + expect(Child.alert_count(@user_d)).to eq(1) + end + + it 'count alert from user group' do + expect(Child.alert_count(@user_c)).to eq(3) + end + + it 'count alert from user agency' do + expect(Child.alert_count(@user_b)).to eq(3) + end + end + after do clean_data( SystemSettings, Alert, User, Role, Agency, Child, UserGroup, diff --git a/spec/models/managed_reports/indicators/verified_information_violations_spec.rb b/spec/models/managed_reports/indicators/verified_information_violations_spec.rb index 96b98b66c5..55506e1b68 100644 --- a/spec/models/managed_reports/indicators/verified_information_violations_spec.rb +++ b/spec/models/managed_reports/indicators/verified_information_violations_spec.rb @@ -32,6 +32,13 @@ incident_id: incident.id ) + Violation.create!( + data: { type: 'attack_on_schools', ctfmr_verified: 'verified', + ctfmr_verified_date: Date.new(2021, 7, 31), + violation_tally: { boys: 1, girls: 1, unknown: 1, total: 3 } }, + incident_id: incident.id + ) + Violation.create!( data: { type: 'killing', ctfmr_verified_date: Date.new(2021, 5, 23), diff --git a/spec/services/bulk_assign_service_spec.rb b/spec/services/bulk_assign_service_spec.rb index e60c4d6c36..f102f481d4 100644 --- a/spec/services/bulk_assign_service_spec.rb +++ b/spec/services/bulk_assign_service_spec.rb @@ -45,7 +45,8 @@ { transitioned_to: user2.user_name, transitioned_by: user.user_name, - notes: 'this is a note' + notes: 'this is a note', + from_bulk_export: true } end @@ -56,7 +57,7 @@ end before :each do - BulkAssignService.any_instance.stub(:search_results).and_return([child, child2, child3]) + BulkAssignService.any_instance.stub(:search_results_ids).and_return([child.id, child2.id, child3.id]) end it 'creates an Transition record' do