remove admin from manager

This commit is contained in:
Christophe Robillard 2023-10-05 11:23:46 +02:00
parent 870efba29b
commit 0b7d4452fd
6 changed files with 164 additions and 6 deletions

View file

@ -22,10 +22,15 @@ module Manager
def delete
administrateur = Administrateur.find(params[:id])
administrateur.delete_and_transfer_services
result = AdministrateurDeletionService.new(current_super_admin, administrateur).call
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_super_admin.id}")
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
case result
in Dry::Monads::Result::Success
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_super_admin.id}")
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
in Dry::Monads::Result::Failure(reason)
flash[:alert] = I18n.t(reason, scope: "manager.administrateurs.delete")
end
redirect_to manager_administrateurs_path
end

View file

@ -70,7 +70,7 @@ class Administrateur < ApplicationRecord
end
def can_be_deleted?
procedures.all? { |p| p.administrateurs.count > 1 }
procedures.all? { |p| p.administrateurs.count > 1 || p.dossiers.empty? }
end
def delete_and_transfer_services

View file

@ -0,0 +1,65 @@
class AdministrateurDeletionService
include Dry::Monads[:result]
attr_reader :super_admin, :admin, :owned_procedures, :shared_procedures
def initialize(super_admin, admin)
@super_admin = super_admin
@admin = admin
@owned_procedures, @shared_procedures = admin
.procedures
.with_discarded
.partition { _1.administrateurs.one? }
end
def call
return Failure(:cannot_be_deleted) unless admin.can_be_deleted?
result = nil
ApplicationRecord.transaction do
delete_admin_from_shared_procedures
delete_procedures_without_dossier
if admin.procedures.with_discarded.count.positive?
result = Failure(:still_procedures)
raise ActiveRecord::Rollback
end
delete_services_without_procedures
transfer_services
if admin.services.count.positive?
result = Failure(:still_services)
raise ActiveRecord::Rollback
end
admin.destroy!
result = Success(:ok)
end
result
end
private
def delete_admin_from_shared_procedures
@shared_procedures.each { _1.administrateurs.delete(admin) }
end
def delete_procedures_without_dossier
procedures_without_dossier = owned_procedures.filter { _1.dossiers.empty? }
procedures_without_dossier.each { _1.discard_and_keep_track!(super_admin) }
procedures_without_dossier.each(&:purge_discarded)
end
def delete_services_without_procedures
admin.services.filter { _1.procedures.with_discarded.count.zero? }.each(&:destroy)
end
def transfer_services
shared_procedures.each do |procedure|
next if procedure.service.nil?
next_admin = procedure.administrateurs.where.not(id: admin.id).first
procedure.service.update(administrateur: next_admin)
end
end
end

View file

@ -2,3 +2,13 @@ fr:
manager:
gestionnaires:
manage_root_groupe_gestionnaire: Gestion du groupe racine
groupe_gestionnaires:
add_gestionnaire:
wrong_address:
one: "%{emails} nest pas une adresse email valide"
other: "%{emails} ne sont pas des adresses emails valides"
administrateurs:
delete:
cannot_be_deleted: "L'administrateur ne peut pas être supprimé"
still_procedures: "L'administrateur ne peut pas être supprimé car il a encore des démarches"
still_services: "L'administrateur ne peut pas être supprimé car il a encore des services"

View file

@ -17,11 +17,26 @@ describe Administrateur, type: :model do
it { is_expected.to be true }
end
context "when the administrateur has a procedure where they is the only admin" do
context "when the administrateur has a procedure with dossiers where they is the only admin" do
let!(:administrateur) { create(:administrateur) }
let!(:procedure) { create(:procedure_with_dossiers, administrateurs: [administrateur]) }
it { is_expected.to be false }
end
context "when the administrateur has a procedure with dossiers and with other admins" do
let!(:administrateur) { create(:administrateur) }
let!(:administrateur2) { create(:administrateur) }
let!(:procedure) { create(:procedure_with_dossiers, administrateurs: [administrateur, administrateur2]) }
it { is_expected.to be true }
end
context "when the administrateur has a procedure without dossiers" do
let!(:administrateur) { create(:administrateur) }
let!(:procedure) { create(:procedure, administrateurs: [administrateur]) }
it { is_expected.to be false }
it { is_expected.to be true }
end
context "when the administrateur has no procedure" do

View file

@ -0,0 +1,63 @@
describe AdministrateurDeletionService do
let(:super_admin) { create(:super_admin) }
let(:admin) { create(:administrateur) }
let(:service) { create(:service, administrateur: admin) }
let(:other_admin) { create(:administrateur) }
let(:procedure) { create(:procedure, service: service, administrateurs: [admin, other_admin]) }
let(:owned_procedure_service) { create(:service, administrateur: admin) }
let(:owned_procedure) { create(:procedure, service: owned_procedure_service, administrateurs: [admin]) }
describe '#call' do
subject { AdministrateurDeletionService.new(super_admin, admin).call }
context 'when admin can be deleted' do
it 'removes admin procedures without dossiers' do
owned_procedure
subject
expect(Procedure.find_by(id: owned_procedure.id)).to be_nil
end
it 'removes service admins without procedure' do
owned_procedure
subject
expect(Service.find_by(id: owned_procedure_service.id)).to be_nil
end
it 'transfer services to other admin' do
procedure
subject
expect(procedure.service.administrateur).to eq other_admin
end
it 'deletes admin' do
procedure
owned_procedure
subject
expect(Administrateur.find_by(id: admin.id)).to be_nil
end
end
context 'when admin has some procedures with dossiers and only one admin' do
let(:owned_procedure_with_dossier) { create(:procedure_with_dossiers, service: owned_procedure_service, administrateurs: [admin]) }
it "doesn't destroy admin" do
owned_procedure_with_dossier
subject
expect(Administrateur.find_by(id: admin.id)).to eq admin
expect(subject.failure).to eq :cannot_be_deleted
end
end
context "when there is a failure" do
it 'rollbacks' do
allow_any_instance_of(Service).to receive(:update).and_return(false)
procedure
owned_procedure
subject
expect(subject.failure).to eq :still_services
expect(admin.procedures.count).to eq 2
expect(procedure.administrateurs).to include(admin)
end
end
end
end