From 5f5714678cecf3a441d41c383599b9b995ba4667 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 30 Jun 2023 11:26:23 +0200 Subject: [PATCH 01/15] feat(DossierAsignment): create model --- .rubocop.yml | 1 + app/models/dossier.rb | 2 ++ app/models/dossier_assignment.rb | 22 +++++++++++++++++++ ...230630091637_create_dossier_assignments.rb | 14 ++++++++++++ db/schema.rb | 15 ++++++++++++- 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 app/models/dossier_assignment.rb create mode 100644 db/migrate/20230630091637_create_dossier_assignments.rb diff --git a/.rubocop.yml b/.rubocop.yml index 9b9a9089a..996908ae9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -743,6 +743,7 @@ Rails/CreateTableWithTimestamps: - db/migrate/2017*.rb - db/migrate/2018*.rb - db/migrate/20200630140356_create_traitements.rb + - db/migrate/20230630091637_create_dossier_assignments.rb Rails/Date: Enabled: false diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 1ea1efb3e..be164a13b 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -155,6 +155,8 @@ class Dossier < ApplicationRecord has_one :traitement, -> { order(processed_at: :desc) }, inverse_of: false has_many :dossier_operation_logs, -> { order(:created_at) }, inverse_of: :dossier + has_many :dossier_assignments, -> { order(:assigned_at) }, inverse_of: :dossier, dependent: :destroy + has_one :dossier_assignment, -> { order(assigned_at: :desc) }, inverse_of: false belongs_to :groupe_instructeur, optional: true belongs_to :revision, class_name: 'ProcedureRevision', optional: false diff --git a/app/models/dossier_assignment.rb b/app/models/dossier_assignment.rb new file mode 100644 index 000000000..bd100b599 --- /dev/null +++ b/app/models/dossier_assignment.rb @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: dossier_assignments +# +# id :bigint not null, primary key +# assigned_at :datetime not null +# assigned_by :string +# groupe_instructeur_label :string +# mode :string not null +# previous_groupe_instructeur_label :string +# dossier_id :bigint not null +# groupe_instructeur_id :bigint +# previous_groupe_instructeur_id :bigint +# +class DossierAssignment < ApplicationRecord + belongs_to :dossier + + enum mode: { + auto: 'auto', + manual: 'manual' + } +end diff --git a/db/migrate/20230630091637_create_dossier_assignments.rb b/db/migrate/20230630091637_create_dossier_assignments.rb new file mode 100644 index 000000000..6dc77f03f --- /dev/null +++ b/db/migrate/20230630091637_create_dossier_assignments.rb @@ -0,0 +1,14 @@ +class CreateDossierAssignments < ActiveRecord::Migration[7.0] + def change + create_table :dossier_assignments do |t| + t.references :dossier, foreign_key: true, null: false + t.string :mode, null: false + t.bigint :groupe_instructeur_id + t.bigint :previous_groupe_instructeur_id + t.string :groupe_instructeur_label + t.string :previous_groupe_instructeur_label + t.string :assigned_by + t.timestamp :assigned_at, null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index c50569b18..cd6e7611a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_07_18_113720) do +ActiveRecord::Schema[7.0].define(version: 2023_07_18_113820) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -307,6 +307,18 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_18_113720) do t.index ["procedure_id"], name: "index_deleted_dossiers_on_procedure_id" end + create_table "dossier_assignments", force: :cascade do |t| + t.datetime "assigned_at", precision: nil, null: false + t.string "assigned_by" + t.bigint "dossier_id", null: false + t.bigint "groupe_instructeur_id" + t.string "groupe_instructeur_label" + t.string "mode", null: false + t.bigint "previous_groupe_instructeur_id" + t.string "previous_groupe_instructeur_label" + t.index ["dossier_id"], name: "index_dossier_assignments_on_dossier_id" + end + create_table "dossier_batch_operations", force: :cascade do |t| t.bigint "batch_operation_id", null: false t.datetime "created_at", precision: 6, null: false @@ -1030,6 +1042,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_18_113720) do add_foreign_key "commentaires", "dossiers" add_foreign_key "commentaires", "experts" add_foreign_key "commentaires", "instructeurs" + add_foreign_key "dossier_assignments", "dossiers" add_foreign_key "dossier_batch_operations", "batch_operations" add_foreign_key "dossier_batch_operations", "dossiers" add_foreign_key "dossier_corrections", "commentaires" From c09655a07ff84acfb00acccefb7f6e4b10b1f6c1 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 30 Jun 2023 14:21:58 +0200 Subject: [PATCH 02/15] feat(DossierAssignment): create assignment from routing engine --- app/models/routing_engine.rb | 14 +++++++++ spec/models/dossier_assignment_spec.rb | 39 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 spec/models/dossier_assignment_spec.rb diff --git a/app/models/routing_engine.rb b/app/models/routing_engine.rb index a0a671d33..2a6e43b72 100644 --- a/app/models/routing_engine.rb +++ b/app/models/routing_engine.rb @@ -2,10 +2,24 @@ module RoutingEngine def self.compute(dossier) return if dossier.forced_groupe_instructeur + previous_groupe_instructeur = dossier.groupe_instructeur + matching_groupe = dossier.procedure.groupe_instructeurs.active.reject(&:invalid_rule?).find do |gi| gi.routing_rule&.compute(dossier.champs) end + matching_groupe ||= dossier.procedure.defaut_groupe_instructeur + dossier.assign_to_groupe_instructeur(matching_groupe) + + DossierAssignment.create!( + dossier_id: dossier.id, + mode: 'auto', + previous_groupe_instructeur_id: previous_groupe_instructeur&.id, + groupe_instructeur_id: matching_groupe.id, + previous_groupe_instructeur_label: previous_groupe_instructeur&.label, + groupe_instructeur_label: matching_groupe.label, + assigned_at: Time.zone.now + ) end end diff --git a/spec/models/dossier_assignment_spec.rb b/spec/models/dossier_assignment_spec.rb new file mode 100644 index 000000000..84b4db5c2 --- /dev/null +++ b/spec/models/dossier_assignment_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +RSpec.describe DossierAssignment, type: :model do + include Logic + + before { Flipper.enable(:routing_rules, procedure) } + + context 'Assignment from routing engine' do + let(:procedure) do + create(:procedure, + types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p| + p.groupe_instructeurs.create(label: 'a second group') + p.groupe_instructeurs.create(label: 'a third group') + end + end + + let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first } + + let(:dossier) { create(:dossier, procedure:, groupe_instructeur_id: nil) } + let(:defaut_groupe) { procedure.defaut_groupe_instructeur } + let(:gi_2) { procedure.groupe_instructeurs.find_by(label: 'a second group') } + + before do + RoutingEngine.compute(dossier) + dossier.reload + end + + it 'creates a dossier assignment with right attributes' do + expect(dossier.dossier_assignments.count).to eq 1 + expect(dossier.dossier_assignment.mode).to eq 'auto' + expect(dossier.dossier_assignment.dossier_id).to eq dossier.id + expect(dossier.dossier_assignment.groupe_instructeur_id).to eq dossier.groupe_instructeur.id + expect(dossier.dossier_assignment.groupe_instructeur_label).to eq dossier.groupe_instructeur.label + expect(dossier.dossier_assignment.previous_groupe_instructeur_id).to be nil + expect(dossier.dossier_assignment.previous_groupe_instructeur_label).to be nil + expect(dossier.dossier_assignment.assigned_by).to be nil + end + end +end From ac2043e9207d3f8bc3aceaf1f7675fa6805f01ac Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 30 Jun 2023 14:52:20 +0200 Subject: [PATCH 03/15] feat(DossierAssignment): create assignment when manual assignment by instructeur --- .../instructeurs/dossiers_controller.rb | 13 +++++++++++++ .../instructeurs/dossiers_controller_spec.rb | 15 ++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index c101b2772..2010d7c81 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -358,6 +358,8 @@ module Instructeurs def reaffecter dossier = current_instructeur.dossiers.find(params[:dossier_id]) + previous_groupe_instructeur = dossier.groupe_instructeur + new_group = dossier .procedure .groupe_instructeurs.find(params[:groupe_instructeur_id]) @@ -366,6 +368,17 @@ module Instructeurs dossier.update!(forced_groupe_instructeur: true) + DossierAssignment.create!( + dossier_id: dossier.id, + mode: :manual, + previous_groupe_instructeur_id: previous_groupe_instructeur&.id, + groupe_instructeur_id: new_group.id, + previous_groupe_instructeur_label: previous_groupe_instructeur&.label, + groupe_instructeur_label: new_group.label, + assigned_at: Time.zone.now, + assigned_by: current_instructeur.email + ) + flash.notice = t('instructeurs.dossiers.reaffectation', dossier_id: dossier.id, label: new_group.label) redirect_to instructeur_procedure_path(procedure) end diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index a18018031..e28fcae48 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1185,10 +1185,16 @@ describe Instructeurs::DossiersController, type: :controller do end describe '#reaffecter' do + let!(:gi_1) { procedure.groupe_instructeurs.first } let!(:gi_2) { GroupeInstructeur.create(label: 'deuxième groupe', procedure: procedure) } - let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, groupe_instructeur: procedure.groupe_instructeurs.first) } + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, groupe_instructeur: gi_1) } + let!(:new_instructeur) { create(:instructeur) } before do + gi_1.instructeurs << new_instructeur + gi_1.dossiers << dossier + new_instructeur.followed_dossiers << dossier + post :reaffecter, params: { procedure_id: procedure.id, @@ -1200,6 +1206,13 @@ describe Instructeurs::DossiersController, type: :controller do it do expect(dossier.reload.groupe_instructeur.id).to eq(gi_2.id) expect(dossier.forced_groupe_instructeur).to be_truthy + expect(dossier.followers_instructeurs).to eq [] + expect(dossier.dossier_assignment.previous_groupe_instructeur_id).to eq(gi_1.id) + expect(dossier.dossier_assignment.previous_groupe_instructeur_label).to eq(gi_1.label) + expect(dossier.dossier_assignment.groupe_instructeur_id).to eq(gi_2.id) + expect(dossier.dossier_assignment.groupe_instructeur_label).to eq(gi_2.label) + expect(dossier.dossier_assignment.mode).to eq('manual') + expect(dossier.dossier_assignment.assigned_by).to eq(instructeur.email) expect(response).to redirect_to(instructeur_procedure_path(procedure)) expect(flash.notice).to eq("Le dossier nº #{dossier.id} a été réaffecté au groupe d’instructeurs « deuxième groupe ».") end From f619fdfb19ef240ed2ca4b2289fda58f084824ab Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 30 Jun 2023 15:27:38 +0200 Subject: [PATCH 04/15] feat(DossierAssignment): add reaffectations to presonnes impliquees view --- app/models/dossier_assignment.rb | 1 + .../dossiers/_reaffectations_block.html.haml | 10 +++++++ .../dossiers/personnes_impliquees.html.haml | 3 +- .../instructeurs/dossiers_controller_spec.rb | 30 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 app/views/instructeurs/dossiers/_reaffectations_block.html.haml diff --git a/app/models/dossier_assignment.rb b/app/models/dossier_assignment.rb index bd100b599..9c3e3c883 100644 --- a/app/models/dossier_assignment.rb +++ b/app/models/dossier_assignment.rb @@ -19,4 +19,5 @@ class DossierAssignment < ApplicationRecord auto: 'auto', manual: 'manual' } + scope :manual, -> { where(mode: :manual) } end diff --git a/app/views/instructeurs/dossiers/_reaffectations_block.html.haml b/app/views/instructeurs/dossiers/_reaffectations_block.html.haml new file mode 100644 index 000000000..a786a6e7c --- /dev/null +++ b/app/views/instructeurs/dossiers/_reaffectations_block.html.haml @@ -0,0 +1,10 @@ +.tab-title Réaffectations +- if manual_assignments.any? + %ul.tab-list + - manual_assignments.each do |assignment| + %li + - assigned_at = l(assignment.assigned_at, format: '%d %B %Y à %R') + = "Le #{assigned_at}, #{assignment.assigned_by} a réaffecté le dossier #{assignment.dossier_id} du groupe #{assignment.previous_groupe_instructeur_id} au groupe #{assignment.groupe_instructeur_id}" + +- else + %p.tab-paragraph Ce dossier n'a pas été réaffecté diff --git a/app/views/instructeurs/dossiers/personnes_impliquees.html.haml b/app/views/instructeurs/dossiers/personnes_impliquees.html.haml index a55b61b2a..7a6d0d94a 100644 --- a/app/views/instructeurs/dossiers/personnes_impliquees.html.haml +++ b/app/views/instructeurs/dossiers/personnes_impliquees.html.haml @@ -16,6 +16,7 @@ = render partial: 'instructeurs/dossiers/decisions_rendues_block', locals: { traitements: @dossier.traitements } + = render partial: 'instructeurs/dossiers/reaffectations_block', locals: { manual_assignments: @dossier.dossier_assignments.manual } + - if @dossier.archived? && @dossier.archived_at.present? = render partial: 'instructeurs/dossiers/archived_block', locals: @dossier.slice(:archived_by, :archived_at) - diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index e28fcae48..95f106982 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1217,4 +1217,34 @@ describe Instructeurs::DossiersController, type: :controller do expect(flash.notice).to eq("Le dossier nº #{dossier.id} a été réaffecté au groupe d’instructeurs « deuxième groupe ».") end end + + describe '#personnes_impliquees' do + let!(:gi_1) { procedure.groupe_instructeurs.first } + let!(:gi_2) { GroupeInstructeur.create(label: 'deuxième groupe', procedure: procedure) } + let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, groupe_instructeur: gi_1) } + let!(:new_instructeur) { create(:instructeur) } + + before do + gi_1.instructeurs << new_instructeur + gi_2.instructeurs << instructeur + new_instructeur.followed_dossiers << dossier + dossier.assign_to_groupe_instructeur(gi_2) + dossier.create_assignment( + DossierAssignment.modes.fetch(:manual), + gi_1, + gi_2, + new_instructeur.email + ) + + get :personnes_impliquees, + params: { + procedure_id: procedure.id, + dossier_id: dossier.id + } + end + + it do + expect(response.body).to include('a réaffecté ce dossier du groupe « défaut » au groupe « deuxième groupe »') + end + end end From d6520249e1bb229a5f35178c791c7e052b6ff7e3 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 30 Jun 2023 16:09:31 +0200 Subject: [PATCH 05/15] feat(DossierAssignment): display groups labels in personnes impliquees view --- app/controllers/instructeurs/dossiers_controller.rb | 1 + .../instructeurs/dossiers/_reaffectations_block.html.haml | 8 +++++++- .../instructeurs/dossiers/personnes_impliquees.html.haml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 2010d7c81..d4b135e3a 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -91,6 +91,7 @@ module Instructeurs @avis_emails = dossier.experts.map(&:email) @invites_emails = dossier.invites.map(&:email) @potential_recipients = dossier.groupe_instructeur.instructeurs.reject { |g| g == current_instructeur } + @manual_assignments = dossier.dossier_assignments.manual end def send_to_instructeurs diff --git a/app/views/instructeurs/dossiers/_reaffectations_block.html.haml b/app/views/instructeurs/dossiers/_reaffectations_block.html.haml index a786a6e7c..57175a6d4 100644 --- a/app/views/instructeurs/dossiers/_reaffectations_block.html.haml +++ b/app/views/instructeurs/dossiers/_reaffectations_block.html.haml @@ -4,7 +4,13 @@ - manual_assignments.each do |assignment| %li - assigned_at = l(assignment.assigned_at, format: '%d %B %Y à %R') - = "Le #{assigned_at}, #{assignment.assigned_by} a réaffecté le dossier #{assignment.dossier_id} du groupe #{assignment.previous_groupe_instructeur_id} au groupe #{assignment.groupe_instructeur_id}" + - assigned_by = assignment.assigned_by + - if assigned_by.present? + = "Le #{assigned_at}, #{assigned_by} a réaffecté ce dossier du groupe « #{assignment.previous_groupe_instructeur_label} » au groupe « #{assignment.groupe_instructeur_label} »" + - else + = "Le #{assigned_at}, ce dossier a été réaffecté du groupe « #{assignment.previous_groupe_instructeur_label} » au groupe « #{assignment.groupe_instructeur_label} »" +- elsif dossier.forced_groupe_instructeur + %p.tab-paragraph Ce dossier a été réaffecté au groupe « #{dossier.groupe_instructeur.label} » - else %p.tab-paragraph Ce dossier n'a pas été réaffecté diff --git a/app/views/instructeurs/dossiers/personnes_impliquees.html.haml b/app/views/instructeurs/dossiers/personnes_impliquees.html.haml index 7a6d0d94a..18067ba00 100644 --- a/app/views/instructeurs/dossiers/personnes_impliquees.html.haml +++ b/app/views/instructeurs/dossiers/personnes_impliquees.html.haml @@ -16,7 +16,7 @@ = render partial: 'instructeurs/dossiers/decisions_rendues_block', locals: { traitements: @dossier.traitements } - = render partial: 'instructeurs/dossiers/reaffectations_block', locals: { manual_assignments: @dossier.dossier_assignments.manual } + = render partial: 'instructeurs/dossiers/reaffectations_block', locals: { manual_assignments: @manual_assignments, dossier: @dossier } - if @dossier.archived? && @dossier.archived_at.present? = render partial: 'instructeurs/dossiers/archived_block', locals: @dossier.slice(:archived_by, :archived_at) From 199cf0d91fed97cf69c45bb6709f7749bea03323 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Tue, 4 Jul 2023 22:19:12 +0200 Subject: [PATCH 06/15] feat(DossierAssignment): fallback on label if group deleted --- app/models/dossier_assignment.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/models/dossier_assignment.rb b/app/models/dossier_assignment.rb index 9c3e3c883..0bd82781f 100644 --- a/app/models/dossier_assignment.rb +++ b/app/models/dossier_assignment.rb @@ -20,4 +20,12 @@ class DossierAssignment < ApplicationRecord manual: 'manual' } scope :manual, -> { where(mode: :manual) } + + def groupe_instructeur_label + @groupe_instructeur_label ||= GroupeInstructeur.find_by(id: groupe_instructeur_id)&.label || read_attribute(:groupe_instructeur_label) + end + + def previous_groupe_instructeur_label + @previous_groupe_instructeur_label ||= GroupeInstructeur.find_by(id: previous_groupe_instructeur_id)&.label || read_attribute(:previous_groupe_instructeur_label) + end end From 488a932cd578e043ae872bc3eb2dd296d087e6b1 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Tue, 4 Jul 2023 23:16:19 +0200 Subject: [PATCH 07/15] refactor(DossierAssignment): extract method create_assignment --- .../instructeurs/dossiers_controller.rb | 14 +++++--------- app/models/dossier.rb | 13 +++++++++++++ app/models/routing_engine.rb | 10 +--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index d4b135e3a..7cf2b6d89 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -369,15 +369,11 @@ module Instructeurs dossier.update!(forced_groupe_instructeur: true) - DossierAssignment.create!( - dossier_id: dossier.id, - mode: :manual, - previous_groupe_instructeur_id: previous_groupe_instructeur&.id, - groupe_instructeur_id: new_group.id, - previous_groupe_instructeur_label: previous_groupe_instructeur&.label, - groupe_instructeur_label: new_group.label, - assigned_at: Time.zone.now, - assigned_by: current_instructeur.email + dossier.create_assignment( + DossierAssignment.modes.fetch(:manual), + previous_groupe_instructeur, + new_group, + current_instructeur.email ) flash.notice = t('instructeurs.dossiers.reaffectation', dossier_id: dossier.id, label: new_group.label) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index be164a13b..8b14e9651 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -1312,6 +1312,19 @@ class Dossier < ApplicationRecord (sva_svr_decision_on - Date.current).to_i end + def create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, instructeur_email = nil) + DossierAssignment.create!( + dossier_id: self.id, + mode: mode, + previous_groupe_instructeur_id: previous_groupe_instructeur&.id, + groupe_instructeur_id: groupe_instructeur.id, + previous_groupe_instructeur_label: previous_groupe_instructeur&.label, + groupe_instructeur_label: groupe_instructeur.label, + assigned_at: Time.zone.now, + assigned_by: instructeur_email + ) + end + private def create_missing_traitemets diff --git a/app/models/routing_engine.rb b/app/models/routing_engine.rb index 2a6e43b72..af4492397 100644 --- a/app/models/routing_engine.rb +++ b/app/models/routing_engine.rb @@ -12,14 +12,6 @@ module RoutingEngine dossier.assign_to_groupe_instructeur(matching_groupe) - DossierAssignment.create!( - dossier_id: dossier.id, - mode: 'auto', - previous_groupe_instructeur_id: previous_groupe_instructeur&.id, - groupe_instructeur_id: matching_groupe.id, - previous_groupe_instructeur_label: previous_groupe_instructeur&.label, - groupe_instructeur_label: matching_groupe.label, - assigned_at: Time.zone.now - ) + dossier.create_assignment(DossierAssignment.modes.fetch(:auto), previous_groupe_instructeur, matching_groupe) end end From 082db0ed02368c7217f9f30c6861f477815dbe7f Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 5 Jul 2023 11:13:01 +0200 Subject: [PATCH 08/15] feat(DossierAssignment): create Assignment when admin reaffect dossiers --- .../administrateurs/groupe_instructeurs_controller.rb | 7 +++++++ .../administrateurs/groupe_instructeurs_controller_spec.rb | 3 +++ 2 files changed, 10 insertions(+) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 6a1baeaee..b88ebef96 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -200,7 +200,14 @@ module Administrateurs target_group = procedure.groupe_instructeurs.find(params[:target_group]) reaffecter_bulk_messages(target_group) groupe_instructeur.dossiers.find_each do |dossier| + previous_group = dossier.groupe_instructeur dossier.assign_to_groupe_instructeur(target_group, current_administrateur) + dossier.create_assignment( + DossierAssignment.modes.fetch(:manual), + previous_group, + target_group, + current_administrateur.email + ) end flash[:notice] = "Les dossiers du groupe « #{groupe_instructeur.label} » ont été réaffectés au groupe « #{target_group.label} »." diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index e7152e9b5..f3a3e22c7 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -208,6 +208,9 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it { expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure)) } it { expect(gi_1_2.dossiers.last.id).to be(dossier12.id) } it { expect(dossier12.groupe_instructeur.id).to be(gi_1_2.id) } + it { expect(dossier12.dossier_assignment.dossier_id).to be(dossier12.id) } + it { expect(dossier12.dossier_assignment.groupe_instructeur_id).to be(gi_1_2.id) } + it { expect(dossier12.dossier_assignment.assigned_by).to eq(admin.email) } it { expect(bulk_message.groupe_instructeurs).to contain_exactly(gi_1_2, gi_1_3) } end From 96d17d03ecd7334d3abe80c71ed6e4a44d79b06d Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 5 Jul 2023 11:31:37 +0200 Subject: [PATCH 09/15] feat(DossierAssignment): create assignments when admin reaffect all dossiers --- .../groupe_instructeurs_controller.rb | 10 +++++++- .../groupe_instructeurs_controller_spec.rb | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index b88ebef96..334d03f27 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -215,9 +215,17 @@ module Administrateurs end def reaffecter_all_dossiers_to_defaut_groupe + defaut_groupe = procedure.defaut_groupe_instructeur procedure.groupe_instructeurs_but_defaut.each do |gi| gi.dossiers.find_each do |dossier| - dossier.assign_to_groupe_instructeur(procedure.defaut_groupe_instructeur, current_administrateur) + previous_group = dossier.groupe_instructeur + dossier.assign_to_groupe_instructeur(defaut_groupe, current_administrateur) + dossier.create_assignment( + DossierAssignment.modes.fetch(:manual), + previous_group, + defaut_groupe, + current_administrateur.email + ) end end end diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index f3a3e22c7..fdaeb450a 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -234,6 +234,30 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do end end + describe '#destroy_all_groups_but_defaut' do + let!(:dossierA) { create(:dossier, :en_construction, :with_individual, procedure: procedure, groupe_instructeur: gi_1_2) } + let!(:dossierB) { create(:dossier, :en_construction, :with_individual, procedure: procedure, groupe_instructeur: gi_1_2) } + + before do + post :destroy_all_groups_but_defaut, + params: { + procedure_id: procedure.id + } + dossierA.reload + dossierB.reload + end + + it do + expect(dossierA.groupe_instructeur.id).to be(procedure.defaut_groupe_instructeur.id) + expect(dossierB.groupe_instructeur.id).to be(procedure.defaut_groupe_instructeur.id) + expect(dossierA.dossier_assignment.dossier_id).to be(dossierA.id) + expect(dossierB.dossier_assignment.dossier_id).to be(dossierB.id) + expect(dossierA.dossier_assignment.groupe_instructeur_id).to be(procedure.defaut_groupe_instructeur.id) + expect(dossierB.dossier_assignment.groupe_instructeur_id).to be(procedure.defaut_groupe_instructeur.id) + expect(dossierA.dossier_assignment.assigned_by).to eq(admin.email) + expect(dossierB.dossier_assignment.assigned_by).to eq(admin.email) + end + end describe '#update' do let(:new_name) { 'nouveau nom du groupe' } let!(:procedure_non_routee) { create(:procedure, :published, :for_individual, administrateurs: [admin]) } From 24f68b4deb1ebf090af9a14f284e197681098e7e Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 5 Jul 2023 17:03:46 +0200 Subject: [PATCH 10/15] feat(DossierAssignment): create assignments from api --- .../mutations/dossier_changer_groupe_instructeur.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb index 7a472b92e..fb7e9eadd 100644 --- a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb +++ b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb @@ -11,8 +11,16 @@ module Mutations field :errors, [Types::ValidationErrorType], null: true def resolve(dossier:, groupe_instructeur:) + previous_groupe_instructeur = dossier.groupe_instructeur + dossier.assign_to_groupe_instructeur(groupe_instructeur) + dossier.create_assignment( + DossierAssignment.modes.fetch(:manual), + previous_groupe_instructeur, + dossier.groupe_instructeur + ) + { dossier: } end From 0e58e10b82e56e5757ec6ba05d1ea3d9d3f5aa0f Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 5 Jul 2023 17:48:18 +0200 Subject: [PATCH 11/15] refactor(DossierAssignment): move create_assignment to assign_to_groupe_instructeur --- .../groupe_instructeurs_controller.rb | 19 ++----------------- .../instructeurs/dossiers_controller.rb | 11 +---------- .../dossier_changer_groupe_instructeur.rb | 10 +--------- app/models/concerns/dossier_clone_concern.rb | 1 - app/models/dossier.rb | 6 +++++- app/models/routing_engine.rb | 6 +----- .../instructeurs/dossiers_controller_spec.rb | 13 +++---------- .../concern/dossier_clone_concern_spec.rb | 2 +- spec/models/dossier_spec.rb | 6 +++--- spec/models/instructeur_spec.rb | 2 +- 10 files changed, 18 insertions(+), 58 deletions(-) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 334d03f27..101d05c1f 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -200,14 +200,7 @@ module Administrateurs target_group = procedure.groupe_instructeurs.find(params[:target_group]) reaffecter_bulk_messages(target_group) groupe_instructeur.dossiers.find_each do |dossier| - previous_group = dossier.groupe_instructeur - dossier.assign_to_groupe_instructeur(target_group, current_administrateur) - dossier.create_assignment( - DossierAssignment.modes.fetch(:manual), - previous_group, - target_group, - current_administrateur.email - ) + dossier.assign_to_groupe_instructeur(target_group, DossierAssignment.modes.fetch(:manual), current_administrateur) end flash[:notice] = "Les dossiers du groupe « #{groupe_instructeur.label} » ont été réaffectés au groupe « #{target_group.label} »." @@ -215,17 +208,9 @@ module Administrateurs end def reaffecter_all_dossiers_to_defaut_groupe - defaut_groupe = procedure.defaut_groupe_instructeur procedure.groupe_instructeurs_but_defaut.each do |gi| gi.dossiers.find_each do |dossier| - previous_group = dossier.groupe_instructeur - dossier.assign_to_groupe_instructeur(defaut_groupe, current_administrateur) - dossier.create_assignment( - DossierAssignment.modes.fetch(:manual), - previous_group, - defaut_groupe, - current_administrateur.email - ) + dossier.assign_to_groupe_instructeur(procedure.defaut_groupe_instructeur, DossierAssignment.modes.fetch(:manual), current_administrateur) end end end diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 7cf2b6d89..62ee9ef1d 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -359,23 +359,14 @@ module Instructeurs def reaffecter dossier = current_instructeur.dossiers.find(params[:dossier_id]) - previous_groupe_instructeur = dossier.groupe_instructeur - new_group = dossier .procedure .groupe_instructeurs.find(params[:groupe_instructeur_id]) - dossier.assign_to_groupe_instructeur(new_group) + dossier.assign_to_groupe_instructeur(new_group, DossierAssignment.modes.fetch(:manual), current_instructeur) dossier.update!(forced_groupe_instructeur: true) - dossier.create_assignment( - DossierAssignment.modes.fetch(:manual), - previous_groupe_instructeur, - new_group, - current_instructeur.email - ) - flash.notice = t('instructeurs.dossiers.reaffectation', dossier_id: dossier.id, label: new_group.label) redirect_to instructeur_procedure_path(procedure) end diff --git a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb index fb7e9eadd..b00cbf9cb 100644 --- a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb +++ b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb @@ -11,15 +11,7 @@ module Mutations field :errors, [Types::ValidationErrorType], null: true def resolve(dossier:, groupe_instructeur:) - previous_groupe_instructeur = dossier.groupe_instructeur - - dossier.assign_to_groupe_instructeur(groupe_instructeur) - - dossier.create_assignment( - DossierAssignment.modes.fetch(:manual), - previous_groupe_instructeur, - dossier.groupe_instructeur - ) + dossier.assign_to_groupe_instructeur(groupe_instructeur, DossierAssignment.modes.fetch(:manual)) { dossier: } end diff --git a/app/models/concerns/dossier_clone_concern.rb b/app/models/concerns/dossier_clone_concern.rb index 5c02ea731..fc056c8bd 100644 --- a/app/models/concerns/dossier_clone_concern.rb +++ b/app/models/concerns/dossier_clone_concern.rb @@ -69,7 +69,6 @@ module DossierCloneConcern diff = make_diff(editing_fork) apply_diff(diff) touch(:last_champ_updated_at) - assign_to_groupe_instructeur(editing_fork.groupe_instructeur) end reload update_search_terms_later diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 8b14e9651..4ca3bfa22 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -688,12 +688,16 @@ class Dossier < ApplicationRecord procedure.discarded? || (brouillon? && !procedure.dossier_can_transition_to_en_construction?) end - def assign_to_groupe_instructeur(groupe_instructeur, author = nil) + def assign_to_groupe_instructeur(groupe_instructeur, mode, author = nil) return if groupe_instructeur.present? && groupe_instructeur.procedure != procedure return if self.groupe_instructeur == groupe_instructeur + previous_groupe_instructeur = self.groupe_instructeur + update!(groupe_instructeur:, groupe_instructeur_updated_at: Time.zone.now) + create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, author&.email) + if !brouillon? unfollow_stale_instructeurs if author.present? diff --git a/app/models/routing_engine.rb b/app/models/routing_engine.rb index af4492397..4d9e00c76 100644 --- a/app/models/routing_engine.rb +++ b/app/models/routing_engine.rb @@ -2,16 +2,12 @@ module RoutingEngine def self.compute(dossier) return if dossier.forced_groupe_instructeur - previous_groupe_instructeur = dossier.groupe_instructeur - matching_groupe = dossier.procedure.groupe_instructeurs.active.reject(&:invalid_rule?).find do |gi| gi.routing_rule&.compute(dossier.champs) end matching_groupe ||= dossier.procedure.defaut_groupe_instructeur - dossier.assign_to_groupe_instructeur(matching_groupe) - - dossier.create_assignment(DossierAssignment.modes.fetch(:auto), previous_groupe_instructeur, matching_groupe) + dossier.assign_to_groupe_instructeur(matching_groupe, DossierAssignment.modes.fetch(:auto)) end end diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 95f106982..4f61debbf 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1187,12 +1187,11 @@ describe Instructeurs::DossiersController, type: :controller do describe '#reaffecter' do let!(:gi_1) { procedure.groupe_instructeurs.first } let!(:gi_2) { GroupeInstructeur.create(label: 'deuxième groupe', procedure: procedure) } - let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, groupe_instructeur: gi_1) } + let!(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure, groupe_instructeur: gi_1) } let!(:new_instructeur) { create(:instructeur) } before do gi_1.instructeurs << new_instructeur - gi_1.dossiers << dossier new_instructeur.followed_dossiers << dossier post :reaffecter, @@ -1221,20 +1220,14 @@ describe Instructeurs::DossiersController, type: :controller do describe '#personnes_impliquees' do let!(:gi_1) { procedure.groupe_instructeurs.first } let!(:gi_2) { GroupeInstructeur.create(label: 'deuxième groupe', procedure: procedure) } - let!(:dossier) { create(:dossier, :en_construction, procedure: procedure, groupe_instructeur: gi_1) } + let!(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure, groupe_instructeur: gi_1) } let!(:new_instructeur) { create(:instructeur) } before do gi_1.instructeurs << new_instructeur gi_2.instructeurs << instructeur new_instructeur.followed_dossiers << dossier - dossier.assign_to_groupe_instructeur(gi_2) - dossier.create_assignment( - DossierAssignment.modes.fetch(:manual), - gi_1, - gi_2, - new_instructeur.email - ) + dossier.assign_to_groupe_instructeur(gi_2, DossierAssignment.modes.fetch(:manual), new_instructeur) get :personnes_impliquees, params: { diff --git a/spec/models/concern/dossier_clone_concern_spec.rb b/spec/models/concern/dossier_clone_concern_spec.rb index 8ebe82ef6..4d9f35d42 100644 --- a/spec/models/concern/dossier_clone_concern_spec.rb +++ b/spec/models/concern/dossier_clone_concern_spec.rb @@ -221,7 +221,7 @@ RSpec.describe DossierCloneConcern do context 'with updated groupe instructeur' do before { dossier.update!(groupe_instructeur: create(:groupe_instructeur)) - forked_dossier.assign_to_groupe_instructeur(dossier.procedure.defaut_groupe_instructeur) + forked_dossier.assign_to_groupe_instructeur(dossier.procedure.defaut_groupe_instructeur, DossierAssignment.modes.fetch(:manual)) } it { is_expected.to eq(added: [], updated: [], removed: []) } diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 8f2641507..fc3780920 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -578,12 +578,12 @@ describe Dossier, type: :model do let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } it "can change groupe instructeur" do - dossier.assign_to_groupe_instructeur(new_groupe_instructeur_new_procedure) + dossier.assign_to_groupe_instructeur(new_groupe_instructeur_new_procedure, DossierAssignment.modes.fetch(:auto)) expect(dossier.groupe_instructeur).not_to eq(new_groupe_instructeur_new_procedure) end it "can not change groupe instructeur if new groupe is from another procedure" do - dossier.assign_to_groupe_instructeur(new_groupe_instructeur) + dossier.assign_to_groupe_instructeur(new_groupe_instructeur, DossierAssignment.modes.fetch(:auto)) expect(dossier.groupe_instructeur).to eq(new_groupe_instructeur) end end @@ -603,7 +603,7 @@ describe Dossier, type: :model do it "unfollows stale instructeurs when groupe instructeur change" do instructeur.follow(dossier) instructeur2.follow(dossier) - dossier.reload.assign_to_groupe_instructeur(new_groupe_instructeur, procedure.administrateurs.first) + dossier.reload.assign_to_groupe_instructeur(new_groupe_instructeur, DossierAssignment.modes.fetch(:auto), procedure.administrateurs.first) expect(dossier.reload.followers_instructeurs).not_to include(instructeur) expect(dossier.reload.followers_instructeurs).to include(instructeur2) diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 47f09dcfe..c4ec8cab8 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -209,7 +209,7 @@ describe Instructeur, type: :model do context 'when there is a modification on groupe instructeur' do let(:groupe_instructeur) { create(:groupe_instructeur, instructeurs: [instructeur], procedure: dossier.procedure) } - before { dossier.assign_to_groupe_instructeur(groupe_instructeur) } + before { dossier.assign_to_groupe_instructeur(groupe_instructeur, DossierAssignment.modes.fetch(:auto)) } it { is_expected.to match({ demande: true, annotations_privees: false, avis: false, messagerie: false }) } end From 7a95846cba24714f99ecbc29999ee1401a24b8ac Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 6 Jul 2023 11:06:10 +0200 Subject: [PATCH 12/15] feat(DossierAssignment): always add forced_groupe_instructeur when manual assignment --- app/controllers/instructeurs/dossiers_controller.rb | 2 -- app/models/dossier.rb | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 62ee9ef1d..5892a7898 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -365,8 +365,6 @@ module Instructeurs dossier.assign_to_groupe_instructeur(new_group, DossierAssignment.modes.fetch(:manual), current_instructeur) - dossier.update!(forced_groupe_instructeur: true) - flash.notice = t('instructeurs.dossiers.reaffectation', dossier_id: dossier.id, label: new_group.label) redirect_to instructeur_procedure_path(procedure) end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 4ca3bfa22..9e1e23122 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -698,6 +698,8 @@ class Dossier < ApplicationRecord create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, author&.email) + update!(forced_groupe_instructeur: true) if mode == DossierAssignment.modes.fetch(:manual) + if !brouillon? unfollow_stale_instructeurs if author.present? From e8e9857dda5b3c6b95aec856c144cd2365ddd61b Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 6 Jul 2023 14:25:46 +0200 Subject: [PATCH 13/15] style(reaffectation): apply dsfr to buttons --- .../groupe_instructeurs/reaffecter_dossiers.html.haml | 8 ++++---- .../instructeurs/dossiers/reaffectation.html.haml | 10 +++++----- .../instructeurs/dossiers_controller_spec.rb | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/views/administrateurs/groupe_instructeurs/reaffecter_dossiers.html.haml b/app/views/administrateurs/groupe_instructeurs/reaffecter_dossiers.html.haml index 1d2c5c456..d74cccae2 100644 --- a/app/views/administrateurs/groupe_instructeurs/reaffecter_dossiers.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/reaffecter_dossiers.html.haml @@ -16,11 +16,11 @@ %th{ colspan: 2 }= t(".existing_groupe", count: @groupes_instructeurs.total_count) %tbody - @groupes_instructeurs.each do |group| - %tr - %td= group.label - %td.actions= button_to 'Réaffecter les dossiers à ce groupe', + .flex.justify-between.align-center.fr-mb-2w + %p.fr-mb-0= group.label + = button_to 'Réaffecter les dossiers à ce groupe', reaffecter_admin_procedure_groupe_instructeur_path(:target_group => group), - { class: 'button', + { class: 'fr-btn fr-btn--secondary fr-btn--sm', data: { confirm: "Êtes-vous sûr de vouloir réaffecter les dossiers du groupe « #{@groupe_instructeur.label} » vers le groupe  « #{group.label} » ?" } } = paginate @groupes_instructeurs, views_prefix: 'shared' diff --git a/app/views/instructeurs/dossiers/reaffectation.html.haml b/app/views/instructeurs/dossiers/reaffectation.html.haml index 116191aa0..5b5307592 100644 --- a/app/views/instructeurs/dossiers/reaffectation.html.haml +++ b/app/views/instructeurs/dossiers/reaffectation.html.haml @@ -7,18 +7,18 @@ .card .card-title Réaffectation du dossier nº #{@dossier.id} du groupe « #{@groupe_instructeur.label} » %p - Vous pouvez réaffecter le dossier nº #{@dossier.id} à l'un des groupes d'instructeurs suivants. + Vous pouvez réaffecter le dossier nº #{@dossier.id} à l’un des groupes d’instructeurs suivants. %table.table.mt-2 %thead %tr %th{ colspan: 2 }= t("instructeurs.dossiers.existing_groupe", count: @groupes_instructeurs.total_count) %tbody - @groupes_instructeurs.each do |group| - %tr - %td= group.label - %td.actions= button_to 'Réaffecter le dossier à ce groupe', + .flex.justify-between.align-center.fr-mb-2w + %p.fr-mb-0= group.label + = button_to 'Réaffecter le dossier à ce groupe', reaffecter_instructeur_dossier_path(procedure_id: @dossier.procedure.id, dossier_id: @dossier.id, groupe_instructeur_id: group.id), - { class: 'button', + { class: 'fr-btn fr-btn--secondary fr-btn--sm', data: { confirm: "Êtes-vous sûr de vouloir réaffecter le dossier nº #{@dossier.id} du groupe « #{@groupe_instructeur.label} » vers le groupe  « #{group.label} » ?" } } = paginate @groupes_instructeurs, views_prefix: 'shared' diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 4f61debbf..7046069af 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1179,7 +1179,7 @@ describe Instructeurs::DossiersController, type: :controller do it do expect(response).to have_http_status(:ok) - expect(response.body).to include("Vous pouvez réaffecter le dossier nº #{dossier.id} à l'un des groupes d'instructeurs suivants.") + expect(response.body).to include("Vous pouvez réaffecter le dossier nº #{dossier.id} à l’un des groupes d’instructeurs suivants.") expect(response.body).to include('2 groupes existent') end end From 04160b5d44f43cf48283b153450fc2c735d3b1ae Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 13 Jul 2023 16:47:55 +0200 Subject: [PATCH 14/15] chore(dossier_assignment): avoid n+1 queries --- app/controllers/instructeurs/dossiers_controller.rb | 2 +- app/models/dossier_assignment.rb | 7 +++++-- app/models/groupe_instructeur.rb | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 5892a7898..2f1ec2448 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -91,7 +91,7 @@ module Instructeurs @avis_emails = dossier.experts.map(&:email) @invites_emails = dossier.invites.map(&:email) @potential_recipients = dossier.groupe_instructeur.instructeurs.reject { |g| g == current_instructeur } - @manual_assignments = dossier.dossier_assignments.manual + @manual_assignments = dossier.dossier_assignments.manual.includes(:groupe_instructeur, :previous_groupe_instructeur) end def send_to_instructeurs diff --git a/app/models/dossier_assignment.rb b/app/models/dossier_assignment.rb index 0bd82781f..46917e188 100644 --- a/app/models/dossier_assignment.rb +++ b/app/models/dossier_assignment.rb @@ -15,6 +15,9 @@ class DossierAssignment < ApplicationRecord belongs_to :dossier + belongs_to :groupe_instructeur, optional: true, inverse_of: :assignments + belongs_to :previous_groupe_instructeur, class_name: 'GroupeInstructeur', optional: true, inverse_of: :previous_assignments + enum mode: { auto: 'auto', manual: 'manual' @@ -22,10 +25,10 @@ class DossierAssignment < ApplicationRecord scope :manual, -> { where(mode: :manual) } def groupe_instructeur_label - @groupe_instructeur_label ||= GroupeInstructeur.find_by(id: groupe_instructeur_id)&.label || read_attribute(:groupe_instructeur_label) + @groupe_instructeur_label ||= groupe_instructeur&.label.presence || read_attribute(:groupe_instructeur_label) end def previous_groupe_instructeur_label - @previous_groupe_instructeur_label ||= GroupeInstructeur.find_by(id: previous_groupe_instructeur_id)&.label || read_attribute(:previous_groupe_instructeur_label) + @previous_groupe_instructeur_label ||= previous_groupe_instructeur&.label.presence || read_attribute(:previous_groupe_instructeur_label) end end diff --git a/app/models/groupe_instructeur.rb b/app/models/groupe_instructeur.rb index 0227e645a..7acf19561 100644 --- a/app/models/groupe_instructeur.rb +++ b/app/models/groupe_instructeur.rb @@ -19,6 +19,8 @@ class GroupeInstructeur < ApplicationRecord has_many :dossiers has_many :deleted_dossiers has_many :batch_operations, through: :dossiers, source: :batch_operations + has_many :assignments, class_name: 'DossierAssignment', dependent: :nullify, inverse_of: :groupe_instructeur + has_many :previous_assignments, class_name: 'DossierAssignment', dependent: :nullify, inverse_of: :previous_groupe_instructeur has_and_belongs_to_many :exports, dependent: :destroy has_and_belongs_to_many :bulk_messages, dependent: :destroy From 1882f652d5fd9b40f01d54b8fdc8e0a0f5b76e09 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 18 Jul 2023 10:37:45 +0200 Subject: [PATCH 15/15] fix(dossier): do not create groupe instructeur assignements on brouillons --- app/controllers/users/dossiers_controller.rb | 2 -- app/graphql/mutations/dossier_changer_groupe_instructeur.rb | 2 +- app/models/dossier.rb | 6 ++---- spec/models/dossier_assignment_spec.rb | 4 +--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 8f9fed8d8..29239156b 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -542,8 +542,6 @@ module Users errors += format_errors(errors: @dossier.errors) errors += format_errors(errors: @dossier.check_mandatory_and_visible_champs) - RoutingEngine.compute(@dossier) - errors end diff --git a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb index b00cbf9cb..e9f4cb947 100644 --- a/app/graphql/mutations/dossier_changer_groupe_instructeur.rb +++ b/app/graphql/mutations/dossier_changer_groupe_instructeur.rb @@ -11,7 +11,7 @@ module Mutations field :errors, [Types::ValidationErrorType], null: true def resolve(dossier:, groupe_instructeur:) - dossier.assign_to_groupe_instructeur(groupe_instructeur, DossierAssignment.modes.fetch(:manual)) + dossier.assign_to_groupe_instructeur(groupe_instructeur, DossierAssignment.modes.fetch(:manual), current_administrateur) { dossier: } end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 9e1e23122..dc10549d9 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -476,7 +476,6 @@ class Dossier < ApplicationRecord validates :user, presence: true, if: -> { deleted_user_email_never_send.nil? }, unless: -> { prefilled } validates :individual, presence: true, if: -> { revision.procedure.for_individual? } - validates :groupe_instructeur, presence: true, if: -> { !brouillon? } validates_associated :prefilled_champs_public, on: :prefilling @@ -695,12 +694,10 @@ class Dossier < ApplicationRecord previous_groupe_instructeur = self.groupe_instructeur update!(groupe_instructeur:, groupe_instructeur_updated_at: Time.zone.now) - - create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, author&.email) - update!(forced_groupe_instructeur: true) if mode == DossierAssignment.modes.fetch(:manual) if !brouillon? + create_assignment(mode, previous_groupe_instructeur, groupe_instructeur, author&.email) unfollow_stale_instructeurs if author.present? log_dossier_operation(author, :changer_groupe_instructeur, self) @@ -908,6 +905,7 @@ class Dossier < ApplicationRecord MailTemplatePresenterService.create_commentaire_for_state(self) NotificationMailer.send_en_construction_notification(self).deliver_later procedure.compute_dossiers_count + RoutingEngine.compute(self) end def after_passer_en_instruction(h) diff --git a/spec/models/dossier_assignment_spec.rb b/spec/models/dossier_assignment_spec.rb index 84b4db5c2..86fe22676 100644 --- a/spec/models/dossier_assignment_spec.rb +++ b/spec/models/dossier_assignment_spec.rb @@ -16,9 +16,7 @@ RSpec.describe DossierAssignment, type: :model do let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first } - let(:dossier) { create(:dossier, procedure:, groupe_instructeur_id: nil) } - let(:defaut_groupe) { procedure.defaut_groupe_instructeur } - let(:gi_2) { procedure.groupe_instructeurs.find_by(label: 'a second group') } + let(:dossier) { create(:dossier, :en_construction, procedure:).tap { _1.update(groupe_instructeur_id: nil) } } before do RoutingEngine.compute(dossier)