Merge pull request #4236 from betagouv/defaut_groupe_instructeur

Insere un niveau d'indirection entre la procédure et les instructeurs
This commit is contained in:
LeSim 2019-09-02 12:14:02 +02:00 committed by GitHub
commit 940813a3ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 173 additions and 51 deletions

View file

@ -8,7 +8,7 @@ class Admin::AssignsController < AdminController
NOT_ASSIGN = 'not_assign'
def show
assign_scope = @procedure.instructeurs
assign_scope = @procedure.defaut_groupe_instructeur.instructeurs
@instructeurs_assign = smart_listing_create :instructeurs_assign,
assign_scope,

View file

@ -136,9 +136,7 @@ class Admin::ProceduresController < AdminController
render '/admin/procedures/transfer', formats: 'js', status: 404
else
procedure = current_administrateur.procedures.find(params[:procedure_id])
clone_procedure = procedure.clone(admin, false)
clone_procedure.save
procedure.clone(admin, false)
flash.now.notice = "La démarche a correctement été clonée vers le nouvel administrateur."
@ -162,7 +160,7 @@ class Admin::ProceduresController < AdminController
procedure = Procedure.find(params[:procedure_id])
new_procedure = procedure.clone(current_administrateur, cloned_from_library?)
if new_procedure.save
if new_procedure.valid?
flash.notice = 'Démarche clonée'
redirect_to edit_admin_procedure_path(id: new_procedure.id)
else

View file

@ -56,7 +56,7 @@ module Instructeurs
@previous_following_instructeurs_emails = previous_followers.pluck(:email)
@avis_emails = dossier.avis.includes(:instructeur).map(&:email_to_display)
@invites_emails = dossier.invites.map(&:email)
@potential_recipients = procedure.instructeurs.reject { |g| g == current_instructeur }
@potential_recipients = procedure.defaut_groupe_instructeur.instructeurs.reject { |g| g == current_instructeur }
end
def send_to_instructeurs

View file

@ -221,7 +221,7 @@ module Instructeurs
end
def ensure_ownership!
if !procedure.instructeurs.include?(current_instructeur)
if !procedure.defaut_groupe_instructeur.instructeurs.include?(current_instructeur)
flash[:alert] = "Vous n'avez pas accès à cette démarche"
redirect_to root_path
end

View file

@ -1,7 +1,7 @@
module DossierLinkHelper
def dossier_linked_path(user, dossier)
if user.is_a?(Instructeur)
if dossier.procedure.instructeurs.include?(user)
if dossier.procedure.defaut_groupe_instructeur.instructeurs.include?(user)
instructeur_dossier_path(dossier.procedure, dossier)
else
avis = dossier.avis.find_by(instructeur: user)

View file

@ -1,6 +1,7 @@
class AssignTo < ApplicationRecord
belongs_to :procedure
belongs_to :instructeur
belongs_to :groupe_instructeur
has_one :procedure_presentation, dependent: :destroy
scope :with_email_notifications, -> { where(email_notifications_enabled: true) }

View file

@ -0,0 +1,6 @@
class GroupeInstructeur < ApplicationRecord
DEFAULT_LABEL = 'défaut'
belongs_to :procedure
has_many :assign_tos
has_many :instructeurs, through: :assign_tos
end

View file

@ -6,7 +6,8 @@ class Instructeur < ApplicationRecord
before_validation -> { sanitize_email(:email) }
has_many :assign_to, dependent: :destroy
has_many :procedures, through: :assign_to
has_many :groupe_instructeurs, through: :assign_to
has_many :procedures, through: :groupe_instructeurs
has_many :assign_to_with_email_notifications, -> { with_email_notifications }, class_name: 'AssignTo', inverse_of: :instructeur
has_many :procedures_with_email_notifications, through: :assign_to_with_email_notifications, source: :procedure
@ -52,7 +53,10 @@ class Instructeur < ApplicationRecord
def assign_to_procedure(procedure)
begin
procedures << procedure
assign_to.create({
procedure: procedure,
groupe_instructeur: procedure.defaut_groupe_instructeur
})
true
rescue ActiveRecord::RecordNotUnique
false
@ -60,7 +64,7 @@ class Instructeur < ApplicationRecord
end
def remove_from_procedure(procedure)
!!(procedure.in?(procedures) && procedures.destroy(procedure))
!!(procedure.defaut_groupe_instructeur.in?(groupe_instructeurs) && groupe_instructeurs.destroy(procedure.defaut_groupe_instructeur))
end
def last_week_overview

View file

@ -14,10 +14,9 @@ class Procedure < ApplicationRecord
belongs_to :parent_procedure, class_name: 'Procedure'
belongs_to :service
has_many :assign_to, dependent: :destroy
has_many :administrateurs_procedures
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
has_many :instructeurs, through: :assign_to
has_many :groupe_instructeurs, dependent: :destroy
has_one :initiated_mail, class_name: "Mails::InitiatedMail", dependent: :destroy
has_one :received_mail, class_name: "Mails::ReceivedMail", dependent: :destroy
@ -73,6 +72,7 @@ class Procedure < ApplicationRecord
before_save :update_juridique_required
before_save :update_durees_conservation_required
before_create :ensure_path_exists
after_create :ensure_default_groupe_instructeur
include AASM
@ -247,6 +247,8 @@ class Procedure < ApplicationRecord
procedure.service = self.service.clone_and_assign_to_administrateur(admin)
end
procedure.save
admin.instructeur.assign_to_procedure(procedure)
procedure
@ -409,7 +411,7 @@ class Procedure < ApplicationRecord
result << :service
end
if instructeurs.empty?
if missing_instructeurs?
result << :instructeurs
end
@ -476,6 +478,14 @@ class Procedure < ApplicationRecord
end
end
def defaut_groupe_instructeur
groupe_instructeurs.find_by(label: GroupeInstructeur::DEFAULT_LABEL)
end
def missing_instructeurs?
!AssignTo.exists?(groupe_instructeur: groupe_instructeurs)
end
private
def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index)
@ -565,4 +575,10 @@ class Procedure < ApplicationRecord
self.path = SecureRandom.uuid
end
end
def ensure_default_groupe_instructeur
if self.groupe_instructeurs.empty?
groupe_instructeurs.create(label: GroupeInstructeur::DEFAULT_LABEL)
end
end
end

View file

@ -5,9 +5,9 @@
= render partial: '/admin/procedures/modal_transfer'
- if @procedure.brouillon?
- if @procedure.instructeurs.empty? || @procedure.service.nil?
- if @procedure.missing_steps.present?
- missing_elements = []
- if @procedure.instructeurs.empty?
- if @procedure.missing_instructeurs?
- missing_elements << 'des instructeurs'
- if @procedure.service.nil?
- missing_elements << 'un service'
@ -59,7 +59,7 @@
%br
Attention, diffusez toujours le <strong>lien complet</strong> affiché ci-dessus, et non pas un lien générique vers demarches-simplifiees.fr. Ne dites pas non plus aux usagers de se rendre sur le site générique demarches-simplifiees.fr, donnez-leur toujours le lien complet.
- elsif @procedure.brouillon_avec_lien?
- if @procedure.instructeurs.present? && @procedure.service.present?
- if @procedure.missing_steps.empty?
%p
Cette démarche est actuellement <strong>en test</strong>,
pour y accéder vous pouvez utiliser le lien :
@ -106,9 +106,9 @@
- else
.alert.alert-info
Pour pouvoir tester cette démarche, vous devez dabord lui affecter
- if @procedure.instructeurs.empty?
- if @procedure.missing_instructeurs?
= link_to("des instructeurs", admin_procedure_assigns_path(@procedure))
- if @procedure.instructeurs.empty? && @procedure.service.nil?
- if @procedure.missing_instructeurs? && @procedure.service.nil?
et
- if @procedure.service.nil?
= link_to("un service", services_path(procedure_id: @procedure))

View file

@ -0,0 +1,12 @@
class CreateGroupeInstructeurs < ActiveRecord::Migration[5.2]
def change
create_table :groupe_instructeurs do |t|
t.references :procedure, foreign_key: true, null: false
t.text :label, null: false
t.timestamps
end
add_index :groupe_instructeurs, [:procedure_id, :label], unique: true
end
end

View file

@ -0,0 +1,6 @@
class AddGroupeInstructeurColumnToAssignTos < ActiveRecord::Migration[5.2]
def change
add_reference :assign_tos, :groupe_instructeur, foreign_key: true
add_index :assign_tos, [:groupe_instructeur_id, :instructeur_id], unique: true, name: 'unique_couple_groupe_instructeur_instructeur'
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_08_09_073736) do
ActiveRecord::Schema.define(version: 2019_08_19_145355) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -118,6 +118,9 @@ ActiveRecord::Schema.define(version: 2019_08_09_073736) do
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "email_notifications_enabled", default: false, null: false
t.bigint "groupe_instructeur_id"
t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true
t.index ["groupe_instructeur_id"], name: "index_assign_tos_on_groupe_instructeur_id"
t.index ["instructeur_id", "procedure_id"], name: "index_assign_tos_on_instructeur_id_and_procedure_id", unique: true
t.index ["instructeur_id"], name: "index_assign_tos_on_instructeur_id"
t.index ["procedure_id"], name: "index_assign_tos_on_procedure_id"
@ -391,6 +394,15 @@ ActiveRecord::Schema.define(version: 2019_08_09_073736) do
t.index ["source"], name: "index_geo_areas_on_source"
end
create_table "groupe_instructeurs", force: :cascade do |t|
t.bigint "procedure_id", null: false
t.text "label", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["procedure_id", "label"], name: "index_groupe_instructeurs_on_procedure_id_and_label", unique: true
t.index ["procedure_id"], name: "index_groupe_instructeurs_on_procedure_id"
end
create_table "individuals", id: :serial, force: :cascade do |t|
t.string "nom"
t.string "prenom"
@ -625,6 +637,7 @@ ActiveRecord::Schema.define(version: 2019_08_09_073736) do
t.index ["procedure_id"], name: "index_without_continuation_mails_on_procedure_id"
end
add_foreign_key "assign_tos", "groupe_instructeurs"
add_foreign_key "attestation_templates", "procedures"
add_foreign_key "attestations", "dossiers"
add_foreign_key "avis", "instructeurs", column: "claimant_id"
@ -638,6 +651,7 @@ ActiveRecord::Schema.define(version: 2019_08_09_073736) do
add_foreign_key "dossiers", "users"
add_foreign_key "feedbacks", "users"
add_foreign_key "geo_areas", "champs"
add_foreign_key "groupe_instructeurs", "procedures"
add_foreign_key "initiated_mails", "procedures"
add_foreign_key "procedure_presentations", "assign_tos"
add_foreign_key "procedures", "services"

View file

@ -0,0 +1,12 @@
namespace :after_party do
desc 'Deployment task: create_default_groupe_instructeur'
task create_default_groupe_instructeur: :environment do
Procedure.find_each do |procedure|
procedure.groupe_instructeurs.create(label: GroupeInstructeur::DEFAULT_LABEL)
end
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord.create version: '20190819142551'
end
end

View file

@ -0,0 +1,15 @@
namespace :after_party do
desc 'Deployment task: link_assign_and_groupe_instructeur'
task link_assign_and_groupe_instructeur: :environment do
AssignTo.find_each do |at|
GroupeInstructeur
.find_by(procedure_id: at.procedure_id)
&.assign_tos
&.push(at)
end
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord.create version: '20190819145528'
end
end

View file

@ -218,7 +218,7 @@ describe Admin::ProceduresController, type: :controller do
describe "admin can also instruct the procedure as a instructeur" do
subject { Procedure.last }
it { expect(subject.instructeurs).to include(instructeur) }
it { expect(subject.defaut_groupe_instructeur.instructeurs).to include(instructeur) }
end
end
end

View file

@ -103,9 +103,9 @@ describe Instructeurs::ProceduresController, type: :controller do
let(:procedure3) { create(:procedure) }
before do
instructeur.procedures << procedure1
instructeur.procedures << procedure2
instructeur.procedures << procedure3
instructeur.groupe_instructeurs << procedure1.defaut_groupe_instructeur
instructeur.groupe_instructeurs << procedure2.defaut_groupe_instructeur
instructeur.groupe_instructeurs << procedure3.defaut_groupe_instructeur
subject
end
@ -117,7 +117,7 @@ describe Instructeurs::ProceduresController, type: :controller do
let(:dossier) { create(:dossier, state: state, procedure: procedure) }
before do
instructeur.procedures << procedure
instructeur.groupe_instructeurs << procedure.defaut_groupe_instructeur
dossier
end
@ -141,7 +141,7 @@ describe Instructeurs::ProceduresController, type: :controller do
create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction))
create(:dossier, procedure: procedure, state: Dossier.states.fetch(:sans_suite), archived: true)
instructeur.procedures << procedure2
instructeur.groupe_instructeurs << procedure2.defaut_groupe_instructeur
create(:dossier, :followed, procedure: procedure2, state: Dossier.states.fetch(:en_construction))
create(:dossier, procedure: procedure2, state: Dossier.states.fetch(:accepte))
instructeur.followed_dossiers << create(:dossier, procedure: procedure2, state: Dossier.states.fetch(:en_instruction))

View file

@ -5,7 +5,7 @@ describe Instructeurs::RechercheController, type: :controller do
let(:dossier2) { create(:dossier, :en_construction, procedure: dossier.procedure) }
let(:instructeur) { create(:instructeur) }
before { instructeur.procedures << dossier2.procedure }
before { instructeur.groupe_instructeurs << dossier2.procedure.defaut_groupe_instructeur }
describe 'GET #index' do
before { sign_in(instructeur.user) }

View file

@ -32,7 +32,7 @@ describe InvitesController, type: :controller do
context 'when instructeur has access to dossier' do
before do
signed_in_profile.instructeur.procedures << dossier.procedure
signed_in_profile.instructeur.groupe_instructeurs << dossier.procedure.defaut_groupe_instructeur
end
it_behaves_like "he can not create invitation"

View file

@ -17,7 +17,7 @@ describe RootController, type: :controller do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
before do
instructeur.procedures << procedure
instructeur.groupe_instructeurs << procedure.defaut_groupe_instructeur
sign_in(instructeur.user)
end

View file

@ -14,6 +14,7 @@ FactoryBot.define do
transient do
administrateur {}
instructeurs { [] }
end
after(:build) do |procedure, evaluator|
@ -24,6 +25,10 @@ FactoryBot.define do
end
end
after(:create) do |procedure, evaluator|
evaluator.instructeurs.each { |i| i.assign_to_procedure(procedure) }
end
factory :procedure_with_dossiers do
transient do
dossiers_count { 1 }
@ -61,8 +66,8 @@ FactoryBot.define do
end
trait :with_instructeur do
after(:build) do |procedure, _evaluator|
procedure.instructeurs << create(:instructeur)
after(:create) do |procedure, _evaluator|
procedure.defaut_groupe_instructeur.instructeurs << create(:instructeur)
end
end

View file

@ -171,7 +171,7 @@ feature 'The instructeur part' do
scenario 'A instructeur can send a dossier to several instructeurs', js: true do
instructeur_2 = FactoryBot.create(:instructeur)
instructeur_3 = FactoryBot.create(:instructeur)
procedure.instructeurs << [instructeur_2, instructeur_3]
procedure.defaut_groupe_instructeur.instructeurs << [instructeur_2, instructeur_3]
send_dossier = double()
expect(InstructeurMailer).to receive(:send_dossier).and_return(send_dossier).twice

View file

@ -1,8 +1,8 @@
require "spec_helper"
feature "procedure filters" do
let(:procedure) { create(:procedure, :published, :with_type_de_champ) }
let(:instructeur) { create(:instructeur, procedures: [procedure]) }
let(:instructeur) { create(:instructeur) }
let(:procedure) { create(:procedure, :published, :with_type_de_champ, instructeurs: [instructeur]) }
let!(:type_de_champ) { procedure.types_de_champ.first }
let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
let!(:champ) { Champ.find_by(type_de_champ_id: type_de_champ.id, dossier_id: new_unfollow_dossier.id) }

View file

@ -18,7 +18,7 @@ describe DossierLinkHelper do
let(:dossier) { create(:dossier) }
let(:instructeur) { create(:instructeur) }
before { dossier.procedure.instructeurs << instructeur }
before { dossier.procedure.defaut_groupe_instructeur.instructeurs << instructeur }
it { expect(helper.dossier_linked_path(instructeur, dossier)).to eq(instructeur_dossier_path(dossier.procedure, dossier)) }
end

View file

@ -19,6 +19,7 @@ describe '20190117154829_delete_dossiers_without_procedure.rake' do
before do
procedure_2_dossier_ids
procedure2.defaut_groupe_instructeur.delete
procedure2.delete
expect(procedure_2_dossier_ids.count).to eq(2)
expect(Dossier.find_by(id: procedure_2_dossier_ids.first).procedure).to be nil

View file

@ -235,10 +235,10 @@ describe Dossier do
end
describe '#avis_for' do
let!(:procedure) { create(:procedure, :published) }
let!(:instructeur) { create(:instructeur) }
let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) }
let!(:dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction)) }
let!(:instructeur) { create(:instructeur, procedures: [procedure]) }
let!(:expert_1) { create(:instructeur) }
let!(:expert_2) { create(:instructeur) }
@ -615,7 +615,7 @@ describe Dossier do
let(:dossier) { create(:dossier, :en_construction, :followed) }
let!(:non_following_instructeur) do
non_following_instructeur = create(:instructeur)
non_following_instructeur.procedures << dossier.procedure
non_following_instructeur.groupe_instructeurs << dossier.procedure.defaut_groupe_instructeur
non_following_instructeur
end

View file

@ -97,6 +97,10 @@ describe Instructeur, type: :model do
it { is_expected.to be_truthy }
it { expect { subject }.to change(instructeur.procedures, :count) }
it do
subject
expect(instructeur.groupe_instructeurs).to include(procedure_to_assign.defaut_groupe_instructeur)
end
end
context "with an already assigned procedure" do
@ -147,17 +151,21 @@ describe Instructeur, type: :model do
after { Timecop.return }
context 'when no procedure published was active last week' do
let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur2], libelle: 'procedure') }
let!(:procedure) { create(:procedure, :published, libelle: 'procedure') }
before { instructeur2.assign_to_procedure(procedure) }
context 'when the instructeur has no notifications' do
it { is_expected.to eq(nil) }
end
end
context 'when a procedure published was active' do
let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur2], libelle: 'procedure') }
let!(:procedure) { create(:procedure, :published, libelle: 'procedure') }
let(:procedure_overview) { double('procedure_overview', 'had_some_activities?'.to_sym => true) }
before :each do
instructeur2.assign_to_procedure(procedure)
expect_any_instance_of(Procedure).to receive(:procedure_overview).and_return(procedure_overview)
end
@ -165,10 +173,11 @@ describe Instructeur, type: :model do
end
context 'when a procedure not published was active with no notifications' do
let!(:procedure) { create(:procedure, instructeurs: [instructeur2], libelle: 'procedure') }
let!(:procedure) { create(:procedure, libelle: 'procedure') }
let(:procedure_overview) { double('procedure_overview', 'had_some_activities?'.to_sym => true) }
before :each do
instructeur2.assign_to_procedure(procedure)
allow_any_instance_of(Procedure).to receive(:procedure_overview).and_return(procedure_overview)
end
@ -255,7 +264,7 @@ describe Instructeur, type: :model do
let!(:dossier) { create(:dossier, :followed, state: Dossier.states.fetch(:en_construction)) }
let(:instructeur) { dossier.follows.first.instructeur }
let(:procedure) { dossier.procedure }
let!(:instructeur_2) { create(:instructeur, procedures: [procedure]) }
let!(:instructeur_2) { create(:instructeur, groupe_instructeurs: [procedure.defaut_groupe_instructeur]) }
let!(:dossier_on_procedure_2) { create(:dossier, :followed, state: Dossier.states.fetch(:en_construction)) }
let!(:instructeur_on_procedure_2) { dossier_on_procedure_2.follows.first.instructeur }
@ -384,7 +393,7 @@ describe Instructeur, type: :model do
let(:procedure_to_assign) { create(:procedure) }
before do
create(:assign_to, instructeur: instructeur, procedure: procedure_to_assign, email_notifications_enabled: true)
create(:assign_to, instructeur: instructeur, procedure: procedure_to_assign, email_notifications_enabled: true, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur)
end
context 'when a dossier in construction exists' do
@ -429,6 +438,6 @@ describe Instructeur, type: :model do
private
def assign(procedure_to_assign)
create :assign_to, instructeur: instructeur, procedure: procedure_to_assign
create :assign_to, instructeur: instructeur, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur
end
end

View file

@ -401,7 +401,7 @@ describe Procedure do
subject { @procedure }
it { expect(subject.parent_procedure).to eq(procedure) }
it { expect(subject.instructeurs.pluck(:email)).to eq([administrateur.email]) }
it { expect(subject.defaut_groupe_instructeur.instructeurs.pluck(:email)).to eq([administrateur.email]) }
it 'should duplicate specific objects with different id' do
expect(subject.id).not_to eq(procedure.id)
@ -882,4 +882,27 @@ describe Procedure do
end
end
end
describe '.ensure_a_groupe_instructeur_exists' do
let!(:procedure) { create(:procedure) }
it { expect(procedure.groupe_instructeurs.count).to eq(1) }
it { expect(procedure.groupe_instructeurs.first.label).to eq(GroupeInstructeur::DEFAULT_LABEL) }
end
describe '.missing_instructeurs?' do
let!(:procedure) { create(:procedure) }
subject { procedure.missing_instructeurs? }
it { is_expected.to be true }
context 'when an instructeur is assign to this procedure' do
let!(:instructeur) { create(:instructeur) }
before { instructeur.assign_to_procedure(procedure) }
it { is_expected.to be false }
end
end
end

View file

@ -15,8 +15,8 @@ describe DossierSearchService do
let(:instructeur_2) { create(:instructeur, administrateurs: [administrateur_2]) }
before do
create :assign_to, instructeur: instructeur_1, procedure: procedure_1
create :assign_to, instructeur: instructeur_2, procedure: procedure_2
instructeur_1.assign_to_procedure(procedure_1)
instructeur_2.assign_to_procedure(procedure_2)
end
let(:procedure_1) { create(:procedure, :published, administrateur: administrateur_1) }

View file

@ -4,7 +4,7 @@ describe 'admin/assigns/show.html.haml', type: :view do
let(:admin) { create(:administrateur) }
let(:procedure) { create :procedure, administrateur: admin }
let(:assign_instructeurs) { procedure.instructeurs }
let(:assign_instructeurs) { procedure.defaut_groupe_instructeur.instructeurs }
let(:not_assign_instructeurs) { admin.instructeurs.where.not(id: assign_instructeurs.ids) }
before do

View file

@ -9,7 +9,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
end
describe 'procedure is draft' do
context 'when procedure does not have a gestionnare affected' do
context 'when procedure does not have a instructeur affected' do
before do
render
end
@ -21,9 +21,9 @@ describe 'admin/procedures/show.html.haml', type: :view do
end
end
context 'when procedure have a gestionnare affected' do
context 'when procedure have a instructeur affected' do
before do
create :assign_to, instructeur: create(:instructeur), procedure: procedure
create(:instructeur).assign_to_procedure(procedure)
render
end