diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 43522e1d9..e72caa804 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -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 diff --git a/app/controllers/new_administrateur/groupe_instructeurs_controller.rb b/app/controllers/new_administrateur/groupe_instructeurs_controller.rb index 2e28b23c2..a23e4253d 100644 --- a/app/controllers/new_administrateur/groupe_instructeurs_controller.rb +++ b/app/controllers/new_administrateur/groupe_instructeurs_controller.rb @@ -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: "L’autogestion 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 diff --git a/app/helpers/procedure_helper.rb b/app/helpers/procedure_helper.rb index 37799973f..f8ffca559 100644 --- a/app/helpers/procedure_helper.rb +++ b/app/helpers/procedure_helper.rb @@ -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 diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 065cf9721..e74f8f47d 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -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 diff --git a/app/views/instructeurs/groupe_instructeurs/show.html.haml b/app/views/instructeurs/groupe_instructeurs/show.html.haml index f4faaef80..fa7f61c2e 100644 --- a/app/views/instructeurs/groupe_instructeurs/show.html.haml +++ b/app/views/instructeurs/groupe_instructeurs/show.html.haml @@ -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 d’instructeurs', 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 d’instructeurs', 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 l’instructeur « #{instructeur.email} » du groupe « #{@groupe_instructeur.label} » ?" : "Êtes-vous sûr de vouloir retirer l’instructeur « #{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 l’instructeur « #{instructeur.email} » du groupe  « #{@groupe_instructeur.label} » ?" }, + data: { confirm: confirmation_message }, params: { instructeur: { id: instructeur.id }}, class: 'button' } diff --git a/app/views/instructeurs/procedures/_header.html.haml b/app/views/instructeurs/procedures/_header.html.haml new file mode 100644 index 000000000..511273910 --- /dev/null +++ b/app/views/instructeurs/procedures/_header.html.haml @@ -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)) diff --git a/app/views/instructeurs/procedures/deleted_dossiers.html.haml b/app/views/instructeurs/procedures/deleted_dossiers.html.haml index 26d2f0b6f..f49872b1b 100644 --- a/app/views/instructeurs/procedures/deleted_dossiers.html.haml +++ b/app/views/instructeurs/procedures/deleted_dossiers.html.haml @@ -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 diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index fcd6b05e3..15d32e1fb 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -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 } diff --git a/app/views/new_administrateur/groupe_instructeurs/_routing.html.haml b/app/views/new_administrateur/groupe_instructeurs/_routing.html.haml index 1bed0804a..8d01f9fa0 100644 --- a/app/views/new_administrateur/groupe_instructeurs/_routing.html.haml +++ b/app/views/new_administrateur/groupe_instructeurs/_routing.html.haml @@ -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 L‘autogestion 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 diff --git a/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml b/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml index 08104eb30..34605ddcb 100644 --- a/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml +++ b/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml @@ -38,4 +38,9 @@ fr:

Cette fonctionnalité permet d’acheminer 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.

- Les instructeurs ne voient que les dossiers les concernant, et n’ont donc pas accès aux données extérieures à leur périmètre. + Les instructeurs ne voient que les dossiers les concernant, et n’ont donc pas accès aux données extérieures à leur périmètre. + self_managment_notice_html: | + L’autogestion 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 l’autogestion des instructeurs diff --git a/config/routes.rb b/config/routes.rb index e1287641d..dcb922acb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/db/migrate/20210923083416_add_instructeurs_self_management_enabled_to_procedures.rb b/db/migrate/20210923083416_add_instructeurs_self_management_enabled_to_procedures.rb new file mode 100644 index 000000000..5ff29ee5d --- /dev/null +++ b/db/migrate/20210923083416_add_instructeurs_self_management_enabled_to_procedures.rb @@ -0,0 +1,5 @@ +class AddInstructeursSelfManagementEnabledToProcedures < ActiveRecord::Migration[6.1] + def change + add_column :procedures, :instructeurs_self_management_enabled, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index 43760d140..aa9ec0bcd 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.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"