diff --git a/app/services/expired_users_deletion_service.rb b/app/services/expired_users_deletion_service.rb index ca0eb5d37..417baa851 100644 --- a/app/services/expired_users_deletion_service.rb +++ b/app/services/expired_users_deletion_service.rb @@ -1,7 +1,22 @@ class ExpiredUsersDeletionService + RETENTION_AFTER_NOTICE = 2.weeks + def self.process_expired - users = find_expired_user - users.find_each do |user| + delete_expired_users + send_inactive_close_to_expiration_notice + end + + def self.send_inactive_close_to_expiration_notice + expiring_users_to_notify.in_batches do |batch| + batch.each do |user| + UserMailer.notify_inactive_close_to_deletion(user).perform_later + end + batch.update_all(inactive_close_to_expiration_notice_sent_at: Time.zone.now.utc) + end + end + + def self.delete_expired_users + expiring_user_notified.find_each do |user| user.delete_and_keep_track_dossiers_also_delete_user(nil) end end @@ -14,4 +29,12 @@ class ExpiredUsersDeletionService .group('users.id') end # rubocop:enable DS/Unscoped + + def self.expiring_users_to_notify + expiring_users.where(inactive_close_to_expiration_notice_sent_at: nil) + end + + def self.expiring_user_notified + expiring_users.where.not(inactive_close_to_expiration_notice_sent_at: RETENTION_AFTER_NOTICE.ago..) + end end diff --git a/spec/services/expired_users_deletion_service_spec.rb b/spec/services/expired_users_deletion_service_spec.rb index 73d86178f..85e1ce2a4 100644 --- a/spec/services/expired_users_deletion_service_spec.rb +++ b/spec/services/expired_users_deletion_service_spec.rb @@ -3,26 +3,49 @@ describe ExpiredUsersDeletionService do before { user && dossier } describe '#process_expired' do - subject { ExpiredUsersDeletionService.process_expired } - context 'when user has a dossier created 1 year ago' do - let(:dossier) { create(:dossier, user:, created_at: 1.year.ago) } - it 'does not destroy anything' do - expect { subject }.not_to change { Dossier.count } - expect(user.reload).to be_truthy + context 'when user has not been notified' do + subject { ExpiredUsersDeletionService.process_expired } + + context 'when user has a dossier created 3 years ago' do + let(:dossier) { create(:dossier, user:, created_at: 3.years.ago) } + it 'update user.inactive_close_to_expiration_notice_sent_at ' do + expect(UserMailer).to receive(:notify_inactive_close_to_deletion).with(user).and_return(double(perform_later: true)) + expect { subject } + .to change { user.reload.inactive_close_to_expiration_notice_sent_at } + .from(nil).to(anything) + end end end - context 'when user has a dossier created 3 years ago' do - let(:dossier) { create(:dossier, user:, created_at: 3.years.ago) } - it 'destroys user and dossier' do - expect { subject }.to change { Dossier.count }.by(-1) - expect { user.reload }.to raise_error(ActiveRecord::RecordNotFound) + context 'when user has been notified 1 week ago' do + before { user.update(inactive_close_to_expiration_notice_sent_at: 1.week.ago) } + subject { ExpiredUsersDeletionService.process_expired } + + context 'when user has a dossier created 3 years ago' do + let(:dossier) { create(:dossier, user:, created_at: 3.years.ago) } + it 'do nothing' do + expect { subject }.not_to change { Dossier.count } + expect { user.reload }.not_to raise_error(ActiveRecord::RecordNotFound) + end + end + end + + context 'when user has been notified 3 weeks ago' do + before { user.update(inactive_close_to_expiration_notice_sent_at: 3.weeks.ago) } + subject { ExpiredUsersDeletionService.process_expired } + + context 'when user has a dossier created 3 years ago' do + let(:dossier) { create(:dossier, user:, created_at: 3.years.ago) } + it 'destroys user and dossier' do + expect { subject }.to change { Dossier.count }.by(-1) + expect { user.reload }.to raise_error(ActiveRecord::RecordNotFound) + end end end end - describe '#find_expired_user' do - subject { ExpiredUsersDeletionService.find_expired_user } + describe '#expiring_users' do + subject { ExpiredUsersDeletionService.expiring_users } context 'when user has no dossiers (TODO: just drop all user without dossier, no need to alert them)' do let(:dossier) { nil }