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:
commit
586286cb08
14 changed files with 106 additions and 35 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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 d’instructeurs 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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? }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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 d’instructeurs 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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue