Merge pull request #8916 from demarches-simplifiees/can-update-defaut-groupe-instructeur-2

feat(routage): permet de changer le groupe par défaut
This commit is contained in:
Paul Chavard 2023-04-20 08:28:46 +00:00 committed by GitHub
commit 586286cb08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 106 additions and 35 deletions

View file

@ -1,6 +1,11 @@
.groupe-instructeur { .groupe-instructeur {
.actions { .setup {
width: 200px;
text-align: center; text-align: center;
width: 100px;
}
.actions {
text-align: center;
width: 250px;
} }
} }

View file

@ -29,6 +29,10 @@
.value { .value {
width: 200px; width: 200px;
select {
width: 100%;
}
} }
} }
@ -56,4 +60,13 @@
border-color: $dark-red; border-color: $dark-red;
} }
} }
.form.defaut-groupe {
padding: $default-spacer;
label {
width: 600px;
font-size: 16px;
}
}
} }

View file

@ -1,7 +1,7 @@
--- ---
fr: fr:
select: Sélectionner select: Sélectionner
apply_routing_rules: Appliquer des règles de routage apply_routing_rules: Règles de routage
routing_rules_notice_html: | routing_rules_notice_html: |
<p>Ajoutez des règles de routage à partir de champs « choix simple » créés dans le <a href="%{path}">formulaire</a>.</p> <p>Ajoutez des règles de routage à partir de champs « choix simple » créés dans le <a href="%{path}">formulaire</a>.</p>
<p>Les dossiers seront routées vers le premier groupe affiché dont la règle correspond.</p> <p>Les dossiers seront routées vers le premier groupe affiché dont la règle correspond.</p>

View file

@ -1,6 +1,5 @@
.card#routing-rules .card#routing-rules
.card-title %h2.card-title= t('.apply_routing_rules')
= t('.apply_routing_rules')
- if can_route? - if can_route?
.notice .notice
= t('.routing_rules_notice_html', path: champs_admin_procedure_path(@procedure_id)) = t('.routing_rules_notice_html', path: champs_admin_procedure_path(@procedure_id))
@ -28,5 +27,14 @@
%td.target= targeted_champ_tag(targeted_champ, row_index) %td.target= targeted_champ_tag(targeted_champ, row_index)
%td.operator est égal à %td.operator est égal à
%td.value= value_tag(targeted_champ, value, row_index) %td.value= value_tag(targeted_champ, value, row_index)
= form_tag admin_procedure_update_defaut_groupe_instructeur_path(@procedure_id),
class: 'form flex align-baseline defaut-groupe',
data: { controller: 'autosave' } do
= label_tag :defaut_groupe_instructeur_id, 'Et si aucune règle ne correspond, router vers :'
= select_tag :defaut_groupe_instructeur_id,
options_for_select(@groupe_instructeurs.pluck(:label, :id), selected: @revision.procedure.defaut_groupe_instructeur.id),
class: 'width-100'
- else - else
.notice= t('.routing_rules_warning_html', path: champs_admin_procedure_path(@procedure_id)) .notice= t('.routing_rules_warning_html', path: champs_admin_procedure_path(@procedure_id))

View file

@ -48,7 +48,10 @@ module Administrateurs
def update def update
@groupe_instructeur = groupe_instructeur @groupe_instructeur = groupe_instructeur
if @groupe_instructeur.update(groupe_instructeur_params) if closed_params? && @groupe_instructeur.id == procedure.defaut_groupe_instructeur.id
redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur),
alert: "Il est impossible de désactiver le groupe dinstructeurs par défaut."
elsif @groupe_instructeur.update(groupe_instructeur_params)
redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur), redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur),
notice: "Le nom est à présent « #{@groupe_instructeur.label} »." notice: "Le nom est à présent « #{@groupe_instructeur.label} »."
else else
@ -68,6 +71,8 @@ module Administrateurs
flash[:alert] = "Impossible de supprimer un groupe avec des dossiers. Il faut le réaffecter avant" flash[:alert] = "Impossible de supprimer un groupe avec des dossiers. Il faut le réaffecter avant"
elsif procedure.groupe_instructeurs.one? elsif procedure.groupe_instructeurs.one?
flash[:alert] = "Suppression impossible : il doit y avoir au moins un groupe instructeur sur chaque procédure" flash[:alert] = "Suppression impossible : il doit y avoir au moins un groupe instructeur sur chaque procédure"
elsif @groupe_instructeur.id == procedure.defaut_groupe_instructeur.id
flash[:alert] = "Suppression impossible : le groupe « #{@groupe_instructeur.label} » est le groupe par défaut."
else else
@groupe_instructeur.destroy! @groupe_instructeur.destroy!
if procedure.groupe_instructeurs.active.one? if procedure.groupe_instructeurs.active.one?
@ -258,6 +263,10 @@ module Administrateurs
private private
def closed_params?
groupe_instructeur_params[:closed] == "1"
end
def procedure def procedure
current_administrateur current_administrateur
.procedures .procedures

View file

@ -12,6 +12,11 @@ module Administrateurs
groupe_instructeur.update!(routing_rule: ds_eq(left, right)) groupe_instructeur.update!(routing_rule: ds_eq(left, right))
end end
def update_defaut_groupe_instructeur
new_defaut = @procedure.groupe_instructeurs.find(defaut_groupe_instructeur_id)
@procedure.update!(defaut_groupe_instructeur: new_defaut)
end
private private
def targeted_champ_changed? def targeted_champ_changed?
@ -19,11 +24,11 @@ module Administrateurs
end end
def targeted_champ def targeted_champ
Logic.from_json(routing_params[:targeted_champ]) Logic.from_json(params[:targeted_champ])
end end
def value def value
Logic.from_json(routing_params[:value]) Logic.from_json(params[:value])
end end
def groupe_instructeur def groupe_instructeur
@ -31,11 +36,11 @@ module Administrateurs
end end
def groupe_instructeur_id def groupe_instructeur_id
routing_params[:groupe_instructeur_id] params[:groupe_instructeur_id]
end end
def routing_params def defaut_groupe_instructeur_id
params.permit(:targeted_champ, :value, :groupe_instructeur_id) params[:defaut_groupe_instructeur_id]
end end
end end
end end

View file

@ -21,6 +21,8 @@ class GroupeInstructeur < ApplicationRecord
has_and_belongs_to_many :exports, dependent: :destroy has_and_belongs_to_many :exports, dependent: :destroy
has_and_belongs_to_many :bulk_messages, dependent: :destroy has_and_belongs_to_many :bulk_messages, dependent: :destroy
has_one :defaut_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :defaut_groupe_instructeur_id, dependent: :nullify, inverse_of: :defaut_groupe_instructeur
validates :label, presence: true, allow_nil: false validates :label, presence: true, allow_nil: false
validates :label, uniqueness: { scope: :procedure } validates :label, uniqueness: { scope: :procedure }
validates :closed, acceptance: { accept: [false] }, if: -> { closed_changed? && self.procedure.groupe_instructeurs.active.one? } validates :closed, acceptance: { accept: [false] }, if: -> { closed_changed? && self.procedure.groupe_instructeurs.active.one? }

View file

@ -208,7 +208,7 @@ class Procedure < ApplicationRecord
has_one :refused_mail, class_name: "Mails::RefusedMail", dependent: :destroy has_one :refused_mail, class_name: "Mails::RefusedMail", dependent: :destroy
has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy has_one :without_continuation_mail, class_name: "Mails::WithoutContinuationMail", dependent: :destroy
has_one :defaut_groupe_instructeur, -> { active.order(id: :asc) }, class_name: 'GroupeInstructeur', inverse_of: false belongs_to :defaut_groupe_instructeur, class_name: 'GroupeInstructeur', inverse_of: false, optional: true
has_one_attached :logo has_one_attached :logo
has_one_attached :notice has_one_attached :notice

View file

@ -11,8 +11,7 @@
= f.submit t('.button.rename'), class: 'button primary send' = f.submit t('.button.rename'), class: 'button primary send'
.card .card
.card-title %h2.card-title= t('.group_management.title')
= t('.group_management.title')
= form_for :groupe_instructeur, html: { class: 'form' } do |f| = form_for :groupe_instructeur, html: { class: 'form' } do |f|
= f.label :label do = f.label :label do
@ -46,13 +45,13 @@
%tr %tr
// i18n-tasks-use t('.existing_groupe') // i18n-tasks-use t('.existing_groupe')
%th{ colspan: 2 }= t(".existing_groupe", count: groupes_instructeurs.total_count) %th{ colspan: 2 }= t(".existing_groupe", count: groupes_instructeurs.total_count)
%th %th.actions
= link_to "Exporter au format CSV", export_groupe_instructeurs_admin_procedure_groupe_instructeurs_path(procedure, format: :csv) = link_to "Exporter au format CSV", export_groupe_instructeurs_admin_procedure_groupe_instructeurs_path(procedure, format: :csv)
%tbody %tbody
- groupes_instructeurs.each do |group| - groupes_instructeurs.each do |group|
%tr %tr
%td= group.label %td= group.label
%td.actions= link_to t('.set_up'), admin_procedure_groupe_instructeur_path(procedure, group) %td.setup= link_to t('.set_up'), admin_procedure_groupe_instructeur_path(procedure, group)
- if group.can_delete? - if group.can_delete?
%td.actions %td.actions
= link_to admin_procedure_groupe_instructeur_path(procedure, group), { method: :delete, class: 'button', data: { confirm: t('.group_management.delete_confirmation', group_name: group.label) }} do = link_to admin_procedure_groupe_instructeur_path(procedure, group), { method: :delete, class: 'button', data: { confirm: t('.group_management.delete_confirmation', group_name: group.label) }} do

View file

@ -506,6 +506,7 @@ Rails.application.routes.draw do
end end
patch :update, controller: 'routing', as: :routing_rules patch :update, controller: 'routing', as: :routing_rules
patch :update_defaut_groupe_instructeur, controller: 'routing', as: :update_defaut_groupe_instructeur
put 'clone' put 'clone'
put 'archive' put 'archive'

View file

@ -83,15 +83,15 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
} }
end end
context 'with only one group' do context 'default group' do
before do before do
delete_group gi_1_1 delete_group gi_1_1
delete_group gi_1_2
end end
it { expect(flash.alert).to be_present } it { expect(flash.alert).to be_present }
it { expect(flash.alert).to eq "Suppression impossible : le groupe « défaut » est le groupe par défaut." }
it { expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure)) } it { expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure)) }
it { expect(procedure.groupe_instructeurs.count).to eq(1) } it { expect(procedure.groupe_instructeurs.count).to eq(2) }
end end
context 'with many groups' do context 'with many groups' do
@ -181,7 +181,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
describe '#update' do describe '#update' do
let(:new_name) { 'nouveau nom du groupe' } let(:new_name) { 'nouveau nom du groupe' }
let(:closed_value) { false } let(:closed_value) { '0' }
let!(:procedure_non_routee) { create(:procedure, :published, :for_individual, administrateurs: [admin]) } let!(:procedure_non_routee) { create(:procedure, :published, :for_individual, administrateurs: [admin]) }
let!(:gi_1_1) { procedure_non_routee.defaut_groupe_instructeur } let!(:gi_1_1) { procedure_non_routee.defaut_groupe_instructeur }
@ -195,26 +195,33 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
gi_1_1.reload gi_1_1.reload
end end
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_1)) } it do
it { expect(gi_1_1.label).to eq(new_name) } expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_1))
it { expect(gi_1_1.closed).to eq(false) } expect(gi_1_1.label).to eq(new_name)
it { expect(flash.notice).to be_present } expect(gi_1_1.closed).to eq(false)
expect(flash.notice).to be_present
end
context 'when we try do disable the only groupe instructeur' do context 'when we try do disable the default groupe instructeur' do
let(:closed_value) { true } let(:closed_value) { '1' }
let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
it { expect(response).to render_template(:show) } it do
it { expect(gi_1_1.label).not_to eq(new_name) } expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_1)
it { expect(gi_1_1.closed).to eq(false) } expect(gi_1_1.label).not_to eq(new_name)
it { expect(flash.alert).to eq(['Il doit y avoir au moins un groupe instructeur actif sur chaque démarche']) } expect(gi_1_1.closed).to eq(false)
expect(flash.alert).to eq('Il est impossible de désactiver le groupe dinstructeurs par défaut.')
end
end end
context 'when the name is already taken' do context 'when the name is already taken' do
let!(:gi_1_2) { procedure_non_routee.groupe_instructeurs.create(label: 'groupe instructeur 2') } let!(:gi_1_2) { procedure_non_routee.groupe_instructeurs.create(label: 'groupe instructeur 2') }
let(:new_name) { gi_1_2.label } let(:new_name) { gi_1_2.label }
it { expect(gi_1_1.label).not_to eq(new_name) } it do
it { expect(flash.alert).to eq(['Le libellé est déjà utilisé(e)']) } expect(gi_1_1.label).not_to eq(new_name)
expect(flash.alert).to eq(['Le libellé est déjà utilisé(e)'])
end
end end
end end

View file

@ -49,4 +49,22 @@ describe Administrateurs::RoutingController, type: :controller do
end end
end end
end end
describe "#update_defaut_groupe_instructeur" do
let(:procedure) { create(:procedure) }
let(:gi_2) { procedure.groupe_instructeurs.create(label: 'groupe 2') }
let(:params) do
{
procedure_id: procedure.id,
defaut_groupe_instructeur_id: gi_2.id
}
end
before do
post :update_defaut_groupe_instructeur, params: params, format: :turbo_stream
procedure.reload
end
it { expect(procedure.defaut_groupe_instructeur.id).to eq(gi_2.id) }
end
end end

View file

@ -27,6 +27,7 @@ FactoryBot.define do
end end
after(:build) do |procedure, evaluator| after(:build) do |procedure, evaluator|
procedure.defaut_groupe_instructeur = procedure.groupe_instructeurs.first
initial_revision = build(:procedure_revision, procedure: procedure, dossier_submitted_message: evaluator.dossier_submitted_message) initial_revision = build(:procedure_revision, procedure: procedure, dossier_submitted_message: evaluator.dossier_submitted_message)
if evaluator.types_de_champ_public.present? if evaluator.types_de_champ_public.present?

View file

@ -100,9 +100,12 @@ describe GroupeInstructeur, type: :model do
describe "active group validations" do describe "active group validations" do
context "there is at least one active groupe instructeur" do context "there is at least one active groupe instructeur" do
let!(:gi_active) { create(:groupe_instructeur, procedure:, closed: false) } let(:gi_active) { procedure.defaut_groupe_instructeur }
let!(:gi_closed) { create(:groupe_instructeur, procedure:, closed: true) } let(:gi_closed) { create(:groupe_instructeur, procedure:) }
before { procedure.defaut_groupe_instructeur.destroy! } before do
gi_active
gi_closed.update(closed: true)
end
it "closed is valid when there is one other active groupe" do it "closed is valid when there is one other active groupe" do
expect(gi_active).to be_valid expect(gi_active).to be_valid