From 5229160408bd43b2b6d315fbc9ac766f7fece68a Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 3 Nov 2023 12:13:41 +0100 Subject: [PATCH] amelioration(ExpiredUsersDeletionService.process_expired): supprime aussi les usagers qui n'ont plus de dossiers sur la plateforme --- .../expired_users_deletion_service.rb | 36 +++++--- .../expired_users_deletion_service_spec.rb | 87 ++++++++++++++----- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/app/services/expired_users_deletion_service.rb b/app/services/expired_users_deletion_service.rb index 64db88a23..a54713f80 100644 --- a/app/services/expired_users_deletion_service.rb +++ b/app/services/expired_users_deletion_service.rb @@ -1,13 +1,18 @@ class ExpiredUsersDeletionService + def self.expirable_after + 2.years.ago + end RETENTION_AFTER_NOTICE_IN_WEEK = 2 def self.process_expired - delete_expired_users - send_inactive_close_to_expiration_notice + [expiring_users_without_dossiers, expiring_users_with_dossiers].map do |expiring_segment| + delete_expired_users(expiring_segment) + send_inactive_close_to_expiration_notice(expiring_segment) + end end - def self.send_inactive_close_to_expiration_notice - expiring_users_to_notify.in_batches do |batch| + def self.send_inactive_close_to_expiration_notice(users) + to_notify_only(users).in_batches do |batch| batch.each do |user| UserMailer.notify_inactive_close_to_deletion(user).perform_later end @@ -15,26 +20,33 @@ class ExpiredUsersDeletionService end end - def self.delete_expired_users - expiring_user_notified.find_each do |user| + def self.delete_expired_users(users) + to_delete_only(users).find_each do |user| user.delete_and_keep_track_dossiers_also_delete_user(nil) end end # rubocop:disable DS/Unscoped - def self.expiring_users + def self.expiring_users_with_dossiers User.unscoped # avoid default_scope eager_loading :export, :instructeur, :administrateur .joins(:dossiers) - .having('MAX(dossiers.created_at) < ?', 2.years.ago) + .having('MAX(dossiers.created_at) < ?', EXPIRABLE_AFTER) .group('users.id') end + + def self.expiring_users_without_dossiers + User.unscoped + .where + .missing(:dossiers) + .where(last_sign_in_at: ..EXPIRABLE_AFTER) + end # rubocop:enable DS/Unscoped - def self.expiring_users_to_notify - expiring_users.where(inactive_close_to_expiration_notice_sent_at: nil) + def self.to_notify_only(users) + 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_IN_WEEK.weeks.ago..) + def self.to_delete_only(users) + users.where.not(inactive_close_to_expiration_notice_sent_at: RETENTION_AFTER_NOTICE_IN_WEEK.weeks.ago..) end end diff --git a/spec/services/expired_users_deletion_service_spec.rb b/spec/services/expired_users_deletion_service_spec.rb index 85e1ce2a4..9b6a71e2d 100644 --- a/spec/services/expired_users_deletion_service_spec.rb +++ b/spec/services/expired_users_deletion_service_spec.rb @@ -1,13 +1,13 @@ describe ExpiredUsersDeletionService do - let(:user) { create(:user) } before { user && dossier } - describe '#process_expired' do - context 'when user has not been notified' do - subject { ExpiredUsersDeletionService.process_expired } + context 'when user has an expirable dossier' do + let(:dossier) { create(:dossier, user:, created_at: 3.years.ago) } + + context 'when user was not notified' do + let(:user) { create(:user, inactive_close_to_expiration_notice_sent_at: nil) } + 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 } @@ -15,43 +15,84 @@ describe ExpiredUsersDeletionService do .from(nil).to(anything) end end - end - 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 'user has been notified 1 week ago' do + let(:user) { create(:user, 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 'user has been notified 3 weeks ago' do + let(:user) { create(:user, 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 + + context 'when user is expirable' do + let(:dossier) { nil } + + context 'when user was not notified' do + let(:user) { create(:user, last_sign_in_at: 3.years.ago, inactive_close_to_expiration_notice_sent_at: nil) } + subject { ExpiredUsersDeletionService.process_expired } + + 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 + + context 'when user has been notified 1 week ago' do + let(:user) { create(:user, last_sign_in_at: 3.years.ago, inactive_close_to_expiration_notice_sent_at: 1.week.ago) } + subject { ExpiredUsersDeletionService.process_expired } + + it 'do nothing' do + expect { subject }.not_to change { Dossier.count } + expect { user.reload }.not_to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'when user has been notified 3 weeks ago' do + let(:user) { create(:user, last_sign_in_at: 3.years.ago, inactive_close_to_expiration_notice_sent_at: 3.weeks.ago) } + subject { ExpiredUsersDeletionService.process_expired } + + it 'destroys user and dossier' do + subject + expect { user.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end end - describe '#expiring_users' do - subject { ExpiredUsersDeletionService.expiring_users } + describe '#expiring_users_without_dossiers' do + let(:dossier) { nil } + subject { ExpiredUsersDeletionService.expiring_users_without_dossiers } - context 'when user has no dossiers (TODO: just drop all user without dossier, no need to alert them)' do - let(:dossier) { nil } - xit { is_expected.to include(user) } + context 'when user last_sign_in_at is 1 year ago and has no dossier' do + let(:user) { create(:user, last_sign_in_at: 1.year.ago) } + it { is_expected.not_to include(user) } end + context 'when user last_sign_in_at is 3 year ago and has no dossier' do + let(:user) { create(:user, last_sign_in_at: 3.years.ago) } + it { is_expected.to include(user) } + end + end + + describe '#expiring_users_with_dossiers' do + let(:user) { create(:user) } + subject { ExpiredUsersDeletionService.expiring_users_with_dossiers } + context 'when user has a dossier created 1 year ago' do let(:dossier) { create(:dossier, user:, created_at: 1.year.ago) } it { is_expected.not_to include(user) }