Merge pull request #6480 from tchak/feat-instructeurs-pour-tous

Instructeurs autogérés
This commit is contained in:
Paul Chavard 2021-09-27 15:21:25 +02:00 committed by GitHub
commit dff96e0497
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 148 additions and 82 deletions

View file

@ -122,6 +122,16 @@ module Instructeurs
.deleted_dossiers
.order(:dossier_id)
.page params[:page]
@a_suivre_count, @suivis_count, @traites_count, @tous_count, @archives_count = current_instructeur
.dossiers_count_summary(groupe_instructeur_ids)
.fetch_values('a_suivre', 'suivis', 'traites', 'tous', 'archives')
notifications = current_instructeur.notifications_for_groupe_instructeurs(groupe_instructeur_ids)
@has_en_cours_notifications = notifications[:en_cours].present?
@has_termine_notifications = notifications[:termines].present?
@statut = 'supprime'
end
def update_displayed_fields

View file

@ -196,6 +196,13 @@ module NewAdministrateur
notice: "Le routage est activé."
end
def update_instructeurs_self_management_enabled
procedure.update!(instructeurs_self_management_enabled_params)
redirect_to admin_procedure_groupe_instructeurs_path(procedure),
notice: "Lautogestion des instructeurs est #{procedure.instructeurs_self_management_enabled? ? "activée" : "désactivée"}."
end
def import
if !CSV_ACCEPTED_CONTENT_TYPES.include?(group_csv_file.content_type) && !CSV_ACCEPTED_CONTENT_TYPES.include?(marcel_content_type)
flash[:alert] = "Importation impossible : veuillez importer un fichier CSV"
@ -297,5 +304,9 @@ module NewAdministrateur
def marcel_content_type
Marcel::MimeType.for(group_csv_file.read, name: group_csv_file.original_filename, declared_type: group_csv_file.content_type)
end
def instructeurs_self_management_enabled_params
params.require(:procedure).permit(:instructeurs_self_management_enabled)
end
end
end

View file

@ -57,4 +57,15 @@ module ProcedureHelper
def procedure_auto_archive_datetime(procedure)
procedure_auto_archive_date(procedure) + ' ' + procedure_auto_archive_time(procedure)
end
def can_manage_groupe_instructeurs?(procedure)
procedure.routee? && current_administrateur&.owns?(procedure)
end
def can_send_groupe_message?(procedure)
procedure.dossiers
.state_brouillon
.includes(:groupe_instructeur)
.exists?(groupe_instructeur: current_instructeur.groupe_instructeurs)
end
end

View file

@ -25,6 +25,7 @@
# experts_require_administrateur_invitation :boolean default(FALSE)
# for_individual :boolean default(FALSE)
# hidden_at :datetime
# instructeurs_self_management_enabled :boolean
# juridique_required :boolean default(TRUE)
# libelle :string
# lien_demarche :string
@ -636,6 +637,10 @@ class Procedure < ApplicationRecord
routing_enabled? || groupe_instructeurs.size > 1
end
def instructeurs_self_management?
routee? || instructeurs_self_management_enabled?
end
def defaut_groupe_instructeur_for_new_dossier
if !routee? || feature_enabled?(:procedure_routage_api)
defaut_groupe_instructeur

View file

@ -1,12 +1,23 @@
- content_for(:title, "Instructeurs du groupe #{@groupe_instructeur.label}")
- if @procedure.routee?
- content_for(:title, "Instructeurs du groupe #{@groupe_instructeur.label}")
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to(@procedure.libelle, instructeur_procedure_path(@procedure)),
link_to('Groupes dinstructeurs', instructeur_groupes_path(@procedure)),
@groupe_instructeur.label] }
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to(@procedure.libelle, instructeur_procedure_path(@procedure)),
link_to('Groupes dinstructeurs', instructeur_groupes_path(@procedure)),
@groupe_instructeur.label] }
- else
- content_for(:title, "Instructeurs de la démarche #{@procedure.libelle}")
= render partial: 'new_administrateur/breadcrumbs',
locals: { steps: [link_to(@procedure.libelle, instructeur_procedure_path(@procedure)), 'Instructeurs'] }
.container.groupe-instructeur
%h1 Groupe « #{@groupe_instructeur.label} »
%h1
- if @procedure.routee?
Groupe « #{@groupe_instructeur.label} »
- else
Démarche « #{@procedure.libelle} »
.card.mt-2
.card-title Gestion des instructeurs
@ -27,10 +38,11 @@
- @instructeurs.each do |instructeur|
%tr
%td= instructeur.email
- confirmation_message = @procedure.routee? ? "Êtes-vous sûr de vouloir retirer linstructeur « #{instructeur.email} » du groupe « #{@groupe_instructeur.label} » ?" : "Êtes-vous sûr de vouloir retirer linstructeur « #{instructeur.email} » de la démarche ?"
%td.actions= button_to 'retirer',
{ action: :remove_instructeur },
{ method: :delete,
data: { confirm: "Êtes-vous sûr de vouloir retirer linstructeur « #{instructeur.email} » du groupe  « #{@groupe_instructeur.label} » ?" },
data: { confirm: confirmation_message },
params: { instructeur: { id: instructeur.id }},
class: 'button' }

View file

@ -0,0 +1,46 @@
.procedure-header
%h1= procedure_libelle procedure
= link_to 'gestion des notifications', email_notifications_instructeur_procedure_path(procedure), class: 'header-link'
|
= link_to 'statistiques', stats_instructeur_procedure_path(procedure), class: 'header-link'
- if procedure.instructeurs_self_management?
|
- if can_manage_groupe_instructeurs?(procedure)
= link_to 'instructeurs', admin_procedure_groupe_instructeurs_path(procedure), class: 'header-link'
- elsif procedure.routee?
= link_to 'instructeurs', instructeur_groupes_path(procedure), class: 'header-link'
- else
= link_to 'instructeurs', instructeur_groupe_path(procedure, procedure.defaut_groupe_instructeur), class: 'header-link'
- if can_send_groupe_message?(procedure)
|
= link_to 'contacter les usagers (brouillon)', email_usagers_instructeur_procedure_path(procedure), class: 'header-link'
%ul.tabs
= tab_item('à suivre',
instructeur_procedure_path(procedure, statut: 'a-suivre'),
active: statut == 'a-suivre',
badge: number_with_html_delimiter(a_suivre_count))
= tab_item(t('pluralize.followed', count: suivis_count),
instructeur_procedure_path(procedure, statut: 'suivis'),
active: statut == 'suivis',
badge: number_with_html_delimiter(suivis_count),
notification: has_en_cours_notifications)
= tab_item(t('pluralize.processed', count: traites_count),
instructeur_procedure_path(procedure, statut: 'traites'),
active: statut == 'traites',
badge: number_with_html_delimiter(traites_count),
notification: has_termine_notifications)
= tab_item('au total',
instructeur_procedure_path(procedure, statut: 'tous'),
active: statut == 'tous',
badge: number_with_html_delimiter(tous_count))
= tab_item(t('pluralize.archived', count: archives_count),
instructeur_procedure_path(procedure, statut: 'archives'),
active: statut == 'archives',
badge: number_with_html_delimiter(archives_count))

View file

@ -7,35 +7,15 @@
.procedure-logo{ style: "background-image: url(#{@procedure.logo_url})",
role: 'img', 'aria-label': "logo de la démarche #{@procedure.libelle}" }
.procedure-header
%h1= procedure_libelle @procedure
= link_to 'gestion des notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'header-link'
|
= link_to 'statistiques', stats_instructeur_procedure_path(@procedure), class: 'header-link'
- if @procedure.routee?
|
- if current_administrateur.present? && current_administrateur.owns?(@procedure)
= link_to 'instructeurs', admin_procedure_groupe_instructeurs_path(@procedure), class: 'header-link'
- else
= link_to 'instructeurs', instructeur_groupes_path(@procedure), class: 'header-link'
%ul.tabs
= tab_item('à suivre',
instructeur_procedure_path(@procedure, statut: 'a-suivre'))
= tab_item(t('pluralize.followed', count: 1),
instructeur_procedure_path(@procedure, statut: 'suivis'),
active: @statut == 'suivis')
= tab_item(t('pluralize.processed', count: 1),
instructeur_procedure_path(@procedure, statut: 'traites'))
= tab_item('tous les dossiers',
instructeur_procedure_path(@procedure, statut: 'tous'))
= tab_item(t('pluralize.archived', count: 1),
instructeur_procedure_path(@procedure, statut: 'archives'),
active: true)
= render partial: 'header', locals: { procedure: @procedure,
statut: @statut,
a_suivre_count: @a_suivre_count,
suivis_count: @suivis_count,
traites_count: @traites_count,
tous_count: @tous_count,
archives_count: @archives_count,
has_en_cours_notifications: @has_en_cours_notifications,
has_termine_notifications: @has_termine_notifications }
.container
%h1.titre-dossiers Dossiers supprimés

View file

@ -7,49 +7,15 @@
.procedure-logo{ style: "background-image: url(#{@procedure.logo_url})",
role: 'img', 'aria-label': "logo de la démarche #{@procedure.libelle}" }
.procedure-header
%h1= procedure_libelle @procedure
= link_to 'gestion des notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'header-link'
|
= link_to 'statistiques', stats_instructeur_procedure_path(@procedure), class: 'header-link'
- if @procedure.routee?
|
- if current_administrateur.present? && current_administrateur.owns?(@procedure)
= link_to 'instructeurs', admin_procedure_groupe_instructeurs_path(@procedure), class: 'header-link'
- else
= link_to 'instructeurs', instructeur_groupes_path(@procedure), class: 'header-link'
- if @procedure.dossiers.state_brouillon.where(groupe_instructeur: current_instructeur.groupe_instructeur_ids).includes(:groupe_instructeur).present?
|
= link_to 'contacter les usagers (brouillon)', email_usagers_instructeur_procedure_path(@procedure), class: 'header-link'
%ul.tabs
= tab_item('à suivre',
instructeur_procedure_path(@procedure, statut: 'a-suivre'),
active: @statut == 'a-suivre',
badge: number_with_html_delimiter(@a_suivre_count))
= tab_item(t('pluralize.followed', count: @suivis_count),
instructeur_procedure_path(@procedure, statut: 'suivis'),
active: @statut == 'suivis',
badge: number_with_html_delimiter(@suivis_count),
notification: @has_en_cours_notifications)
= tab_item(t('pluralize.processed', count: @traites_count),
instructeur_procedure_path(@procedure, statut: 'traites'),
active: @statut == 'traites',
badge: number_with_html_delimiter(@traites_count),
notification: @has_termine_notifications)
= tab_item('au total',
instructeur_procedure_path(@procedure, statut: 'tous'),
active: @statut == 'tous',
badge: number_with_html_delimiter(@tous_count))
= tab_item(t('pluralize.archived', count: @archives_count),
instructeur_procedure_path(@procedure, statut: 'archives'),
active: @statut == 'archives',
badge: number_with_html_delimiter(@archives_count))
= render partial: 'header', locals: { procedure: @procedure,
statut: @statut,
a_suivre_count: @a_suivre_count,
suivis_count: @suivis_count,
traites_count: @traites_count,
tous_count: @tous_count,
archives_count: @archives_count,
has_en_cours_notifications: @has_en_cours_notifications,
has_termine_notifications: @has_termine_notifications }
.procedure-actions
= render partial: "download_dossiers", locals: { procedure: @procedure, exports: @exports, dossier_count: @tous_count + @archives_count }

View file

@ -2,4 +2,17 @@
.card-title Routage
%p.notice= t('.notice_html')
= link_to 'Activer le routage', update_routing_enabled_admin_procedure_groupe_instructeurs_path(procedure), class: 'button primary', method: 'patch'
= link_to t('.button.routing_enable'), update_routing_enabled_admin_procedure_groupe_instructeurs_path(procedure), class: 'button primary mt-1', method: 'patch'
.card-title.mt-4 Lautogestion des instructeurs
%p.notice= t('.self_managment_notice_html')
= form_for procedure,
method: :patch,
url: update_instructeurs_self_management_enabled_admin_procedure_groupe_instructeurs_path(procedure),
html: { class: 'form procedure-form__column--form no-background' } do |f|
%label.toggle-switch
= f.check_box :instructeurs_self_management_enabled, class: 'toggle-switch-checkbox', onchange: 'this.form.submit()'
%span.toggle-switch-control.round
%span.toggle-switch-label.on
%span.toggle-switch-label.off

View file

@ -38,4 +38,9 @@ fr:
<br><br>
Cette fonctionnalité permet dacheminer les dossier vers chaque groupe, et de ne plus avoir besoin de filtrer ses dossiers parmi une grande quantité de demandes. Elle est donc particulièrement adaptée pour les démarches nationales instruites localement.
<br><br>
Les instructeurs ne voient que les dossiers les concernant, et nont donc pas accès aux données extérieures à leur périmètre.
Les instructeurs ne voient que les dossiers les concernant, et nont donc pas accès aux données extérieures à leur périmètre.
self_managment_notice_html: |
Lautogestion des instructeurs permet aux instructeurs de gérer eux-mêmes la liste des instructeurs de la démarche.
button:
routing_enable: Activer le routage
self_managment_toggle: Activer lautogestion des instructeurs

View file

@ -424,6 +424,7 @@ Rails.application.routes.draw do
collection do
patch 'update_routing_criteria_name'
patch 'update_routing_enabled'
patch 'update_instructeurs_self_management_enabled'
post 'import'
end
end

View file

@ -0,0 +1,5 @@
class AddInstructeursSelfManagementEnabledToProcedures < ActiveRecord::Migration[6.1]
def change
add_column :procedures, :instructeurs_self_management_enabled, :boolean
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: 2021_09_15_170019) do
ActiveRecord::Schema.define(version: 2021_09_23_083416) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -621,6 +621,7 @@ ActiveRecord::Schema.define(version: 2021_09_15_170019) do
t.string "encrypted_api_particulier_token"
t.text "api_particulier_scopes", default: [], array: true
t.jsonb "api_particulier_sources", default: {}
t.boolean "instructeurs_self_management_enabled"
t.index ["api_particulier_sources"], name: "index_procedures_on_api_particulier_sources", using: :gin
t.boolean "routing_enabled"
t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state"