diff --git a/app/models/expert.rb b/app/models/expert.rb index d2766a3f7..01042c840 100644 --- a/app/models/expert.rb +++ b/app/models/expert.rb @@ -9,6 +9,7 @@ class Expert < ApplicationRecord has_one :user has_many :experts_procedures + has_many :procedures, through: :experts_procedures has_many :avis, through: :experts_procedures has_many :dossiers, through: :avis has_many :commentaires @@ -37,7 +38,22 @@ class Expert < ApplicationRecord end def merge(old_expert) - old_expert.experts_procedures.update_all(expert_id: id) + procedure_with_new, procedure_without_new = old_expert + .procedures + .partition { |p| p.experts.exists?(id) } + + ExpertsProcedure + .where(expert_id: old_expert.id, procedure: procedure_without_new) + .update_all(expert_id: id) + + ExpertsProcedure + .where(expert_id: old_expert.id, procedure: procedure_with_new) + .destroy_all + old_expert.commentaires.update_all(expert_id: id) + + Avis + .where(claimant_id: old_expert.id, claimant_type: Expert.name) + .update_all(claimant_id: id) end end diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 572900f3e..e9b4c5985 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -252,9 +252,29 @@ class Instructeur < ApplicationRecord end def merge(old_instructeur) - old_instructeur.assign_to.update_all(instructeur_id: id) - old_instructeur.follows.update_all(instructeur_id: id) - old_instructeur.administrateurs_instructeurs.update_all(instructeur_id: id) + old_instructeur + .assign_to + .where.not(groupe_instructeur_id: assign_to.pluck(:groupe_instructeur_id)) + .update_all(instructeur_id: id) + + old_instructeur + .follows + .where.not(dossier_id: follows.pluck(:dossier_id)) + .update_all(instructeur_id: id) + + admin_with_new_instructeur, admin_without_new_instructeur = old_instructeur + .administrateurs + .partition { |admin| admin.instructeurs.exists?(id) } + + admin_without_new_instructeur.each do |admin| + admin.instructeurs << self + admin.instructeurs.delete(old_instructeur) + end + + admin_with_new_instructeur.each do |admin| + admin.instructeurs.delete(old_instructeur) + end + old_instructeur.commentaires.update_all(instructeur_id: id) old_instructeur.bulk_messages.update_all(instructeur_id: id) end diff --git a/spec/models/expert_spec.rb b/spec/models/expert_spec.rb index 2b3dd1c78..5b3ebf607 100644 --- a/spec/models/expert_spec.rb +++ b/spec/models/expert_spec.rb @@ -12,4 +12,67 @@ RSpec.describe Expert, type: :model do it { expect(ExpertsProcedure.where(expert: expert, procedure: procedure).count).to eq(1) } it { expect(ExpertsProcedure.where(expert: expert, procedure: procedure).first.allow_decision_access).to be_falsy } end + + describe '#merge' do + let(:old_expert) { create(:expert) } + let(:new_expert) { create(:expert) } + + subject { new_expert.merge(old_expert) } + + context 'when an old expert access a procedure' do + let(:procedure) { create(:procedure) } + + before do + procedure.experts << old_expert + subject + end + + it 'transfers the access to the new expert' do + expect(procedure.reload.experts). to match_array(new_expert) + end + end + + context 'when both expert access a procedure' do + let(:procedure) { create(:procedure) } + + before do + procedure.experts << old_expert + procedure.experts << new_expert + subject + end + + it 'removes the old one' do + expect(procedure.reload.experts). to match_array(new_expert) + end + end + + context 'when an old expert has a commentaire' do + let(:dossier) { create(:dossier) } + let(:commentaire) { CommentaireService.build(old_expert, dossier, body: "Mon commentaire") } + + before do + commentaire.save + subject + end + + it 'transfers the commentaire to the new expert' do + expect(new_expert.reload.commentaires).to match_array(commentaire) + end + end + + context 'when an old expert claims for an avis' do + let!(:avis) { create(:avis, dossier: create(:dossier), claimant: old_expert) } + + before do + subject + end + + it 'transfers the claim to the new expert' do + avis_claimed_by_new_expert = Avis + .where(claimant_id: new_expert.id, claimant_type: Expert.name) + + expect(avis_claimed_by_new_expert).to match_array(avis) + end + end + end end diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 065e3eb19..a9ffc2c4a 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -737,6 +737,94 @@ describe Instructeur, type: :model do end end + describe '#merge' do + let(:old_instructeur) { create(:instructeur) } + let(:new_instructeur) { create(:instructeur) } + + subject { new_instructeur.merge(old_instructeur) } + + context 'when an procedure is assigned to the old instructeur' do + let(:procedure) { create(:procedure) } + + before do + procedure.defaut_groupe_instructeur.instructeurs << old_instructeur + subject + end + + it 'transfers the assignment' do + expect(new_instructeur.procedures).to match_array(procedure) + end + end + + context 'when both instructeurs are assigned to the same procedure' do + let(:procedure) { create(:procedure) } + + before do + procedure.defaut_groupe_instructeur.instructeurs << old_instructeur + procedure.defaut_groupe_instructeur.instructeurs << new_instructeur + subject + end + + it 'keeps the assignment' do + expect(new_instructeur.procedures).to match_array(procedure) + end + end + + context 'when a dossier is followed by an old instructeur' do + let(:dossier) { create(:dossier) } + + before do + old_instructeur.followed_dossiers << dossier + subject + end + + it 'transfers the dossier' do + expect(new_instructeur.followed_dossiers).to match_array(dossier) + end + end + + context 'when both instructeurs follow the same dossier' do + let(:dossier) { create(:dossier) } + + before do + old_instructeur.followed_dossiers << dossier + new_instructeur.followed_dossiers << dossier + subject + end + + it 'does not change anything' do + expect(new_instructeur.followed_dossiers.pluck(:id)).to match_array(dossier.id) + end + end + + context 'when the old instructeur is on on admin list' do + let(:administrateur) { create(:administrateur) } + + before do + administrateur.instructeurs << old_instructeur + subject + end + + it 'is replaced by the new one' do + expect(administrateur.reload.instructeurs).to match_array(new_instructeur) + end + end + + context 'when both are on the same admin list' do + let(:administrateur) { create(:administrateur) } + + before do + administrateur.instructeurs << old_instructeur + administrateur.instructeurs << new_instructeur + subject + end + + it 'removes the old one' do + expect(administrateur.reload.instructeurs).to match_array(new_instructeur) + end + end + end + private def assign(procedure_to_assign, instructeur_assigne: instructeur)