From ef775f6ee53a29e8e1c817bb97aff7492e5a440f Mon Sep 17 00:00:00 2001 From: Nils Rauch Date: Mon, 16 Oct 2023 12:51:51 +0200 Subject: [PATCH] Add cleanup finder adjustments --- app/domain/youth/people/cleanup_finder.rb | 23 ++ lib/hitobito_youth/wagon.rb | 1 + spec/domain/people/cleanup_finder_spec.rb | 290 ++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 app/domain/youth/people/cleanup_finder.rb create mode 100644 spec/domain/people/cleanup_finder_spec.rb diff --git a/app/domain/youth/people/cleanup_finder.rb b/app/domain/youth/people/cleanup_finder.rb new file mode 100644 index 00000000..472880a2 --- /dev/null +++ b/app/domain/youth/people/cleanup_finder.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + +module Youth::People::CleanupFinder + + def run + Person.where(id: super.map(&:id)).left_joins(:people_manageds).where(no_people_manageds_exist).distinct + end + + private + + def no_people_manageds_exist + people_manageds.arel.exists.not + end + + def people_manageds + PeopleManager.where('people_managers.manager_id = people.id') + end +end diff --git a/lib/hitobito_youth/wagon.rb b/lib/hitobito_youth/wagon.rb index 77b4f444..dc729b0f 100644 --- a/lib/hitobito_youth/wagon.rb +++ b/lib/hitobito_youth/wagon.rb @@ -44,6 +44,7 @@ class Wagon < Rails::Engine Export::Tabular::Events::Row.include Youth::Export::Tabular::Events::Row Person::AddRequest::Approver::Event.include Youth::Person::AddRequest::Approver::Event People::Merger.prepend Youth::People::Merger + People::CleanupFinder.prepend Youth::People::CleanupFinder MailRelay::AddressList.include Youth::MailRelay::AddressList Messages::BulkMail::AddressList.include Youth::Messages::BulkMail::AddressList Synchronize::Mailchimp::Subscriber.prepend Youth::Synchronize::Mailchimp::Subscriber diff --git a/spec/domain/people/cleanup_finder_spec.rb b/spec/domain/people/cleanup_finder_spec.rb new file mode 100644 index 00000000..7dff8036 --- /dev/null +++ b/spec/domain/people/cleanup_finder_spec.rb @@ -0,0 +1,290 @@ +# frozen_string_literal: true + +# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of +# hitobito and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + +require 'spec_helper' + +describe People::CleanupFinder do + + let(:people_without_roles) { 3.times.map { Fabricate(:person) } } + let(:people_with_expired_roles) { 3.times.map { Fabricate(Group::BottomGroup::Member.name.to_sym, + group: groups(:bottom_group_one_one), + created_at: 11.months.ago, + deleted_at: 10.months.ago).person } } + let(:people_with_roles) { 3.times.map { Fabricate(Group::BottomGroup::Member.name.to_sym, + group: groups(:bottom_group_one_one)).person } } + + subject { People::CleanupFinder.new.run } + context '#run' do + context 'people with expired roles outside cutoff duration' do + let!(:people) { people_with_expired_roles } + + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_roles).and_return(9) + end + + context 'with people_manageds' do + before do + people.each do |p| + p.manageds = [Fabricate(:person)] + end + end + + context 'with current_sign_in_at outside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 13.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the future' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.from_now)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the past' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.ago)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at nil' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + + people.each { |p| p.update!(current_sign_in_at: nil) } + end + + it 'does not finds them' do + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at inside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 11.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + end + + context 'without people_manageds' do + context 'with current_sign_in_at outside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 13.months.ago) } + end + + it 'finds them' do + expect(subject).to match_array(people) + end + + it 'does not find them with event participation in the future' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.from_now)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + + it 'finds them with event participation in the past' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.ago)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to match_array(people) + end + end + + context 'with current_sign_in_at nil' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + + people.each { |p| p.update!(current_sign_in_at: nil) } + end + + it 'finds them' do + expect(subject).to match_array(people) + end + end + + context 'with current_sign_in_at inside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 11.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + end + end + + context 'people with expired roles inside cutoff duration' do + let!(:people) { people_with_expired_roles } + + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_roles).and_return(12) + end + + context 'with people_manageds' do + before do + people.each do |p| + p.manageds = [Fabricate(:person)] + end + end + + context 'with current_sign_in_at outside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 13.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the future' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.from_now)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the past' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.ago, finish_at: 5.days.ago)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at nil' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + + people.each { |p| p.update!(current_sign_in_at: nil) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at inside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 11.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + end + + context 'without people_manageds' do + context 'with current_sign_in_at outside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 13.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the future' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.from_now)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + + it 'does not find them with event participation in the past' do + event = Fabricate(:event, dates: [Event::Date.new(start_at: 10.days.ago, finish_at: 5.days.ago)]) + people.each do |p| + Event::Participation.create!(event: event, person: p) + end + + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at nil' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + + people.each { |p| p.update!(current_sign_in_at: nil) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + + context 'with current_sign_in_at inside cutoff duration' do + before do + expect(Settings.people.cleanup_cutoff_duration).to receive(:regarding_current_sign_in_at).and_return(12) + people.each { |p| p.update!(current_sign_in_at: 11.months.ago) } + end + + it 'does not find them' do + expect(subject).to_not match_array(people) + end + end + end + end + + context 'with people_manageds' do + it 'does not find people without any roles' do + people_without_roles.each do |p| + p.manageds += [Fabricate(:person)] + end + expect(subject).to_not match_array(people_without_roles) + end + + it 'does not find people with active roles' do + people_with_roles.each do |p| + p.manageds += [Fabricate(:person)] + end + expect(subject).to_not match_array(people_with_roles) + end + end + end +end